Merge changes I40cf6e7d,Iff515ae2,If8ca1f57,I1eec7a73,Iccb4e72c, ...

* changes:
  Removed line deemed incompatible with Dialer open source.
  Avoid updating system call log cache when the call log is being built
  Make sure we have a host for the search fragment before loading data.
  Fix scroll for new favorites
  UI refresh for bottom nav bar.
  UI refresh for FAB.
  Use ConcurrentMap to log Contacts Provider metrics in the old call log.
  Also ignore IllegalStateException thrown by SQLiteClosable when coalescing fails.
  UI refresh for search fragment.
  Add voicemail greeting setting screen to voicemail settings.
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index f5474ee..485683b 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -100,6 +100,8 @@
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 /** Adapter class to fill in data for the Call Log. */
 public class CallLogAdapter extends GroupingListAdapter
@@ -158,9 +160,12 @@
   /**
    * Maps a raw input number to match info. We only log one MatchInfo per raw input number to reduce
    * the amount of data logged.
+   *
+   * <p>Note that this has to be a {@link ConcurrentMap} as the match info for each row in the UI is
+   * loaded in a background thread spawned when the ViewHolder is bound.
    */
-  private final Map<String, ContactsProviderMatchInfo> contactsProviderMatchInfos =
-      new ArrayMap<>();
+  private final ConcurrentMap<String, ContactsProviderMatchInfo> contactsProviderMatchInfos =
+      new ConcurrentHashMap<>();
 
   private final ActionMode.Callback actionModeCallback =
       new ActionMode.Callback() {
@@ -1464,6 +1469,7 @@
     notifyDataSetChanged();
   }
 
+  @WorkerThread
   private void logCp2Metrics(PhoneCallDetails details, ContactInfo contactInfo) {
     if (details == null) {
       return;
diff --git a/java/com/android/dialer/calllog/CallLogCacheUpdater.java b/java/com/android/dialer/calllog/CallLogCacheUpdater.java
index a7b2b3d..b3130e9 100644
--- a/java/com/android/dialer/calllog/CallLogCacheUpdater.java
+++ b/java/com/android/dialer/calllog/CallLogCacheUpdater.java
@@ -25,6 +25,7 @@
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.support.annotation.VisibleForTesting;
 import com.android.dialer.DialerPhoneNumber;
 import com.android.dialer.NumberAttributes;
 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
@@ -33,6 +34,7 @@
 import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
 import com.android.dialer.inject.ApplicationContext;
 import com.android.dialer.protos.ProtoParsers;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import java.util.ArrayList;
@@ -49,13 +51,23 @@
 
   private final Context appContext;
   private final ListeningExecutorService backgroundExecutor;
+  private final CallLogState callLogState;
+
+  /**
+   * Maximum numbers of operations the updater can do. Each transaction to the system call log will
+   * trigger a call log refresh, so the updater can only do a single batch. If there are more
+   * operations it will be truncated. Under normal circumstances there will only be 1 operation
+   */
+  @VisibleForTesting static final int CACHE_UPDATE_LIMIT = 100;
 
   @Inject
   CallLogCacheUpdater(
       @ApplicationContext Context appContext,
-      @BackgroundExecutor ListeningExecutorService backgroundExecutor) {
+      @BackgroundExecutor ListeningExecutorService backgroundExecutor,
+      CallLogState callLogState) {
     this.appContext = appContext;
     this.backgroundExecutor = backgroundExecutor;
+    this.callLogState = callLogState;
   }
 
   /**
@@ -66,17 +78,27 @@
    * has changed
    */
   public ListenableFuture<Void> updateCache(CallLogMutations mutations) {
-    return backgroundExecutor.submit(
-        () -> {
+    return Futures.transform(
+        callLogState.isBuilt(),
+        isBuilt -> {
+          if (!isBuilt) {
+            // Initial build might need to update 1000 caches, which may overflow the batch
+            // operation limit. The initial data was already built with the cache, there's no need
+            // to update it.
+            LogUtil.i("CallLogCacheUpdater.updateCache", "not updating cache for initial build");
+            return null;
+          }
           updateCacheInternal(mutations);
           return null;
-        });
+        },
+        backgroundExecutor);
   }
 
   private void updateCacheInternal(CallLogMutations mutations) {
     ArrayList<ContentProviderOperation> operations = new ArrayList<>();
     Stream.concat(
             mutations.getInserts().entrySet().stream(), mutations.getUpdates().entrySet().stream())
+        .limit(CACHE_UPDATE_LIMIT)
         .forEach(
             entry -> {
               ContentValues values = entry.getValue();
diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java
index 2ad9f9a..fd751e7 100644
--- a/java/com/android/dialer/calllog/database/Coalescer.java
+++ b/java/com/android/dialer/calllog/database/Coalescer.java
@@ -16,6 +16,7 @@
 package com.android.dialer.calllog.database;
 
 import android.database.Cursor;
+import android.database.StaleDataException;
 import android.provider.CallLog.Calls;
 import android.support.annotation.NonNull;
 import android.support.annotation.WorkerThread;
@@ -85,34 +86,72 @@
   @WorkerThread
   @NonNull
   private ImmutableList<CoalescedRow> coalesceInternal(
-      Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) {
+      Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) throws ExpectedCoalescerException {
     Assert.isWorkerThread();
 
-    if (!allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) {
-      return ImmutableList.of();
-    }
-
     ImmutableList.Builder<CoalescedRow> coalescedRowListBuilder = new ImmutableList.Builder<>();
 
-    RowCombiner rowCombiner = new RowCombiner(allAnnotatedCallLogRowsSortedByTimestampDesc);
-    rowCombiner.startNewGroup();
-
-    long coalescedRowId = 0;
-    do {
-      boolean isRowMerged = rowCombiner.mergeRow(allAnnotatedCallLogRowsSortedByTimestampDesc);
-
-      if (isRowMerged) {
-        allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext();
+    try {
+      if (!allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) {
+        return ImmutableList.of();
       }
 
-      if (!isRowMerged || allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()) {
-        coalescedRowListBuilder.add(
-            rowCombiner.combine().toBuilder().setId(coalescedRowId++).build());
-        rowCombiner.startNewGroup();
-      }
-    } while (!allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast());
+      RowCombiner rowCombiner = new RowCombiner(allAnnotatedCallLogRowsSortedByTimestampDesc);
+      rowCombiner.startNewGroup();
 
-    return coalescedRowListBuilder.build();
+      long coalescedRowId = 0;
+      do {
+        boolean isRowMerged = rowCombiner.mergeRow(allAnnotatedCallLogRowsSortedByTimestampDesc);
+
+        if (isRowMerged) {
+          allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext();
+        }
+
+        if (!isRowMerged || allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()) {
+          coalescedRowListBuilder.add(
+              rowCombiner.combine().toBuilder().setId(coalescedRowId++).build());
+          rowCombiner.startNewGroup();
+        }
+      } while (!allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast());
+
+      return coalescedRowListBuilder.build();
+
+    } catch (Exception exception) {
+      // Coalescing can fail if cursor "allAnnotatedCallLogRowsSortedByTimestampDesc" is closed by
+      // its loader while the work is still in progress.
+      //
+      // This can happen when the loader restarts and finishes loading data before the coalescing
+      // work is completed.
+      //
+      // This kind of failure doesn't have to crash the app as coalescing will be restarted on the
+      // latest data obtained by the loader. Therefore, we inspect the exception here and throw an
+      // ExpectedCoalescerException if it is the case described above.
+      //
+      // The type of expected exception depends on whether AbstractWindowedCursor#checkPosition() is
+      // called when the cursor is closed.
+      //   (1) If it is called before the cursor is closed, we will get IllegalStateException thrown
+      //       by SQLiteClosable when it attempts to acquire a reference to the database.
+      //   (2) Otherwise, we will get StaleDataException thrown by AbstractWindowedCursor's
+      //       checkPosition() method.
+      //
+      // Note that it would be more accurate to inspect the stack trace to locate the origin of the
+      // exception. However, according to the documentation on Throwable#getStackTrace, "some
+      // virtual machines may, under some circumstances, omit one or more stack frames from the
+      // stack trace". "In the extreme case, a virtual machine that has no stack trace information
+      // concerning this throwable is permitted to return a zero-length array from this method."
+      // Therefore, the best we can do is to inspect the message in the exception.
+      // TODO(linyuh): try to avoid the expected failure.
+      String message = exception.getMessage();
+      if (message != null
+          && ((exception instanceof StaleDataException
+                  && message.startsWith("Attempting to access a closed CursorWindow"))
+              || (exception instanceof IllegalStateException
+                  && message.startsWith("attempt to re-open an already-closed object")))) {
+        throw new ExpectedCoalescerException(exception);
+      }
+
+      throw exception;
+    }
   }
 
   /** Combines rows from {@link AnnotatedCallLog} into a {@link CoalescedRow}. */
@@ -337,4 +376,11 @@
       return dialerPhoneNumberUtil.isMatch(groupPhoneNumber, rowPhoneNumber);
     }
   }
+
+  /** A checked exception thrown when expected failure happens when coalescing is in progress. */
+  public static final class ExpectedCoalescerException extends Exception {
+    ExpectedCoalescerException(Throwable throwable) {
+      super("Expected coalescing exception", throwable);
+    }
+  }
 }
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
index 4141fe7..5e72a1a 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
@@ -17,7 +17,6 @@
 
 import android.app.Activity;
 import android.database.Cursor;
-import android.database.StaleDataException;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
@@ -34,6 +33,7 @@
 import com.android.dialer.calllog.CallLogComponent;
 import com.android.dialer.calllog.RefreshAnnotatedCallLogReceiver;
 import com.android.dialer.calllog.database.CallLogDatabaseComponent;
+import com.android.dialer.calllog.database.Coalescer;
 import com.android.dialer.calllog.model.CoalescedRow;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
@@ -337,16 +337,13 @@
           }
         },
         throwable -> {
-          if (throwable instanceof StaleDataException) {
-            // Coalescing can fail if the cursor passed to Coalescer is closed by the loader while
-            // the work is still in progress.
-            // This can happen when the loader restarts and finishes loading data before the
-            // coalescing work is completed.
-            // This failure doesn't need to be thrown as coalescing will be restarted on the latest
-            // data obtained by the loader.
-            // TODO(linyuh): Also throw an exception if the failure above can be avoided.
-            LogUtil.e("NewCallLogFragment.onLoadFinished", "coalescing failed", throwable);
-          } else {
+          // Coalescing can fail if the cursor passed to Coalescer is closed by the loader while
+          // the work is still in progress.
+          // This can happen when the loader restarts and finishes loading data before the
+          // coalescing work is completed.
+          // This failure is identified by ExpectedCoalescerException and doesn't need to be
+          // thrown as coalescing will be restarted on the latest data obtained by the loader.
+          if (!(throwable instanceof Coalescer.ExpectedCoalescerException)) {
             throw new AssertionError(throwable);
           }
         });
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index d790c68..73bb4f8 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -51,6 +51,7 @@
 import android.view.ActionMode;
 import android.view.DragEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
@@ -334,7 +335,12 @@
             activity.findViewById(R.id.remove_view),
             activity.findViewById(R.id.search_view_container),
             toolbar);
-    speedDialFragmentHost = new MainSpeedDialFragmentHost(toolbar);
+    speedDialFragmentHost =
+        new MainSpeedDialFragmentHost(
+            toolbar,
+            activity.findViewById(R.id.root_layout),
+            activity.findViewById(R.id.coordinator_layout),
+            activity.findViewById(R.id.fragment_container));
 
     lastTabController = new LastTabController(activity, bottomNav, showVoicemailTab);
 
@@ -1255,15 +1261,32 @@
   private static final class MainSpeedDialFragmentHost implements SpeedDialFragment.HostInterface {
 
     private final MainToolbar toolbar;
+    private final ViewGroup rootLayout;
+    private final ViewGroup coordinatorLayout;
+    private final ViewGroup fragmentContainer;
 
-    MainSpeedDialFragmentHost(MainToolbar toolbar) {
+    MainSpeedDialFragmentHost(
+        MainToolbar toolbar,
+        ViewGroup rootLayout,
+        ViewGroup coordinatorLayout,
+        ViewGroup fragmentContainer) {
       this.toolbar = toolbar;
+      this.rootLayout = rootLayout;
+      this.coordinatorLayout = coordinatorLayout;
+      this.fragmentContainer = fragmentContainer;
     }
 
     @Override
     public void setHasFrequents(boolean hasFrequents) {
       toolbar.showClearFrequents(hasFrequents);
     }
+
+    @Override
+    public void dragFavorite(boolean start) {
+      rootLayout.setClipChildren(!start);
+      coordinatorLayout.setClipChildren(!start);
+      fragmentContainer.setClipChildren(!start);
+    }
   }
 
   /**
diff --git a/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java b/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java
index 4794b88..48cfc81 100644
--- a/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java
+++ b/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java
@@ -20,20 +20,18 @@
 import android.content.res.ColorStateList;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.Nullable;
-import android.support.annotation.Px;
 import android.support.annotation.StringRes;
 import android.util.AttributeSet;
 import android.view.View;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 import com.android.dialer.common.Assert;
 import com.android.dialer.configprovider.ConfigProviderComponent;
 import com.android.dialer.theme.base.ThemeComponent;
 
 /** Navigation item in a bottom nav. */
-final class BottomNavItem extends LinearLayout {
+final class BottomNavItem extends RelativeLayout {
 
   private ImageView image;
   private TextView text;
@@ -57,7 +55,7 @@
     int colorId =
         selected
             ? ThemeComponent.get(getContext()).theme().getColorPrimary()
-            : ThemeComponent.get(getContext()).theme().getTextColorSecondary();
+            : ThemeComponent.get(getContext()).theme().getColorIcon();
     image.setImageTintList(ColorStateList.valueOf(colorId));
     text.setTextColor(colorId);
   }
@@ -87,20 +85,6 @@
       }
       notificationBadge.setVisibility(View.VISIBLE);
       notificationBadge.setText(countString);
-
-      @Px int margin;
-      if (countString.length() == 1) {
-        margin = getContext().getResources().getDimensionPixelSize(R.dimen.badge_margin_length_1);
-      } else if (countString.length() == 2) {
-        margin = getContext().getResources().getDimensionPixelSize(R.dimen.badge_margin_length_2);
-      } else {
-        margin = getContext().getResources().getDimensionPixelSize(R.dimen.badge_margin_length_3);
-      }
-
-      FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) image.getLayoutParams();
-      params.setMarginStart(margin);
-      params.setMarginEnd(margin);
-      image.setLayoutParams(params);
     }
   }
 }
diff --git a/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml b/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml
index 65bc8f9..e02d7c4 100644
--- a/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml
+++ b/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml
@@ -16,8 +16,6 @@
   -->
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-  <solid android:color="?android:attr/colorPrimary"/>
-  <corners android:radius="20dp"/>
-  <stroke android:color="?android:attr/colorBackgroundFloating" android:width="2dp"/>
+    android:shape="oval">
+  <solid android:color="@color/dialer_red"/>
 </shape>
\ No newline at end of file
diff --git a/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml b/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml
index 02874a9..8c0705f 100644
--- a/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml
+++ b/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml
@@ -16,49 +16,41 @@
   -->
 <com.android.dialer.main.impl.bottomnav.BottomNavItem
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:minWidth="80dp"
+    android:background="?android:attr/selectableItemBackgroundBorderless"
     android:minHeight="56dp"
-    android:gravity="center"
-    android:background="?android:attr/selectableItemBackgroundBorderless">
+    android:minWidth="80dp">
 
-  <FrameLayout
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content">
-
-    <ImageView
-        android:id="@+id/bottom_nav_item_image"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
-        android:layout_marginTop="8dp"/>
-
-    <TextView
-        android:id="@+id/notification_badge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="top|end"
-        android:layout_marginTop="2dp"
-        android:paddingStart="6dp"
-        android:paddingEnd="6dp"
-        android:paddingBottom="1dp"
-        android:minHeight="20dp"
-        android:minWidth="20dp"
-        android:gravity="center"
-        android:textSize="12sp"
-        android:textColor="?android:attr/textColorPrimaryInverse"
-        android:background="@drawable/notification_badge"
-        android:fontFamily="sans-serif-medium"
-        android:visibility="invisible"/>
-  </FrameLayout>
+  <ImageView
+      android:id="@+id/bottom_nav_item_image"
+      android:layout_width="24dp"
+      android:layout_height="24dp"
+      android:layout_marginTop="8dp"
+      android:layout_alignParentTop="true"
+      android:layout_centerHorizontal="true"/>
 
   <TextView
+      android:id="@+id/notification_badge"
+      style="@style/Dialer.TextAppearance.OVERLINE"
+      android:layout_width="16dp"
+      android:layout_height="16dp"
+      android:layout_marginTop="2dp"
+      android:layout_marginStart="-8dp"
+      android:layout_alignParentTop="true"
+      android:layout_toEndOf="@id/bottom_nav_item_image"
+      android:background="@drawable/notification_badge"
+      android:gravity="center"
+      android:textColor="?android:attr/colorBackgroundFloating"
+      android:textSize="11dp"
+      android:visibility="invisible"/>
+  <TextView
       android:id="@+id/bottom_nav_item_text"
+      style="@style/Dialer.TextAppearance.SubHeader2"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginBottom="8dp"
-      android:gravity="center_horizontal"
-      android:textSize="12sp"
-      style="@style/Dialer.TextAppearance.Secondary"/>
+      android:layout_below="@id/bottom_nav_item_image"
+      android:layout_centerHorizontal="true"
+      android:gravity="center_horizontal"/>
 </com.android.dialer.main.impl.bottomnav.BottomNavItem>
\ No newline at end of file
diff --git a/java/com/android/dialer/main/impl/bottomnav/res/values/dimens.xml b/java/com/android/dialer/main/impl/bottomnav/res/values/dimens.xml
deleted file mode 100644
index 8fd376b..0000000
--- a/java/com/android/dialer/main/impl/bottomnav/res/values/dimens.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
-  -->
-<resources>
-  <dimen name="badge_margin_length_1">10dp</dimen>
-  <dimen name="badge_margin_length_2">14dp</dimen>
-  <dimen name="badge_margin_length_3">22dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml
index 5cb457e..5fd9bed 100644
--- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml
+++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml
@@ -19,9 +19,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/root_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false"
-    android:clipToPadding="false">
+    android:layout_height="match_parent">
 
   <!-- MainToolbar -->
   <include
@@ -35,17 +33,13 @@
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_below="@+id/toolbar"
-      android:layout_above="@+id/bottom_nav_bar"
-      android:clipChildren="false"
-      android:clipToPadding="false">
+      android:layout_above="@+id/bottom_nav_bar">
 
     <!-- Holds SpeedDial, Call Log, Contacts, Voicemail and Search fragments -->
     <FrameLayout
         android:id="@+id/fragment_container"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clipChildren="false"
-        android:clipToPadding="false"/>
+        android:layout_height="match_parent"/>
 
     <FrameLayout
         android:id="@+id/search_fragment_container"
@@ -64,7 +58,7 @@
         android:id="@+id/fab"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_margin="16dp"
+        android:layout_margin="24dp"
         android:layout_gravity="end|bottom"
         android:src="@drawable/quantum_ic_dialpad_white_24"
         android:contentDescription="@string/dialpad_button_content_description"
@@ -102,4 +96,4 @@
         android:importantForAccessibility="no"
         android:visibility="gone"/>
   </FrameLayout>
-</RelativeLayout>
\ No newline at end of file
+</RelativeLayout>
diff --git a/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml b/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml
index e5b72f2..9ae884d 100644
--- a/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml
+++ b/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml
@@ -29,7 +29,7 @@
       android:background="?attr/selectableItemBackgroundBorderless"
       android:contentDescription="@string/action_menu_back_from_search"
       android:src="@drawable/quantum_ic_arrow_back_vd_theme_24"
-      android:tint="?android:attr/colorPrimary"/>
+      android:tint="?colorIcon"/>
 
   <EditText
       android:id="@+id/search_view"
@@ -45,10 +45,9 @@
       android:inputType="textFilter"
       android:maxLines="1"
       android:hint="@string/dialer_hint_find_contact"
-      android:textColor="?android:attr/textColorSecondary"
       android:textColorHint="?android:attr/textColorHint"
       android:textCursorDrawable="@drawable/custom_cursor"
-      android:textSize="16sp"/>
+      style="@style/Dialer.TextAppearance.Primary"/>
 
   <ImageView
       android:id="@+id/search_clear_button"
diff --git a/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml b/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml
index 4f8e305..08d2baa 100644
--- a/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml
+++ b/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml
@@ -19,8 +19,8 @@
     android:orientation="horizontal"
     android:layout_width="match_parent"
     android:layout_height="@dimen/search_row_height"
-    android:paddingStart="8dp"
-    android:paddingEnd="8dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
     android:background="?android:attr/selectableItemBackground">
 
   <QuickContactBadge
@@ -44,7 +44,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:gravity="center_vertical|start"
-        android:fontFamily="sans-serif"
         style="@style/Dialer.TextAppearance.Primary"/>
 
     <com.android.dialer.widget.BidiTextView
@@ -52,7 +51,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:gravity="center_vertical|start"
-        android:fontFamily="sans-serif"
         style="@style/Dialer.TextAppearance.Secondary"/>
   </LinearLayout>
 
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index 65ce873..809f917 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -121,11 +121,23 @@
   // the contacts in them).
   private final List<Directory> directories = new ArrayList<>();
   private final Runnable loaderCp2ContactsRunnable =
-      () -> getLoaderManager().restartLoader(CONTACTS_LOADER_ID, null, this);
+      () -> {
+        if (getHost() != null) {
+          getLoaderManager().restartLoader(CONTACTS_LOADER_ID, null, this);
+        }
+      };
   private final Runnable loadNearbyPlacesRunnable =
-      () -> getLoaderManager().restartLoader(NEARBY_PLACES_LOADER_ID, null, this);
+      () -> {
+        if (getHost() != null) {
+          getLoaderManager().restartLoader(NEARBY_PLACES_LOADER_ID, null, this);
+        }
+      };
   private final Runnable loadDirectoryContactsRunnable =
-      () -> getLoaderManager().restartLoader(DIRECTORY_CONTACTS_LOADER_ID, null, this);
+      () -> {
+        if (getHost() != null) {
+          getLoaderManager().restartLoader(DIRECTORY_CONTACTS_LOADER_ID, null, this);
+        }
+      };
   private final Runnable capabilitiesUpdatedRunnable = () -> adapter.notifyDataSetChanged();
 
   private Runnable updatePositionRunnable;
diff --git a/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml b/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml
index ff59206..16f3701 100644
--- a/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml
+++ b/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml
@@ -27,5 +27,5 @@
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_vertical"
-      style="@style/Dialer.TextAppearance.Secondary.Ellipsize"/>
+      style="@style/Dialer.TextAppearance.OVERLINE.Ellipsize"/>
 </FrameLayout>
diff --git a/java/com/android/dialer/speeddial/SpeedDialAdapter.java b/java/com/android/dialer/speeddial/SpeedDialAdapter.java
index ff52a07..4a48b65 100644
--- a/java/com/android/dialer/speeddial/SpeedDialAdapter.java
+++ b/java/com/android/dialer/speeddial/SpeedDialAdapter.java
@@ -34,6 +34,7 @@
 import com.android.dialer.common.Assert;
 import com.android.dialer.speeddial.FavoritesViewHolder.FavoriteContactsListener;
 import com.android.dialer.speeddial.HeaderViewHolder.SpeedDialHeaderListener;
+import com.android.dialer.speeddial.SpeedDialFragment.HostInterface;
 import com.android.dialer.speeddial.SuggestionViewHolder.SuggestedContactsListener;
 import com.android.dialer.speeddial.draghelper.SpeedDialItemTouchHelperCallback.ItemTouchHelperAdapter;
 import com.android.dialer.speeddial.loader.SpeedDialUiItem;
@@ -81,6 +82,7 @@
   private final FavoriteContactsListener favoritesListener;
   private final SuggestedContactsListener suggestedListener;
   private final SpeedDialHeaderListener headerListener;
+  private final HostInterface hostInterface;
 
   private final Map<Integer, Integer> positionToRowTypeMap = new ArrayMap<>();
   private List<SpeedDialUiItem> speedDialUiItems;
@@ -95,11 +97,13 @@
       Context context,
       FavoriteContactsListener favoritesListener,
       SuggestedContactsListener suggestedListener,
-      SpeedDialHeaderListener headerListener) {
+      SpeedDialHeaderListener headerListener,
+      HostInterface hostInterface) {
     this.context = context;
     this.favoritesListener = favoritesListener;
     this.suggestedListener = suggestedListener;
     this.headerListener = headerListener;
+    this.hostInterface = hostInterface;
   }
 
   @Override
@@ -255,6 +259,7 @@
         if (viewHolder != null) {
           draggingFavoritesViewHolder = (FavoritesViewHolder) viewHolder;
           draggingFavoritesViewHolder.onSelectedChanged(true);
+          hostInterface.dragFavorite(true);
           removeViewHolder.show();
         }
         break;
@@ -263,6 +268,7 @@
         if (draggingFavoritesViewHolder != null) {
           draggingFavoritesViewHolder.onSelectedChanged(false);
           draggingFavoritesViewHolder = null;
+          hostInterface.dragFavorite(false);
           removeViewHolder.hide();
         }
         break;
diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java
index a958d44..d4e7a76 100644
--- a/java/com/android/dialer/speeddial/SpeedDialFragment.java
+++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java
@@ -156,7 +156,12 @@
             new UpdateSpeedDialAdapterListener(),
             speedDialLoaderListener);
     adapter =
-        new SpeedDialAdapter(getContext(), favoritesListener, suggestedListener, headerListener);
+        new SpeedDialAdapter(
+            getContext(),
+            favoritesListener,
+            suggestedListener,
+            headerListener,
+            FragmentUtils.getParentUnsafe(this, HostInterface.class));
     layoutManager.setSpanSizeLookup(adapter.getSpanSizeLookup());
     RecyclerView recyclerView = rootLayout.findViewById(R.id.speed_dial_recycler_view);
     recyclerView.setLayoutManager(layoutManager);
@@ -653,5 +658,7 @@
   public interface HostInterface {
 
     void setHasFrequents(boolean hasFrequents);
+
+    void dragFavorite(boolean start);
   }
 }
diff --git a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml
index 472f9e9..e79bc6b 100644
--- a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml
+++ b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml
@@ -17,9 +17,7 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/speed_dial_root"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false"
-    android:clipToPadding="false">
+    android:layout_height="match_parent">
 
   <android.support.v7.widget.RecyclerView
       android:id="@+id/speed_dial_recycler_view"
diff --git a/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml b/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml
index d03a96b..d2cc0fc 100644
--- a/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml
+++ b/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml
@@ -51,8 +51,8 @@
     <item name="colorPrimary">@color/dialer_dark_theme_color</item>
     <item name="android:colorPrimaryDark">@color/dialer_dark_theme_color_dark</item>
     <item name="colorPrimaryDark">@color/dialer_dark_theme_color_dark</item>
-    <item name="android:colorAccent">@color/dialer_dark_secondary_color</item>
-    <item name="colorAccent">@color/dialer_dark_secondary_color</item>
+    <item name="android:colorAccent">@color/dialer_dark_theme_color</item>
+    <item name="colorAccent">@color/dialer_dark_theme_color</item>
 
     <!-- Used to automatically style check/selected checkbox, switches and radio buttons -->
     <item name="colorControlActivated">?android:attr/colorPrimary</item>
diff --git a/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml b/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml
index 8aa87df..69ecba4 100644
--- a/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml
+++ b/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml
@@ -57,8 +57,8 @@
     <item name="colorPrimary">@color/dialer_theme_color</item>
     <item name="android:colorPrimaryDark">@color/dialer_theme_color_dark</item>
     <item name="colorPrimaryDark">@color/dialer_theme_color_dark</item>
-    <item name="android:colorAccent">@color/dialer_secondary_color</item>
-    <item name="colorAccent">@color/dialer_secondary_color</item>
+    <item name="android:colorAccent">@color/dialer_theme_color</item>
+    <item name="colorAccent">@color/dialer_theme_color</item>
 
     <!-- Used to automatically style check/selected checkbox, switches and radio buttons -->
     <item name="colorControlActivated">?android:attr/colorPrimary</item>
diff --git a/java/com/android/dialer/theme/common/res/values/colors.xml b/java/com/android/dialer/theme/common/res/values/colors.xml
index 207d29c..0af550f 100644
--- a/java/com/android/dialer/theme/common/res/values/colors.xml
+++ b/java/com/android/dialer/theme/common/res/values/colors.xml
@@ -27,7 +27,7 @@
   <color name="notification_action_dismiss">#A52714</color>
   <color name="notification_action_answer_video">#097138</color>
 
-  <color name="dialer_red">#C53929</color>
+  <color name="dialer_red">#EA4335</color>
 
   <!-- Legacy -->
   <color name="blue_grey_100">#CFD8DC</color>
diff --git a/java/com/android/dialer/theme/common/res/values/text_styles.xml b/java/com/android/dialer/theme/common/res/values/text_styles.xml
index df5dafa..1f2d6c7 100644
--- a/java/com/android/dialer/theme/common/res/values/text_styles.xml
+++ b/java/com/android/dialer/theme/common/res/values/text_styles.xml
@@ -37,6 +37,12 @@
     <item name="android:fontFamily">sans-serif-medium</item>
   </style>
 
+  <style name="Dialer.TextAppearance.SubHeader2" parent="TextAppearance.AppCompat">
+    <item name="android:textColor">?android:attr/textColorSecondary</item>
+    <item name="android:textSize">14sp</item>
+    <item name="android:fontFamily">sans-serif-medium</item>
+  </style>
+
   <style name="Dialer.TextAppearance.Primary" parent="TextAppearance.AppCompat">
     <item name="android:textColor">?android:attr/textColorPrimary</item>
     <item name="android:textSize">16sp</item>
diff --git a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml
index e48474e..41c5fd1 100644
--- a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml
+++ b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml
@@ -18,5 +18,4 @@
   <color name="dialer_dark_theme_color">#5195EA</color>
   <color name="dialer_dark_theme_color_20pct">#335195EA</color>
   <color name="dialer_dark_theme_color_dark">#2374CE</color>
-  <color name="dialer_dark_secondary_color">#5195EA</color>
 </resources>
diff --git a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml
index 4621be1..ec2f262 100644
--- a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml
+++ b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml
@@ -18,5 +18,4 @@
   <color name="dialer_theme_color">@color/google_blue_600</color>
   <color name="dialer_theme_color_20pct">#332A56C6</color>
   <color name="dialer_theme_color_dark">#1C3AA9</color>
-  <color name="dialer_secondary_color">#F50057</color>
 </resources>
diff --git a/java/com/android/dialer/voicemail/settings/AndroidManifest.xml b/java/com/android/dialer/voicemail/settings/AndroidManifest.xml
index 71a70da..8506ddd 100644
--- a/java/com/android/dialer/voicemail/settings/AndroidManifest.xml
+++ b/java/com/android/dialer/voicemail/settings/AndroidManifest.xml
@@ -13,12 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.dialer.voicemail.settings">
 
   <application>
-
     <!-- Causes the "Voicemail" item under "Calls" setting to be hidden. The voicemail module will
     be handling the settings. Has no effect before OC where dialer cannot provide voicemail
     settings -->
@@ -43,7 +41,13 @@
         android:parentActivityName="com.android.dialer.app.settings.DialerSettingsActivity"
         android:theme="@style/SettingsStyle">
     </activity>
-    <activity android:name=".CurrentVoicemailGreetingActivity">
+    <activity
+        android:name=".CurrentVoicemailGreetingActivity"
+        android:label="@string/voicemail_change_greeting_preference_title"
+        android:parentActivityName="com.android.dialer.app.settings.DialerSettingsActivity"
+        android:exported="true">
+    <!-- TODO(a bug): delete android:exported="true" closer to submitting  -->
     </activity>
   </application>
+
 </manifest>
diff --git a/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java b/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java
index 2b6f27b..ff7ae97 100644
--- a/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java
+++ b/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java
@@ -16,15 +16,154 @@
 
 package com.android.dialer.voicemail.settings;
 
+import android.Manifest;
 import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.MediaPlayer;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.widget.DialerToolbar;
+import java.io.IOException;
+import java.util.Locale;
 
 /** Activity to display current voicemail greeting and allow user to navigate to record a new one */
 public class CurrentVoicemailGreetingActivity extends Activity {
+  public static final String VOICEMAIL_GREETING_FILEPATH_KEY = "canonVoicemailGreetingFilePathKey";
+
+  private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200;
+
+  private boolean permissionToRecordAccepted = false;
+
+  private ImageButton changeGreetingButton;
+  private ImageButton playButton;
+
+  private DialerToolbar currentVoicemailGreetingDialerToolbar;
+
+  private int greetingDuration = -1;
+
+  private MediaPlayer mediaPlayer;
+
+  private TextView playbackProgressLabel;
+  private View playbackDisplay;
+
+  private String voicemailGreetingFilePath = "";
 
   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_current_voicemail_greeting);
+
+    playbackDisplay = findViewById(R.id.current_voicemail_greeting_recording_display);
+    playbackProgressLabel = (TextView) findViewById(R.id.playback_progress_text_view);
+    currentVoicemailGreetingDialerToolbar = (DialerToolbar) findViewById(R.id.toolbar);
+
+    currentVoicemailGreetingDialerToolbar.setTitle(
+        R.string.voicemail_change_greeting_preference_title);
+
+    changeGreetingButton = (ImageButton) findViewById(R.id.change_greeting_button);
+    changeGreetingButton.setOnClickListener(
+        new OnClickListener() {
+          @Override
+          public void onClick(View v) {
+            // TODO(sabowitz): Implement this in CL child beta01.
+          }
+        });
+
+    playButton = (ImageButton) findViewById(R.id.play_button);
+    playButton.setOnClickListener(
+        new OnClickListener() {
+          @Override
+          public void onClick(View v) {
+            // TODO(sabowitz): Finish implementing this in CL child beta02.
+          }
+        });
+
+    displayCurrentVoicemailGreetingStatus();
+  }
+
+  @Override
+  public void onStart() {
+    ActivityCompat.requestPermissions(
+        this, new String[] {Manifest.permission.RECORD_AUDIO}, REQUEST_RECORD_AUDIO_PERMISSION);
+
+    if (isGreetingRecorded()) {
+      mediaPlayer = new MediaPlayer();
+      try {
+        mediaPlayer.setDataSource(voicemailGreetingFilePath);
+        mediaPlayer.prepare();
+      } catch (IOException e) {
+        LogUtil.e("CurrentVoicemailGreetingActivity.onStart", "mediaPlayer setup failed.");
+      }
+    }
+    super.onStart();
+  }
+
+  @Override
+  public void onPause() {
+    if (isGreetingRecorded()) {
+      if (mediaPlayer.isPlaying()) {
+        mediaPlayer.release();
+        mediaPlayer = null;
+      }
+    }
+    super.onPause();
+  }
+
+  @Override
+  public void onRequestPermissionsResult(
+      int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+    if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
+      permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
+    }
+    if (!permissionToRecordAccepted) {
+      LogUtil.w(
+          "CurrentVoicemailGreetingActivity.onRequestPermissionsResult",
+          "permissionToRecordAccepted = false.");
+      // TODO(sabowitz): Implement error dialog logic in a child CL.
+    }
+  }
+
+  private boolean isGreetingRecorded() {
+    Intent intent = getIntent();
+    if (intent.hasExtra(VOICEMAIL_GREETING_FILEPATH_KEY)) {
+      String filePathProxy = intent.getStringExtra(VOICEMAIL_GREETING_FILEPATH_KEY);
+      if (filePathProxy == null || filePathProxy.length() == 0) {
+        return false;
+      }
+      if (mediaPlayer == null) {
+        mediaPlayer = new MediaPlayer();
+      }
+      try {
+        mediaPlayer.setDataSource(filePathProxy);
+        int durationProxy = mediaPlayer.getDuration();
+        greetingDuration = durationProxy;
+        voicemailGreetingFilePath = filePathProxy;
+        mediaPlayer = null;
+        return true;
+      } catch (IOException e) {
+        LogUtil.e("CurrentVoicemailGreetingActivity.isGreetingRecorded", "bad filepath.");
+        mediaPlayer = null;
+        return false;
+      }
+    }
+    return false;
+  }
+
+  private void displayCurrentVoicemailGreetingStatus() {
+    if (isGreetingRecorded()) {
+      String durationLabel = String.format(Locale.US, "00:%d", greetingDuration);
+      playbackProgressLabel.setText(durationLabel);
+    } else {
+      playbackDisplay.setVisibility(View.GONE);
+    }
   }
 }
diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_arrow_back_grey600_48dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_arrow_back_grey600_48dp.png
new file mode 100644
index 0000000..0a379b4
--- /dev/null
+++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_arrow_back_grey600_48dp.png
Binary files differ
diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_circles_add_googblue_48dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_circles_add_googblue_48dp.png
new file mode 100644
index 0000000..5ae5230
--- /dev/null
+++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_circles_add_googblue_48dp.png
Binary files differ
diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_play_circle_filled_googblue_48dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_play_circle_filled_googblue_48dp.png
new file mode 100644
index 0000000..0657758
--- /dev/null
+++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_play_circle_filled_googblue_48dp.png
Binary files differ
diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_stop_circle_filled_blue_24dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_stop_circle_filled_blue_24dp.png
new file mode 100644
index 0000000..520f860
--- /dev/null
+++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_stop_circle_filled_blue_24dp.png
Binary files differ
diff --git a/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml b/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml
index 81d175a..3e90cf7 100644
--- a/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml
+++ b/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml
@@ -21,4 +21,107 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context="com.android.dialer.voicemail.settings.CurrentVoicemailGreetingActivity">
+  <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+      android:layout_alignParentTop="true"
+      android:layout_centerHorizontal="true"
+      android:orientation="vertical">
+    <com.android.dialer.widget.DialerToolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:title="@string/voicemail_change_greeting_preference_title">
+    </com.android.dialer.widget.DialerToolbar>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/dialer_divider_line_color"
+        />
+
+    <!-- Change Greeting Panel -->
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="72dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="7dp"
+        android:orientation="horizontal"
+        android:visibility="visible">
+
+        <!-- Change Greeting Button -->
+      <ImageButton
+          android:id="@+id/change_greeting_button"
+          style="@android:style/Widget.Material.Light.ImageButton"
+          android:layout_width="40dp"
+          android:layout_height="40dp"
+          android:layout_marginStart="16dp"
+          android:layout_gravity="center_vertical"
+          android:background="?android:attr/colorBackground"
+          android:foregroundGravity="center_vertical"
+          android:scaleType="centerCrop"
+          android:src="@drawable/ic_circles_add_googblue_48dp"/>
+
+      <TextView
+          android:id="@+id/textView"
+          android:layout_width="0dp"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"
+          android:layout_marginStart="17dp"
+          android:layout_gravity="center_vertical"
+          android:text="@string/current_voicemail_greeting_record_instruction"
+          style="@style/Dialer.TextAppearance.Primary"/>
+
+    </LinearLayout>
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/dialer_divider_line_color"
+        />
+    <LinearLayout
+        android:id="@+id/current_voicemail_greeting_recording_display"
+        android:layout_width="match_parent"
+        android:layout_height="72dp"
+        android:background="?android:attr/colorBackground"
+        android:orientation="horizontal">
+        <!-- Play Button -->
+      <ImageButton
+          android:id="@+id/play_button"
+          style="@android:style/Widget.Material.Light.ImageButton"
+          android:layout_width="40dp"
+          android:layout_height="40dp"
+          android:layout_marginStart="16dp"
+          android:layout_gravity="center_vertical"
+          android:adjustViewBounds="false"
+          android:background="?android:attr/colorBackground"
+          android:cropToPadding="false"
+          android:scaleType="centerCrop"
+          android:src="@drawable/ic_play_circle_filled_googblue_48dp"/>
+
+      <LinearLayout
+          android:layout_width="232dp"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"
+          android:layout_marginStart="16dp"
+          android:layout_gravity="center_vertical"
+          android:orientation="vertical">
+        <TextView
+            android:id="@+id/current_voicemail_greeting_recording_title_textview"
+            style="@style/Dialer.TextAppearance.Primary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/current_voicemail_greeting_recording_title"/>
+        <TextView
+            android:id="@+id/playback_progress_text_view"
+            style="@style/Dialer.TextAppearance.Secondary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+      </LinearLayout>
+    </LinearLayout>
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/dialer_divider_line_color"
+        />
+  </LinearLayout>
 </RelativeLayout>
diff --git a/java/com/android/dialer/voicemail/settings/res/values/strings.xml b/java/com/android/dialer/voicemail/settings/res/values/strings.xml
index 14793fd..971f37a 100644
--- a/java/com/android/dialer/voicemail/settings/res/values/strings.xml
+++ b/java/com/android/dialer/voicemail/settings/res/values/strings.xml
@@ -36,6 +36,12 @@
   <!-- Title for changing voicemail greeting activity [CHAR LIMIT=40] -->
   <string name="voicemail_change_greeting_preference_title">Voicemail greeting</string>
 
+  <!-- Text instruction shown on the current voicemail greeting display screen [CHAR LIMIT=20] -->
+  <string name="current_voicemail_greeting_record_instruction">Record a greeting</string>
+
+  <!-- Title for voicemail greeting, if one is already recorded. -->
+  <string name="current_voicemail_greeting_recording_title">My voicemail greeting</string>
+
   <!-- Text shown on the record voicemail activity [CHAR LIMIT=20] -->
   <string name="change_greeting_text">Tap to Record</string>