Snap for 4625912 from a69ac08a9ecdd27094bf062e160f3a451841bc6c to pi-release

Change-Id: Iac7e3688606695fefac1a4e683c060d0628df2cf
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0653fe4..164dbc9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -16,8 +16,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   coreApp="true"
   package="com.android.dialer"
-  android:versionCode="240000"
-  android:versionName="18.0">
+  android:versionCode="250000"
+  android:versionName="19.0">
 
   <uses-sdk
     android:minSdkVersion="23"
diff --git a/java/com/android/contacts/common/ContactsUtils.java b/java/com/android/contacts/common/ContactsUtils.java
index bc0e423..bca8b62 100644
--- a/java/com/android/contacts/common/ContactsUtils.java
+++ b/java/com/android/contacts/common/ContactsUtils.java
@@ -18,7 +18,7 @@
 
 import android.provider.ContactsContract.Contacts;
 import android.support.annotation.IntDef;
-import com.android.contacts.common.compat.DirectoryCompat;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
diff --git a/java/com/android/contacts/common/list/ContactEntryListAdapter.java b/java/com/android/contacts/common/list/ContactEntryListAdapter.java
index 117825d..413a1de 100644
--- a/java/com/android/contacts/common/list/ContactEntryListAdapter.java
+++ b/java/com/android/contacts/common/list/ContactEntryListAdapter.java
@@ -34,9 +34,9 @@
 import android.widget.TextView;
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.R;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.contacts.common.util.SearchUtil;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.compat.CompatUtils;
 import com.android.dialer.configprovider.ConfigProviderBindings;
 import com.android.dialer.contactphoto.ContactPhotoManager;
diff --git a/java/com/android/contacts/common/list/DirectoryListLoader.java b/java/com/android/contacts/common/list/DirectoryListLoader.java
index be62cc7..ce78d2c 100644
--- a/java/com/android/contacts/common/list/DirectoryListLoader.java
+++ b/java/com/android/contacts/common/list/DirectoryListLoader.java
@@ -26,8 +26,8 @@
 import android.provider.ContactsContract.Directory;
 import android.text.TextUtils;
 import com.android.contacts.common.R;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.util.PermissionsUtil;
 
 /** A specialized loader for the list of directories, see {@link Directory}. */
diff --git a/java/com/android/contacts/common/list/PhoneNumberListAdapter.java b/java/com/android/contacts/common/list/PhoneNumberListAdapter.java
index 58628d2..3c45abf 100644
--- a/java/com/android/contacts/common/list/PhoneNumberListAdapter.java
+++ b/java/com/android/contacts/common/list/PhoneNumberListAdapter.java
@@ -34,13 +34,13 @@
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.R;
 import com.android.contacts.common.compat.CallableCompat;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.contacts.common.compat.PhoneCompat;
 import com.android.contacts.common.extensions.PhoneDirectoryExtenderAccessor;
 import com.android.contacts.common.list.ContactListItemView.CallToAction;
 import com.android.contacts.common.preference.ContactsPreferences;
 import com.android.contacts.common.util.Constants;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.compat.CompatUtils;
 import com.android.dialer.configprovider.ConfigProviderBindings;
 import com.android.dialer.contactphoto.ContactPhotoManager.DefaultImageRequest;
diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java
index dd1d98c..11c2499 100644
--- a/java/com/android/dialer/app/calllog/CallLogFragment.java
+++ b/java/com/android/dialer/app/calllog/CallLogFragment.java
@@ -583,7 +583,7 @@
     } else if (!isCallLogActivity) {
       LogUtil.i("CallLogFragment.onEmptyViewActionButtonClicked", "showing dialpad");
       // Show dialpad if we are not in the call log activity.
-      ((HostInterface) activity).showDialpad();
+      FragmentUtils.getParentUnsafe(this, HostInterface.class).showDialpad();
     }
   }
 
@@ -626,7 +626,7 @@
   @CallSuper
   public void onVisible() {
     LogUtil.enterBlock("CallLogFragment.onPageSelected");
-    if (getActivity() != null && getActivity() instanceof HostInterface) {
+    if (getActivity() != null && FragmentUtils.getParent(this, HostInterface.class) != null) {
       FragmentUtils.getParentUnsafe(this, HostInterface.class)
           .enableFloatingButton(!isModalAlertVisible());
     }
diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java
index 8b50473..f1ede89 100644
--- a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java
+++ b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java
@@ -158,7 +158,7 @@
   public void onVisible() {
     LogUtil.enterBlock("VisualVoicemailCallLogFragment.onVisible");
     super.onVisible();
-    if (getActivity() != null) {
+    if (getActivity() != null && preSyncVoicemailStatusCheckExecutor != null) {
       preSyncVoicemailStatusCheckExecutor.executeParallel(getActivity());
       Logger.get(getActivity()).logImpression(DialerImpression.Type.VVM_TAB_VIEWED);
       getActivity().setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM);
diff --git a/java/com/android/dialer/app/list/RegularSearchListAdapter.java b/java/com/android/dialer/app/list/RegularSearchListAdapter.java
index aee68ae..c92f48c 100644
--- a/java/com/android/dialer/app/list/RegularSearchListAdapter.java
+++ b/java/com/android/dialer/app/list/RegularSearchListAdapter.java
@@ -20,8 +20,8 @@
 import android.net.Uri;
 import android.text.TextUtils;
 import com.android.contacts.common.ContactsUtils;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.contacts.common.list.DirectoryPartition;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.phonenumbercache.CachedNumberLookupService;
 import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo;
 import com.android.dialer.phonenumbercache.ContactInfo;
diff --git a/java/com/android/dialer/binary/google/AndroidManifest.xml b/java/com/android/dialer/binary/google/AndroidManifest.xml
index f7c5643..c1f1a59 100644
--- a/java/com/android/dialer/binary/google/AndroidManifest.xml
+++ b/java/com/android/dialer/binary/google/AndroidManifest.xml
@@ -16,8 +16,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   coreApp="true"
   package="com.google.android.google_stub_dialer"
-  android:versionCode="240000"
-  android:versionName="18.0">
+  android:versionCode="250000"
+  android:versionName="19.0">
 
   <uses-sdk
     android:minSdkVersion="23"
diff --git a/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogNotifier.java b/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogNotifier.java
index fd6a807..fd81568 100644
--- a/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogNotifier.java
+++ b/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogNotifier.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.support.v4.content.LocalBroadcastManager;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.logging.ReportingLocation;
 
 /**
  * Notifies that a dialog for blocking a number and/or marking it as spam/not spam should be shown.
@@ -35,9 +36,15 @@
    * @param normalizedNumber The number to be blocked/marked as spam
    * @param countryIso The ISO 3166-1 two letters country code for the number
    * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+   * @param reportingLocation The location where the number is reported. See {@link
+   *     ReportingLocation.Type}.
    */
   public static void notifyShowDialogToBlockNumberAndOptionallyReportSpam(
-      Context context, String normalizedNumber, String countryIso, int callType) {
+      Context context,
+      String normalizedNumber,
+      String countryIso,
+      int callType,
+      ReportingLocation.Type reportingLocation) {
     LogUtil.enterBlock(
         "ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam");
 
@@ -49,6 +56,8 @@
     intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_NUMBER, normalizedNumber);
     intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_COUNTRY_ISO, countryIso);
     intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_CALL_TYPE, callType);
+    intent.putExtra(
+        ShowBlockReportSpamDialogReceiver.EXTRA_REPORTING_LOCATION, reportingLocation.getNumber());
 
     LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
   }
@@ -60,9 +69,15 @@
    * @param normalizedNumber The number to be reported as not spam
    * @param countryIso The ISO 3166-1 two letters country code for the number
    * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+   * @param reportingLocation The location where the number is reported. See {@link
+   *     ReportingLocation.Type}.
    */
   public static void notifyShowDialogToReportNotSpam(
-      Context context, String normalizedNumber, String countryIso, int callType) {
+      Context context,
+      String normalizedNumber,
+      String countryIso,
+      int callType,
+      ReportingLocation.Type reportingLocation) {
     LogUtil.enterBlock("ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam");
 
     Intent intent = new Intent();
@@ -70,6 +85,7 @@
     intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_NUMBER, normalizedNumber);
     intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_COUNTRY_ISO, countryIso);
     intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_CALL_TYPE, callType);
+    intent.putExtra(ShowBlockReportSpamDialogReceiver.EXTRA_REPORTING_LOCATION, reportingLocation);
 
     LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
   }
diff --git a/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java b/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java
index 9642468..75b6241 100644
--- a/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java
+++ b/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java
@@ -46,6 +46,7 @@
   static final String EXTRA_NUMBER = "number";
   static final String EXTRA_COUNTRY_ISO = "country_iso";
   static final String EXTRA_CALL_TYPE = "call_type";
+  static final String EXTRA_REPORTING_LOCATION = "reporting_location";
 
   /** {@link FragmentManager} needed to show a {@link android.app.DialogFragment}. */
   private final FragmentManager fragmentManager;
@@ -87,10 +88,16 @@
     Assert.checkArgument(intent.hasExtra(EXTRA_NUMBER));
     Assert.checkArgument(intent.hasExtra(EXTRA_COUNTRY_ISO));
     Assert.checkArgument(intent.hasExtra(EXTRA_CALL_TYPE));
+    Assert.checkArgument(intent.hasExtra(EXTRA_REPORTING_LOCATION));
 
     String normalizedNumber = intent.getStringExtra(EXTRA_NUMBER);
     String countryIso = intent.getStringExtra(EXTRA_COUNTRY_ISO);
     int callType = intent.getIntExtra(EXTRA_CALL_TYPE, 0);
+    ReportingLocation.Type reportingLocation =
+        ReportingLocation.Type.forNumber(
+            intent.getIntExtra(
+                EXTRA_REPORTING_LOCATION,
+                ReportingLocation.Type.UNKNOWN_REPORTING_LOCATION.getNumber()));
 
     Spam spam = SpamComponent.get(context).spam();
 
@@ -113,7 +120,7 @@
                 normalizedNumber,
                 countryIso,
                 callType,
-                ReportingLocation.Type.UNKNOWN_REPORTING_LOCATION /* TODO(a bug): Fix. */,
+                reportingLocation,
                 ContactSource.Type.UNKNOWN_SOURCE_TYPE /* TODO(a bug): Fix. */);
           }
 
@@ -140,10 +147,16 @@
     Assert.checkArgument(intent.hasExtra(EXTRA_NUMBER));
     Assert.checkArgument(intent.hasExtra(EXTRA_COUNTRY_ISO));
     Assert.checkArgument(intent.hasExtra(EXTRA_CALL_TYPE));
+    Assert.checkArgument(intent.hasExtra(EXTRA_REPORTING_LOCATION));
 
     String normalizedNumber = intent.getStringExtra(EXTRA_NUMBER);
     String countryIso = intent.getStringExtra(EXTRA_COUNTRY_ISO);
     int callType = intent.getIntExtra(EXTRA_CALL_TYPE, 0);
+    ReportingLocation.Type reportingLocation =
+        ReportingLocation.Type.forNumber(
+            intent.getIntExtra(
+                EXTRA_REPORTING_LOCATION,
+                ReportingLocation.Type.UNKNOWN_REPORTING_LOCATION.getNumber()));
 
     // Set up the positive listener for the dialog.
     OnConfirmListener onConfirmListener =
@@ -158,7 +171,7 @@
                 normalizedNumber,
                 countryIso,
                 callType,
-                ReportingLocation.Type.UNKNOWN_REPORTING_LOCATION /* TODO(a bug): Fix. */,
+                reportingLocation,
                 ContactSource.Type.UNKNOWN_SOURCE_TYPE /* TODO(a bug): Fix. */);
           }
         };
diff --git a/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java b/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java
index ac2e3b3..ad5671e 100644
--- a/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java
+++ b/java/com/android/dialer/calllog/ui/menu/DeleteCallLogItemModule.java
@@ -28,13 +28,13 @@
 import com.android.dialer.common.concurrent.DialerExecutor.Worker;
 import com.android.dialer.common.concurrent.DialerExecutorComponent;
 import com.android.dialer.common.database.Selection;
-import com.android.dialer.contactactions.ContactActionModule;
+import com.android.dialer.historyitemactions.HistoryItemActionModule;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 
-/** {@link ContactActionModule} for deleting a call log item in the new call log. */
-public final class DeleteCallLogItemModule implements ContactActionModule {
+/** {@link HistoryItemActionModule} for deleting a call log item in the new call log. */
+public final class DeleteCallLogItemModule implements HistoryItemActionModule {
   private static final String TAG = DeleteCallLogItemModule.class.getName();
 
   private final Context context;
diff --git a/java/com/android/dialer/calllog/ui/menu/Modules.java b/java/com/android/dialer/calllog/ui/menu/Modules.java
index 48de03e..1479727 100644
--- a/java/com/android/dialer/calllog/ui/menu/Modules.java
+++ b/java/com/android/dialer/calllog/ui/menu/Modules.java
@@ -25,35 +25,42 @@
 import com.android.dialer.calllog.model.CoalescedRow;
 import com.android.dialer.calllogutils.CallLogContactTypes;
 import com.android.dialer.calllogutils.PhoneNumberDisplayUtil;
-import com.android.dialer.contactactions.ContactActionModule;
-import com.android.dialer.contactactions.DividerModule;
-import com.android.dialer.contactactions.IntentModule;
-import com.android.dialer.contactactions.SharedModules;
 import com.android.dialer.dialercontact.DialerContact;
+import com.android.dialer.historyitemactions.DividerModule;
+import com.android.dialer.historyitemactions.HistoryItemActionModule;
+import com.android.dialer.historyitemactions.IntentModule;
+import com.android.dialer.historyitemactions.SharedModules;
+import com.android.dialer.logging.ReportingLocation;
 import com.android.dialer.phonenumberutil.PhoneNumberHelper;
 import com.android.dialer.telecom.TelecomUtil;
 import com.google.common.base.Optional;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
  * Configures the modules for the bottom sheet; these are the rows below the top row (primary
  * action) in the bottom sheet.
  */
+@SuppressWarnings("Guava")
 final class Modules {
 
-  static List<ContactActionModule> fromRow(Context context, CoalescedRow row) {
+  static List<HistoryItemActionModule> fromRow(Context context, CoalescedRow row) {
     // Conditionally add each module, which are items in the bottom sheet's menu.
-    List<ContactActionModule> modules = new ArrayList<>();
+    List<HistoryItemActionModule> modules = new ArrayList<>();
 
     String normalizedNumber = row.number().getNormalizedNumber();
     boolean canPlaceCalls =
         PhoneNumberHelper.canPlaceCallsTo(normalizedNumber, row.numberPresentation());
 
     if (canPlaceCalls) {
-      addModuleForCalls(context, modules, row, normalizedNumber);
-      SharedModules.maybeAddModuleForSendingTextMessage(
-          context, modules, normalizedNumber, row.numberAttributes().getIsBlocked());
+      modules.addAll(createModulesForCalls(context, row, normalizedNumber));
+      Optional<HistoryItemActionModule> moduleForSendingTextMessage =
+          SharedModules.createModuleForSendingTextMessage(
+              context, normalizedNumber, row.numberAttributes().getIsBlocked());
+      if (moduleForSendingTextMessage.isPresent()) {
+        modules.add(moduleForSendingTextMessage.get());
+      }
     }
 
     if (!modules.isEmpty()) {
@@ -64,44 +71,52 @@
     // TODO(zachh): Module for CallComposer.
 
     if (canPlaceCalls) {
-      SharedModules.maybeAddModuleForAddingToContacts(
-          context,
-          modules,
-          row.number(),
-          row.numberAttributes().getName(),
-          row.numberAttributes().getLookupUri(),
-          row.numberAttributes().getIsBlocked(),
-          row.numberAttributes().getIsSpam());
-      SharedModules.addModulesHandlingBlockedOrSpamNumber(
-          context,
-          modules,
-          row.number().getNormalizedNumber(),
-          row.number().getCountryIso(),
-          row.callType(),
-          row.numberAttributes().getIsBlocked(),
-          row.numberAttributes().getIsSpam());
-      SharedModules.maybeAddModuleForCopyingNumber(context, modules, normalizedNumber);
+      Optional<HistoryItemActionModule> moduleForAddingToContacts =
+          SharedModules.createModuleForAddingToContacts(
+              context,
+              row.number(),
+              row.numberAttributes().getName(),
+              row.numberAttributes().getLookupUri(),
+              row.numberAttributes().getIsBlocked(),
+              row.numberAttributes().getIsSpam());
+      if (moduleForAddingToContacts.isPresent()) {
+        modules.add(moduleForAddingToContacts.get());
+      }
+
+      modules.addAll(
+          SharedModules.createModulesHandlingBlockedOrSpamNumber(
+              context,
+              row.number().getNormalizedNumber(),
+              row.number().getCountryIso(),
+              row.callType(),
+              row.numberAttributes().getIsBlocked(),
+              row.numberAttributes().getIsSpam(),
+              ReportingLocation.Type.CALL_LOG_HISTORY));
+
+      Optional<HistoryItemActionModule> moduleForCopyingNumber =
+          SharedModules.createModuleForCopyingNumber(context, normalizedNumber);
+      if (moduleForCopyingNumber.isPresent()) {
+        modules.add(moduleForCopyingNumber.get());
+      }
     }
 
     // TODO(zachh): Revisit if DialerContact is the best thing to pass to CallDetails; could
-    // it use a ContactPrimaryActionInfo instead?
-    addModuleForAccessingCallDetails(context, modules, row);
+    // it use a HistoryItemPrimaryActionInfo instead?
+    modules.add(createModuleForAccessingCallDetails(context, row));
 
     modules.add(new DeleteCallLogItemModule(context, row.coalescedIds()));
 
     return modules;
   }
 
-  private static void addModuleForCalls(
-      Context context,
-      List<ContactActionModule> modules,
-      CoalescedRow row,
-      String normalizedNumber) {
+  private static List<HistoryItemActionModule> createModulesForCalls(
+      Context context, CoalescedRow row, String normalizedNumber) {
     // Don't add call options if a number is blocked.
     if (row.numberAttributes().getIsBlocked()) {
-      return;
+      return Collections.emptyList();
     }
 
+    List<HistoryItemActionModule> modules = new ArrayList<>();
     PhoneAccountHandle phoneAccountHandle =
         TelecomUtil.composePhoneAccountHandle(
             row.phoneAccountComponentName(), row.phoneAccountId());
@@ -121,24 +136,25 @@
 
     // TODO(zachh): Also show video option if the call log entry is for an audio call but video
     // capabilities are present?
+
+    return modules;
   }
 
-  private static void addModuleForAccessingCallDetails(
-      Context context, List<ContactActionModule> modules, CoalescedRow row) {
+  private static HistoryItemActionModule createModuleForAccessingCallDetails(
+      Context context, CoalescedRow row) {
     boolean canReportAsInvalidNumber = row.numberAttributes().getCanReportAsInvalidNumber();
     boolean canSupportAssistedDialing = !TextUtils.isEmpty(row.numberAttributes().getLookupUri());
 
-    modules.add(
-        new IntentModule(
+    return new IntentModule(
+        context,
+        CallDetailsActivity.newInstance(
             context,
-            CallDetailsActivity.newInstance(
-                context,
-                row.coalescedIds(),
-                createDialerContactFromRow(context, row),
-                canReportAsInvalidNumber,
-                canSupportAssistedDialing),
-            R.string.call_details_menu_label,
-            R.drawable.quantum_ic_info_outline_vd_theme_24));
+            row.coalescedIds(),
+            createDialerContactFromRow(context, row),
+            canReportAsInvalidNumber,
+            canSupportAssistedDialing),
+        R.string.call_details_menu_label,
+        R.drawable.quantum_ic_info_outline_vd_theme_24);
   }
 
   private static DialerContact createDialerContactFromRow(Context context, CoalescedRow row) {
diff --git a/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java b/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java
index 02724e6..9efe907 100644
--- a/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java
+++ b/java/com/android/dialer/calllog/ui/menu/NewCallLogMenu.java
@@ -22,8 +22,8 @@
 import com.android.dialer.calllog.CallLogComponent;
 import com.android.dialer.calllog.model.CoalescedRow;
 import com.android.dialer.common.concurrent.DefaultFutureCallback;
-import com.android.dialer.contactactions.ContactActionBottomSheet;
 import com.android.dialer.glidephotomanager.GlidePhotoManager;
+import com.android.dialer.historyitemactions.HistoryItemActionBottomSheet;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.MoreExecutors;
 
@@ -34,7 +34,7 @@
   public static View.OnClickListener createOnClickListener(
       Context context, CoalescedRow row, GlidePhotoManager glidePhotoManager) {
     return view -> {
-      ContactActionBottomSheet.show(
+      HistoryItemActionBottomSheet.show(
           context,
           PrimaryAction.fromRow(context, row),
           Modules.fromRow(context, row),
diff --git a/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java b/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java
index 92a8453..de4a70c 100644
--- a/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java
+++ b/java/com/android/dialer/calllog/ui/menu/PrimaryAction.java
@@ -22,14 +22,14 @@
 import com.android.dialer.calllogutils.CallLogEntryText;
 import com.android.dialer.calllogutils.CallLogIntents;
 import com.android.dialer.calllogutils.NumberAttributesConverter;
-import com.android.dialer.contactactions.ContactPrimaryActionInfo;
+import com.android.dialer.historyitemactions.HistoryItemPrimaryActionInfo;
 
 /** Configures the primary action row (top row) for the bottom sheet. */
 final class PrimaryAction {
 
-  static ContactPrimaryActionInfo fromRow(Context context, CoalescedRow row) {
+  static HistoryItemPrimaryActionInfo fromRow(Context context, CoalescedRow row) {
     CharSequence primaryText = CallLogEntryText.buildPrimaryText(context, row);
-    return ContactPrimaryActionInfo.builder()
+    return HistoryItemPrimaryActionInfo.builder()
         .setNumber(row.number())
         .setPhotoInfo(
             NumberAttributesConverter.toPhotoInfoBuilder(row.numberAttributes())
diff --git a/java/com/android/contacts/common/compat/DirectoryCompat.java b/java/com/android/dialer/common/cp2/DirectoryCompat.java
similarity index 90%
rename from java/com/android/contacts/common/compat/DirectoryCompat.java
rename to java/com/android/dialer/common/cp2/DirectoryCompat.java
index e670876..3e33394 100644
--- a/java/com/android/contacts/common/compat/DirectoryCompat.java
+++ b/java/com/android/dialer/common/cp2/DirectoryCompat.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.contacts.common.compat;
+package com.android.dialer.common.cp2;
 
 import android.net.Uri;
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
 import android.provider.ContactsContract.Directory;
 
+/** Compatibility utility for {@link Directory}. */
 public class DirectoryCompat {
 
   public static Uri getContentUri() {
@@ -42,7 +43,7 @@
     if (VERSION.SDK_INT >= VERSION_CODES.N) {
       return Directory.isRemoteDirectoryId(directoryId);
     }
-    return !(directoryId == Directory.DEFAULT || directoryId == Directory.LOCAL_INVISIBLE);
+    return directoryId != Directory.DEFAULT && directoryId != Directory.LOCAL_INVISIBLE;
   }
 
   public static boolean isEnterpriseDirectoryId(long directoryId) {
diff --git a/java/com/android/dialer/contactactions/SharedModules.java b/java/com/android/dialer/contactactions/SharedModules.java
deleted file mode 100644
index 0689f98..0000000
--- a/java/com/android/dialer/contactactions/SharedModules.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2017 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
- */
-
-package com.android.dialer.contactactions;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.widget.Toast;
-import com.android.dialer.DialerPhoneNumber;
-import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier;
-import com.android.dialer.clipboard.ClipboardUtils;
-import com.android.dialer.util.IntentUtil;
-import com.android.dialer.util.UriUtils;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Modules for the bottom sheet that are shared between NewVoicemailFragment and NewCallLogFragment
- */
-public class SharedModules {
-
-  public static void maybeAddModuleForAddingToContacts(
-      Context context,
-      List<ContactActionModule> modules,
-      DialerPhoneNumber dialerPhoneNumber,
-      String name,
-      String lookupUri,
-      boolean isBlocked,
-      boolean isSpam) {
-    // Skip showing the menu item for a spam/blocked number.
-    if (isBlocked || isSpam) {
-      return;
-    }
-
-    // Skip showing the menu item for existing contacts.
-    if (isExistingContact(lookupUri)) {
-      return;
-    }
-
-    // Skip showing the menu item if there is no number.
-    String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
-    if (TextUtils.isEmpty(normalizedNumber)) {
-      return;
-    }
-
-    Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
-    intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
-    intent.putExtra(ContactsContract.Intents.Insert.PHONE, normalizedNumber);
-
-    if (!TextUtils.isEmpty(name)) {
-      intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
-    }
-    modules.add(
-        new IntentModule(
-            context,
-            intent,
-            R.string.add_to_contacts,
-            R.drawable.quantum_ic_person_add_vd_theme_24));
-  }
-
-  /**
-   * Lookup URIs are currently fetched from the cached column of the system call log. This URI
-   * contains encoded information for non-contacts for the purposes of populating contact cards.
-   *
-   * <p>We infer whether a contact is existing or not by checking if the lookup URI is "encoded" or
-   * not.
-   *
-   * <p>TODO(zachh): We should revisit this once the contact URI is no longer being read from the
-   * cached column in the system database, in case we decide not to overload the column.
-   */
-  public static boolean isExistingContact(@Nullable String lookupUri) {
-    return !TextUtils.isEmpty(lookupUri) && !UriUtils.isEncodedContactUri(Uri.parse(lookupUri));
-  }
-
-  public static void maybeAddModuleForSendingTextMessage(
-      Context context,
-      List<ContactActionModule> modules,
-      String normalizedNumber,
-      boolean isBlocked) {
-    // Don't show the option to send a text message if the number is blocked.
-    if (isBlocked) {
-      return;
-    }
-
-    // TODO(zachh): There are some conditions where this module should not be shown; consider
-    // voicemail, business numbers, etc.
-
-    if (!TextUtils.isEmpty(normalizedNumber)) {
-      modules.add(
-          new IntentModule(
-              context,
-              IntentUtil.getSendSmsIntent(normalizedNumber),
-              R.string.send_a_message,
-              R.drawable.quantum_ic_message_vd_theme_24));
-    }
-  }
-
-  /**
-   * Add modules related to blocking/unblocking a number and/or reporting it as spam/not spam.
-   *
-   * @param normalizedNumber The number to be blocked / unblocked / marked as spam/not spam
-   * @param countryIso The ISO 3166-1 two letters country code for the number
-   * @param callType Call type defined in {@link android.provider.CallLog.Calls}
-   */
-  public static void addModulesHandlingBlockedOrSpamNumber(
-      Context context,
-      List<ContactActionModule> modules,
-      String normalizedNumber,
-      String countryIso,
-      int callType,
-      boolean isBlocked,
-      boolean isSpam) {
-    // For a spam number, add two options:
-    // (1) "Not spam" and "Block", or
-    // (2) "Not spam" and "Unblock".
-    if (isSpam) {
-      addModuleForMarkingNumberAsNonSpam(context, modules, normalizedNumber, countryIso, callType);
-      addModuleForBlockingOrUnblockingNumber(context, modules, normalizedNumber, isBlocked);
-      return;
-    }
-
-    // For a blocked non-spam number, add "Unblock" option.
-    if (isBlocked) {
-      addModuleForBlockingOrUnblockingNumber(context, modules, normalizedNumber, isBlocked);
-      return;
-    }
-
-    // For a number that is neither a spam number nor blocked, add "Block/Report spam" option.
-    addModuleForBlockingNumberAndOptionallyReportingSpam(
-        context, modules, normalizedNumber, countryIso, callType);
-  }
-
-  /**
-   * Add "Not spam" module.
-   *
-   * @param normalizedNumber The number to be marked as not spam
-   * @param countryIso The ISO 3166-1 two letters country code for the number
-   * @param callType Call type defined in {@link android.provider.CallLog.Calls}
-   */
-  private static void addModuleForMarkingNumberAsNonSpam(
-      Context context,
-      List<ContactActionModule> modules,
-      String normalizedNumber,
-      String countryIso,
-      int callType) {
-    modules.add(
-        new ContactActionModule() {
-          @Override
-          public int getStringId() {
-            return R.string.not_spam;
-          }
-
-          @Override
-          public int getDrawableId() {
-            return R.drawable.quantum_ic_report_off_vd_theme_24;
-          }
-
-          @Override
-          public boolean onClick() {
-            ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam(
-                context, normalizedNumber, countryIso, callType);
-            return true; // Close the bottom sheet.
-          }
-        });
-  }
-
-  private static void addModuleForBlockingOrUnblockingNumber(
-      Context context,
-      List<ContactActionModule> modules,
-      String normalizedNumber,
-      boolean isBlocked) {
-    modules.add(
-        new ContactActionModule() {
-          @Override
-          public int getStringId() {
-            return isBlocked ? R.string.unblock_number : R.string.block_number;
-          }
-
-          @Override
-          public int getDrawableId() {
-            return isBlocked
-                ? R.drawable.ic_unblock // TODO(a bug): use a vector icon
-                : R.drawable.quantum_ic_block_vd_theme_24;
-          }
-
-          @Override
-          public boolean onClick() {
-            // TODO(a bug): implement this method.
-            Toast.makeText(
-                    context,
-                    String.format(
-                        Locale.ENGLISH,
-                        "TODO: " + (isBlocked ? "Unblock " : "Block ") + " number %s.",
-                        normalizedNumber),
-                    Toast.LENGTH_SHORT)
-                .show();
-            return true; // Close the bottom sheet.
-          }
-        });
-  }
-
-  /**
-   * Add "Block/Report spam" module
-   *
-   * @param normalizedNumber The number to be blocked / unblocked / marked as spam/not spam
-   * @param countryIso The ISO 3166-1 two letters country code for the number
-   * @param callType Call type defined in {@link android.provider.CallLog.Calls}
-   */
-  private static void addModuleForBlockingNumberAndOptionallyReportingSpam(
-      Context context,
-      List<ContactActionModule> modules,
-      String normalizedNumber,
-      String countryIso,
-      int callType) {
-    modules.add(
-        new ContactActionModule() {
-          @Override
-          public int getStringId() {
-            return R.string.block_and_optionally_report_spam;
-          }
-
-          @Override
-          public int getDrawableId() {
-            return R.drawable.quantum_ic_block_vd_theme_24;
-          }
-
-          @Override
-          public boolean onClick() {
-            ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam(
-                context, normalizedNumber, countryIso, callType);
-            return true; // Close the bottom sheet.
-          }
-        });
-  }
-
-  public static void maybeAddModuleForCopyingNumber(
-      Context context, List<ContactActionModule> modules, String normalizedNumber) {
-    if (TextUtils.isEmpty(normalizedNumber)) {
-      return;
-    }
-    modules.add(
-        new ContactActionModule() {
-          @Override
-          public int getStringId() {
-            return R.string.copy_number;
-          }
-
-          @Override
-          public int getDrawableId() {
-            return R.drawable.quantum_ic_content_copy_vd_theme_24;
-          }
-
-          @Override
-          public boolean onClick() {
-            ClipboardUtils.copyText(context, null, normalizedNumber, true);
-            return false;
-          }
-        });
-  }
-}
diff --git a/java/com/android/dialer/contactsfragment/ContactsFragment.java b/java/com/android/dialer/contactsfragment/ContactsFragment.java
index ae2bd74..794a5b9 100644
--- a/java/com/android/dialer/contactsfragment/ContactsFragment.java
+++ b/java/com/android/dialer/contactsfragment/ContactsFragment.java
@@ -158,6 +158,11 @@
     contactsPrefs.registerChangeListener(this);
     header = getArguments().getInt(EXTRA_HEADER);
     hasPhoneNumbers = getArguments().getBoolean(EXTRA_HAS_PHONE_NUMBERS);
+    if (savedInstanceState == null) {
+      // The onHiddenChanged callback does not get called the first time the fragment is
+      // attached, so call it ourselves here.
+      onHiddenChanged(false);
+    }
   }
 
   @Override
@@ -354,6 +359,16 @@
     }
   }
 
+  @Override
+  public void onHiddenChanged(boolean hidden) {
+    super.onHiddenChanged(hidden);
+    OnContactsFragmentHiddenChangedListener listener =
+        FragmentUtils.getParent(this, OnContactsFragmentHiddenChangedListener.class);
+    if (listener != null) {
+      listener.onContactsFragmentHiddenChanged(hidden);
+    }
+  }
+
   private void loadContacts() {
     getLoaderManager().initLoader(0, null, this);
     recyclerView.setVisibility(View.VISIBLE);
@@ -371,4 +386,9 @@
     /** Called when a contact is selected in {@link ContactsFragment}. */
     void onContactSelected(ImageView photo, Uri contactUri, long contactId);
   }
+
+  /** Listener for contacts fragment hidden state */
+  public interface OnContactsFragmentHiddenChangedListener {
+    void onContactsFragmentHiddenChanged(boolean hidden);
+  }
 }
diff --git a/java/com/android/dialer/contactactions/AndroidManifest.xml b/java/com/android/dialer/historyitemactions/AndroidManifest.xml
similarity index 90%
rename from java/com/android/dialer/contactactions/AndroidManifest.xml
rename to java/com/android/dialer/historyitemactions/AndroidManifest.xml
index a64066e..4d30268 100644
--- a/java/com/android/dialer/contactactions/AndroidManifest.xml
+++ b/java/com/android/dialer/historyitemactions/AndroidManifest.xml
@@ -13,4 +13,4 @@
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License
  -->
-<manifest package="com.android.dialer.contactactions"/>
+<manifest package="com.android.dialer.historyitemactions"/>
diff --git a/java/com/android/dialer/contactactions/DividerModule.java b/java/com/android/dialer/historyitemactions/DividerModule.java
similarity index 79%
rename from java/com/android/dialer/contactactions/DividerModule.java
rename to java/com/android/dialer/historyitemactions/DividerModule.java
index aabd160..a5ca62a 100644
--- a/java/com/android/dialer/contactactions/DividerModule.java
+++ b/java/com/android/dialer/historyitemactions/DividerModule.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.dialer.contactactions;
+package com.android.dialer.historyitemactions;
 
 import com.android.dialer.common.Assert;
 
 /**
- * A module that inserts a grey line divider into {@link ContactActionModule}. Layout it provided in
- * R.layout.divider_layout.xml
+ * A module that inserts a grey line divider into {@link HistoryItemActionModule}. Layout it
+ * provided in R.layout.divider_layout.xml
  */
-public final class DividerModule implements ContactActionModule {
+public final class DividerModule implements HistoryItemActionModule {
 
   @Override
   public int getStringId() {
diff --git a/java/com/android/dialer/contactactions/ContactActionBottomSheet.java b/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
similarity index 64%
rename from java/com/android/dialer/contactactions/ContactActionBottomSheet.java
rename to java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
index 98a5dd1..47aa100 100644
--- a/java/com/android/dialer/contactactions/ContactActionBottomSheet.java
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.dialer.contactactions;
+package com.android.dialer.historyitemactions;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -32,37 +32,38 @@
 import java.util.List;
 
 /**
- * {@link BottomSheetDialog} used for building a list of contact actions in a bottom sheet menu.
+ * {@link BottomSheetDialog} used to show a list of actions in a bottom sheet menu.
  *
- * <p>{@link #show(Context, ContactPrimaryActionInfo, List)} should be used to create and display
- * the menu. Modules are built using {@link ContactActionModule} and some defaults are provided by
- * {@link IntentModule} and {@link DividerModule}.
+ * <p>{@link #show(Context, HistoryItemPrimaryActionInfo, List, GlidePhotoManager)} should be used
+ * to create and display the menu. Modules are built using {@link HistoryItemActionModule} and some
+ * defaults are provided by {@link IntentModule} and {@link DividerModule}.
  */
-public class ContactActionBottomSheet extends BottomSheetDialog implements OnClickListener {
+public class HistoryItemActionBottomSheet extends BottomSheetDialog implements OnClickListener {
 
-  private final List<ContactActionModule> modules;
-  private final ContactPrimaryActionInfo contactPrimaryActionInfo;
+  private final List<HistoryItemActionModule> modules;
+  private final HistoryItemPrimaryActionInfo historyItemPrimaryActionInfo;
   private final GlidePhotoManager glidePhotoManager;
 
-  private ContactActionBottomSheet(
+  private HistoryItemActionBottomSheet(
       Context context,
-      ContactPrimaryActionInfo contactPrimaryActionInfo,
-      List<ContactActionModule> modules,
+      HistoryItemPrimaryActionInfo historyItemPrimaryActionInfo,
+      List<HistoryItemActionModule> modules,
       GlidePhotoManager glidePhotoManager) {
     super(context);
     this.modules = modules;
-    this.contactPrimaryActionInfo = contactPrimaryActionInfo;
+    this.historyItemPrimaryActionInfo = historyItemPrimaryActionInfo;
     this.glidePhotoManager = glidePhotoManager;
     setContentView(LayoutInflater.from(context).inflate(R.layout.sheet_layout, null));
   }
 
-  public static ContactActionBottomSheet show(
+  public static HistoryItemActionBottomSheet show(
       Context context,
-      ContactPrimaryActionInfo contactPrimaryActionInfo,
-      List<ContactActionModule> modules,
+      HistoryItemPrimaryActionInfo historyItemPrimaryActionInfo,
+      List<HistoryItemActionModule> modules,
       GlidePhotoManager glidePhotoManager) {
-    ContactActionBottomSheet sheet =
-        new ContactActionBottomSheet(context, contactPrimaryActionInfo, modules, glidePhotoManager);
+    HistoryItemActionBottomSheet sheet =
+        new HistoryItemActionBottomSheet(
+            context, historyItemPrimaryActionInfo, modules, glidePhotoManager);
     sheet.show();
     return sheet;
   }
@@ -73,7 +74,7 @@
     LinearLayout container = Assert.isNotNull(findViewById(R.id.action_container));
     container.addView(getContactView(container));
 
-    for (ContactActionModule module : modules) {
+    for (HistoryItemActionModule module : modules) {
       if (module instanceof DividerModule) {
         container.addView(getDividerView(container));
       } else {
@@ -88,22 +89,23 @@
 
     // TODO(zachh): The contact image should be badged with a video icon if it is for a video call.
     glidePhotoManager.loadQuickContactBadge(
-        contactView.findViewById(R.id.quick_contact_photo), contactPrimaryActionInfo.photoInfo());
+        contactView.findViewById(R.id.quick_contact_photo),
+        historyItemPrimaryActionInfo.photoInfo());
 
     TextView primaryTextView = contactView.findViewById(R.id.primary_text);
     TextView secondaryTextView = contactView.findViewById(R.id.secondary_text);
 
-    primaryTextView.setText(contactPrimaryActionInfo.primaryText());
-    if (!TextUtils.isEmpty(contactPrimaryActionInfo.secondaryText())) {
-      secondaryTextView.setText(contactPrimaryActionInfo.secondaryText());
+    primaryTextView.setText(historyItemPrimaryActionInfo.primaryText());
+    if (!TextUtils.isEmpty(historyItemPrimaryActionInfo.secondaryText())) {
+      secondaryTextView.setText(historyItemPrimaryActionInfo.secondaryText());
     } else {
       secondaryTextView.setVisibility(View.GONE);
       secondaryTextView.setText(null);
     }
-    if (contactPrimaryActionInfo.intent() != null) {
+    if (historyItemPrimaryActionInfo.intent() != null) {
       contactView.setOnClickListener(
           (view) -> {
-            getContext().startActivity(contactPrimaryActionInfo.intent());
+            getContext().startActivity(historyItemPrimaryActionInfo.intent());
             dismiss();
           });
     }
@@ -115,7 +117,7 @@
     return inflater.inflate(R.layout.divider_layout, container, false);
   }
 
-  private View getModuleView(ViewGroup container, ContactActionModule module) {
+  private View getModuleView(ViewGroup container, HistoryItemActionModule module) {
     LayoutInflater inflater = LayoutInflater.from(getContext());
     View moduleView = inflater.inflate(R.layout.module_layout, container, false);
     ((TextView) moduleView.findViewById(R.id.module_text)).setText(module.getStringId());
@@ -128,7 +130,7 @@
 
   @Override
   public void onClick(View view) {
-    if (((ContactActionModule) view.getTag()).onClick()) {
+    if (((HistoryItemActionModule) view.getTag()).onClick()) {
       dismiss();
     }
   }
diff --git a/java/com/android/dialer/contactactions/ContactActionModule.java b/java/com/android/dialer/historyitemactions/HistoryItemActionModule.java
similarity index 72%
rename from java/com/android/dialer/contactactions/ContactActionModule.java
rename to java/com/android/dialer/historyitemactions/HistoryItemActionModule.java
index 8089edc..d64cbca 100644
--- a/java/com/android/dialer/contactactions/ContactActionModule.java
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionModule.java
@@ -14,18 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.dialer.contactactions;
+package com.android.dialer.historyitemactions;
 
 import android.support.annotation.DrawableRes;
 import android.support.annotation.StringRes;
 
 /**
- * Modules used to build {@link ContactActionBottomSheet}.
+ * Modules used to build {@link HistoryItemActionBottomSheet}.
  *
- * <p>Contacts as they relate to this class should be thought of as any entity that an action can be
- * performed on like unknown/restricted contacts, along with saved and non-saved contacts.
+ * <p>A history item is one that is displayed in the call log or the voicemail fragment.
  */
-public interface ContactActionModule {
+public interface HistoryItemActionModule {
 
   @StringRes
   int getStringId();
diff --git a/java/com/android/dialer/contactactions/ContactPrimaryActionInfo.java b/java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java
similarity index 82%
rename from java/com/android/dialer/contactactions/ContactPrimaryActionInfo.java
rename to java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java
index 5017d83..f4338ce 100644
--- a/java/com/android/dialer/contactactions/ContactPrimaryActionInfo.java
+++ b/java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.dialer.contactactions;
+package com.android.dialer.historyitemactions;
 
 import android.content.Intent;
 import android.support.annotation.NonNull;
@@ -23,13 +23,12 @@
 import com.google.auto.value.AutoValue;
 
 /**
- * Contains information necessary to construct the primary action for a contact bottom sheet.
+ * Contains information necessary to construct the primary action for a history item's bottom sheet.
  *
- * <p>This may include information about the call, for instance when the bottom sheet is shown from
- * the call log.
+ * <p>A history item is one that is displayed in the call log or the voicemail fragment.
  */
 @AutoValue
-public abstract class ContactPrimaryActionInfo {
+public abstract class HistoryItemPrimaryActionInfo {
 
   @Nullable
   public abstract DialerPhoneNumber number();
@@ -52,7 +51,7 @@
 
   // TODO(zachh): Add SIM info here if should be shown in bottom sheet.
 
-  /** Builder for {@link ContactPrimaryActionInfo}. */
+  /** Builder for {@link HistoryItemPrimaryActionInfo}. */
   @AutoValue.Builder
   public abstract static class Builder {
     public abstract Builder setNumber(@Nullable DialerPhoneNumber dialerPhoneNumber);
@@ -65,10 +64,10 @@
 
     public abstract Builder setIntent(@Nullable Intent intent);
 
-    public abstract ContactPrimaryActionInfo build();
+    public abstract HistoryItemPrimaryActionInfo build();
   }
 
   public static Builder builder() {
-    return new AutoValue_ContactPrimaryActionInfo.Builder();
+    return new AutoValue_HistoryItemPrimaryActionInfo.Builder();
   }
 }
diff --git a/java/com/android/dialer/contactactions/IntentModule.java b/java/com/android/dialer/historyitemactions/IntentModule.java
similarity index 92%
rename from java/com/android/dialer/contactactions/IntentModule.java
rename to java/com/android/dialer/historyitemactions/IntentModule.java
index 9a345c6..dfe9bb0 100644
--- a/java/com/android/dialer/contactactions/IntentModule.java
+++ b/java/com/android/dialer/historyitemactions/IntentModule.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.dialer.contactactions;
+package com.android.dialer.historyitemactions;
 
 import android.content.Context;
 import android.content.Intent;
@@ -28,9 +28,10 @@
 import com.android.dialer.util.DialerUtils;
 
 /**
- * {@link ContactActionModule} useful for making easy to build modules based on starting an intent.
+ * {@link HistoryItemActionModule} useful for making easy to build modules based on starting an
+ * intent.
  */
-public class IntentModule implements ContactActionModule {
+public class IntentModule implements HistoryItemActionModule {
 
   private final Context context;
   private final Intent intent;
diff --git a/java/com/android/dialer/historyitemactions/SharedModules.java b/java/com/android/dialer/historyitemactions/SharedModules.java
new file mode 100644
index 0000000..7cfee37
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/SharedModules.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2017 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
+ */
+
+package com.android.dialer.historyitemactions;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.widget.Toast;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier;
+import com.android.dialer.clipboard.ClipboardUtils;
+import com.android.dialer.logging.ReportingLocation;
+import com.android.dialer.util.IntentUtil;
+import com.android.dialer.util.UriUtils;
+import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Modules for the bottom sheet that are shared between NewVoicemailFragment and NewCallLogFragment
+ */
+@SuppressWarnings("Guava")
+public class SharedModules {
+
+  public static Optional<HistoryItemActionModule> createModuleForAddingToContacts(
+      Context context,
+      DialerPhoneNumber dialerPhoneNumber,
+      String name,
+      String lookupUri,
+      boolean isBlocked,
+      boolean isSpam) {
+    // Skip showing the menu item for a spam/blocked number.
+    if (isBlocked || isSpam) {
+      return Optional.absent();
+    }
+
+    // Skip showing the menu item for existing contacts.
+    if (isExistingContact(lookupUri)) {
+      return Optional.absent();
+    }
+
+    // Skip showing the menu item if there is no number.
+    String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
+    if (TextUtils.isEmpty(normalizedNumber)) {
+      return Optional.absent();
+    }
+
+    Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+    intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
+    intent.putExtra(ContactsContract.Intents.Insert.PHONE, normalizedNumber);
+
+    if (!TextUtils.isEmpty(name)) {
+      intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
+    }
+
+    return Optional.of(
+        new IntentModule(
+            context,
+            intent,
+            R.string.add_to_contacts,
+            R.drawable.quantum_ic_person_add_vd_theme_24));
+  }
+
+  /**
+   * Lookup URIs are currently fetched from the cached column of the system call log. This URI
+   * contains encoded information for non-contacts for the purposes of populating contact cards.
+   *
+   * <p>We infer whether a contact is existing or not by checking if the lookup URI is "encoded" or
+   * not.
+   *
+   * <p>TODO(zachh): We should revisit this once the contact URI is no longer being read from the
+   * cached column in the system database, in case we decide not to overload the column.
+   */
+  private static boolean isExistingContact(@Nullable String lookupUri) {
+    return !TextUtils.isEmpty(lookupUri) && !UriUtils.isEncodedContactUri(Uri.parse(lookupUri));
+  }
+
+  public static Optional<HistoryItemActionModule> createModuleForSendingTextMessage(
+      Context context, String normalizedNumber, boolean isBlocked) {
+    // Don't show the option to send a text message if the number is blocked.
+    if (isBlocked) {
+      return Optional.absent();
+    }
+
+    // TODO(zachh): There are some conditions where this module should not be shown; consider
+    // voicemail, business numbers, etc.
+
+    return !TextUtils.isEmpty(normalizedNumber)
+        ? Optional.of(
+            new IntentModule(
+                context,
+                IntentUtil.getSendSmsIntent(normalizedNumber),
+                R.string.send_a_message,
+                R.drawable.quantum_ic_message_vd_theme_24))
+        : Optional.absent();
+  }
+
+  /**
+   * Add modules related to blocking/unblocking a number and/or reporting it as spam/not spam.
+   *
+   * @param normalizedNumber The number to be blocked / unblocked / marked as spam/not spam
+   * @param countryIso The ISO 3166-1 two letters country code for the number
+   * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+   * @param reportingLocation The location where the number is reported. See {@link
+   *     ReportingLocation.Type}.
+   */
+  public static List<HistoryItemActionModule> createModulesHandlingBlockedOrSpamNumber(
+      Context context,
+      String normalizedNumber,
+      String countryIso,
+      int callType,
+      boolean isBlocked,
+      boolean isSpam,
+      ReportingLocation.Type reportingLocation) {
+    List<HistoryItemActionModule> modules = new ArrayList<>();
+
+    // For a spam number, add two options:
+    // (1) "Not spam" and "Block", or
+    // (2) "Not spam" and "Unblock".
+    if (isSpam) {
+      modules.add(
+          createModuleForMarkingNumberAsNonSpam(
+              context, normalizedNumber, countryIso, callType, reportingLocation));
+      modules.add(createModuleForBlockingOrUnblockingNumber(context, normalizedNumber, isBlocked));
+      return modules;
+    }
+
+    // For a blocked non-spam number, add "Unblock" option.
+    if (isBlocked) {
+      modules.add(createModuleForBlockingOrUnblockingNumber(context, normalizedNumber, isBlocked));
+      return modules;
+    }
+
+    // For a number that is neither a spam number nor blocked, add "Block/Report spam" option.
+    modules.add(
+        createModuleForBlockingNumberAndOptionallyReportingSpam(
+            context, normalizedNumber, countryIso, callType, reportingLocation));
+    return modules;
+  }
+
+  /**
+   * Add "Not spam" module.
+   *
+   * @param normalizedNumber The number to be marked as not spam
+   * @param countryIso The ISO 3166-1 two letters country code for the number
+   * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+   * @param reportingLocation The location where the number is reported. See {@link
+   *     ReportingLocation.Type}.
+   */
+  private static HistoryItemActionModule createModuleForMarkingNumberAsNonSpam(
+      Context context,
+      String normalizedNumber,
+      String countryIso,
+      int callType,
+      ReportingLocation.Type reportingLocation) {
+    return new HistoryItemActionModule() {
+      @Override
+      public int getStringId() {
+        return R.string.not_spam;
+      }
+
+      @Override
+      public int getDrawableId() {
+        return R.drawable.quantum_ic_report_off_vd_theme_24;
+      }
+
+      @Override
+      public boolean onClick() {
+        ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam(
+            context, normalizedNumber, countryIso, callType, reportingLocation);
+        return true; // Close the bottom sheet.
+      }
+    };
+  }
+
+  private static HistoryItemActionModule createModuleForBlockingOrUnblockingNumber(
+      Context context, String normalizedNumber, boolean isBlocked) {
+    return new HistoryItemActionModule() {
+      @Override
+      public int getStringId() {
+        return isBlocked ? R.string.unblock_number : R.string.block_number;
+      }
+
+      @Override
+      public int getDrawableId() {
+        return isBlocked
+            ? R.drawable.ic_unblock // TODO(a bug): use a vector icon
+            : R.drawable.quantum_ic_block_vd_theme_24;
+      }
+
+      @Override
+      public boolean onClick() {
+        // TODO(a bug): implement this method.
+        Toast.makeText(
+                context,
+                String.format(
+                    Locale.ENGLISH,
+                    "TODO: " + (isBlocked ? "Unblock " : "Block ") + " number %s.",
+                    normalizedNumber),
+                Toast.LENGTH_SHORT)
+            .show();
+        return true; // Close the bottom sheet.
+      }
+    };
+  }
+
+  /**
+   * Add "Block/Report spam" module
+   *
+   * @param normalizedNumber The number to be blocked / unblocked / marked as spam/not spam
+   * @param countryIso The ISO 3166-1 two letters country code for the number
+   * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+   * @param reportingLocation The location where the number is reported. See {@link
+   *     ReportingLocation.Type}.
+   */
+  private static HistoryItemActionModule createModuleForBlockingNumberAndOptionallyReportingSpam(
+      Context context,
+      String normalizedNumber,
+      String countryIso,
+      int callType,
+      ReportingLocation.Type reportingLocation) {
+    return new HistoryItemActionModule() {
+      @Override
+      public int getStringId() {
+        return R.string.block_and_optionally_report_spam;
+      }
+
+      @Override
+      public int getDrawableId() {
+        return R.drawable.quantum_ic_block_vd_theme_24;
+      }
+
+      @Override
+      public boolean onClick() {
+        ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam(
+            context, normalizedNumber, countryIso, callType, reportingLocation);
+        return true; // Close the bottom sheet.
+      }
+    };
+  }
+
+  public static Optional<HistoryItemActionModule> createModuleForCopyingNumber(
+      Context context, String normalizedNumber) {
+    if (TextUtils.isEmpty(normalizedNumber)) {
+      return Optional.absent();
+    }
+    return Optional.of(
+        new HistoryItemActionModule() {
+          @Override
+          public int getStringId() {
+            return R.string.copy_number;
+          }
+
+          @Override
+          public int getDrawableId() {
+            return R.drawable.quantum_ic_content_copy_vd_theme_24;
+          }
+
+          @Override
+          public boolean onClick() {
+            ClipboardUtils.copyText(context, null, normalizedNumber, true);
+            return false;
+          }
+        });
+  }
+}
diff --git a/java/com/android/dialer/contactactions/res/drawable-xxxhdpi/ic_unblock.png b/java/com/android/dialer/historyitemactions/res/drawable-xxxhdpi/ic_unblock.png
similarity index 100%
rename from java/com/android/dialer/contactactions/res/drawable-xxxhdpi/ic_unblock.png
rename to java/com/android/dialer/historyitemactions/res/drawable-xxxhdpi/ic_unblock.png
Binary files differ
diff --git a/java/com/android/dialer/contactactions/res/layout/contact_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
similarity index 100%
rename from java/com/android/dialer/contactactions/res/layout/contact_layout.xml
rename to java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
diff --git a/java/com/android/dialer/contactactions/res/layout/divider_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/divider_layout.xml
similarity index 100%
rename from java/com/android/dialer/contactactions/res/layout/divider_layout.xml
rename to java/com/android/dialer/historyitemactions/res/layout/divider_layout.xml
diff --git a/java/com/android/dialer/contactactions/res/layout/module_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/module_layout.xml
similarity index 100%
rename from java/com/android/dialer/contactactions/res/layout/module_layout.xml
rename to java/com/android/dialer/historyitemactions/res/layout/module_layout.xml
diff --git a/java/com/android/dialer/contactactions/res/layout/sheet_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
similarity index 100%
rename from java/com/android/dialer/contactactions/res/layout/sheet_layout.xml
rename to java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
diff --git a/java/com/android/dialer/contactactions/res/values/dimens.xml b/java/com/android/dialer/historyitemactions/res/values/dimens.xml
similarity index 100%
rename from java/com/android/dialer/contactactions/res/values/dimens.xml
rename to java/com/android/dialer/historyitemactions/res/values/dimens.xml
diff --git a/java/com/android/dialer/contactactions/res/values/strings.xml b/java/com/android/dialer/historyitemactions/res/values/strings.xml
similarity index 100%
rename from java/com/android/dialer/contactactions/res/values/strings.xml
rename to java/com/android/dialer/historyitemactions/res/values/strings.xml
diff --git a/java/com/android/dialer/logging/reporting_location.proto b/java/com/android/dialer/logging/reporting_location.proto
index 3c1baf0..b9912be 100644
--- a/java/com/android/dialer/logging/reporting_location.proto
+++ b/java/com/android/dialer/logging/reporting_location.proto
@@ -14,5 +14,6 @@
     UNKNOWN_REPORTING_LOCATION = 0;
     CALL_LOG_HISTORY = 1;
     FEEDBACK_PROMPT = 2;
+    VOICEMAIL_HISTORY = 3;
   }
 }
diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java
index 33e0981..7d380d7 100644
--- a/java/com/android/dialer/main/impl/MainSearchController.java
+++ b/java/com/android/dialer/main/impl/MainSearchController.java
@@ -52,6 +52,7 @@
 import com.android.dialer.smartdial.util.SmartDialNameMatcher;
 import com.google.common.base.Optional;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Search controller for handling all the logic related to entering and exiting the search UI.
@@ -83,6 +84,8 @@
   private final MainToolbar toolbar;
   private final View toolbarShadow;
 
+  private final List<OnSearchShowListener> onSearchShowListenerList = new ArrayList<>();
+
   public MainSearchController(
       MainActivity mainActivity,
       BottomNavBar bottomNav,
@@ -125,7 +128,9 @@
       // TODO(a bug): zero suggest results aren't actually shown but this enabled the nearby
       // places promo to be shown.
       searchFragment = NewSearchFragment.newInstance(/* showZeroSuggest=*/ true);
-      transaction.add(R.id.fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
+      transaction.replace(R.id.fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
+      transaction.addToBackStack(null);
+      transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
     } else if (!isSearchVisible()) {
       transaction.show(searchFragment);
     }
@@ -142,6 +147,8 @@
       transaction.show(dialpadFragment);
     }
     transaction.commit();
+
+    notifyListenersOnSearchOpen();
   }
 
   /**
@@ -282,12 +289,23 @@
     showBottomNav();
     toolbar.collapse(animate);
     toolbarShadow.setVisibility(View.GONE);
-    mainActivity.getFragmentManager().beginTransaction().remove(getSearchFragment()).commit();
+    mainActivity.getFragmentManager().popBackStack();
 
     // Clear the dialpad so the phone number isn't persisted between search sessions.
-    if (getDialpadFragment() != null) {
-      getDialpadFragment().clearDialpad();
+    DialpadFragment dialpadFragment = getDialpadFragment();
+    if (dialpadFragment != null) {
+      // Temporarily disable accessibility when we clear the dialpad, since it should be
+      // invisible and should not announce anything.
+      dialpadFragment
+          .getDigitsWidget()
+          .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+      dialpadFragment.clearDialpad();
+      dialpadFragment
+          .getDigitsWidget()
+          .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
     }
+
+    notifyListenersOnSearchClose();
   }
 
   @Nullable
@@ -348,7 +366,9 @@
       // TODO(a bug): zero suggest results aren't actually shown but this enabled the nearby
       // places promo to be shown.
       searchFragment = NewSearchFragment.newInstance(true);
-      transaction.add(R.id.fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
+      transaction.replace(R.id.fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
+      transaction.addToBackStack(null);
+      transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
     } else if (!isSearchVisible()) {
       transaction.show(getSearchFragment());
     }
@@ -356,6 +376,8 @@
     searchFragment.setQuery(
         query.isPresent() ? query.get() : "", CallInitiationType.Type.REGULAR_SEARCH);
     transaction.commit();
+
+    notifyListenersOnSearchOpen();
   }
 
   @Override
@@ -455,4 +477,31 @@
       toolbar.slideUp(false);
     }
   }
+
+  public void addOnSearchShowListener(OnSearchShowListener listener) {
+    onSearchShowListenerList.add(listener);
+  }
+
+  public void removeOnSearchShowListener(OnSearchShowListener listener) {
+    onSearchShowListenerList.remove(listener);
+  }
+
+  private void notifyListenersOnSearchOpen() {
+    for (OnSearchShowListener listener : onSearchShowListenerList) {
+      listener.onSearchOpen();
+    }
+  }
+
+  private void notifyListenersOnSearchClose() {
+    for (OnSearchShowListener listener : onSearchShowListenerList) {
+      listener.onSearchClose();
+    }
+  }
+
+  /** Listener for search fragment show states change */
+  public interface OnSearchShowListener {
+    void onSearchOpen();
+
+    void onSearchClose();
+  }
 }
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 9ceea28..a05ef6d 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -201,7 +201,8 @@
 
     bottomNav = mainActivity.findViewById(R.id.bottom_nav_bar);
     MainBottomNavBarBottomNavTabListener bottomNavTabListener =
-        new MainBottomNavBarBottomNavTabListener(mainActivity, mainActivity.getFragmentManager());
+        new MainBottomNavBarBottomNavTabListener(
+            mainActivity, mainActivity.getFragmentManager(), fab);
     bottomNav.addOnTabSelectedListener(bottomNavTabListener);
     // TODO(uabdullah): Handle case of when a sim is inserted/removed while the activity is open.
     boolean showVoicemailTab = canVoicemailTabBeShown(mainActivity);
@@ -251,7 +252,7 @@
    * Check and return whether the voicemail tab should be shown or not. This includes the following
    * criteria under which we show the voicemail tab:
    * <li>The voicemail number exists (e.g we are able to dial into listen to voicemail or press and
-   *     hold 1)
+   *     hold 1) (TODO (uabdullah): Handle this case properly)
    * <li>Visual voicemail is enabled from the settings tab
    * <li>Visual voicemail carrier is supported by dialer
    * <li>There is no voicemail carrier app installed.
@@ -264,14 +265,18 @@
     PhoneAccountHandle defaultUserSelectedAccount =
         TelecomUtil.getDefaultOutgoingPhoneAccount(context, PhoneAccount.SCHEME_VOICEMAIL);
 
-    if (isVoicemailAvailable(context, defaultUserSelectedAccount)) {
-      return true;
+    if (!isVoicemailAvailable(context, defaultUserSelectedAccount)) {
+      LogUtil.i("OldMainActivityPeer.canVoicemailTabBeShown", "Voicemail is not available");
+      return false;
     }
+
     if (VoicemailComponent.get(context)
         .getVoicemailClient()
         .isVoicemailEnabled(context, defaultUserSelectedAccount)) {
+      LogUtil.i("OldMainActivityPeer.canVoicemailTabBeShown", "Voicemail is not enabled");
       return true;
     }
+    LogUtil.i("OldMainActivityPeer.canVoicemailTabBeShown", "returning false");
     return false;
   }
 
@@ -674,6 +679,7 @@
 
     @Override
     public void enableFloatingButton(boolean enabled) {
+      LogUtil.i("MainCallLogHost.enableFloatingButton", "enabled: " + enabled);
       if (enabled) {
         fab.show();
       } else {
@@ -972,7 +978,10 @@
 
   /**
    * Implementation of {@link OnBottomNavTabSelectedListener} that handles logic for showing each of
-   * the main tabs.
+   * the main tabs and FAB.
+   *
+   * <p>TODO(calderwoodra, uabdullah): Rethink the logic for showing/hiding the FAB when new
+   * voicemail is ready.
    */
   private static final class MainBottomNavBarBottomNavTabListener
       implements OnBottomNavTabSelectedListener {
@@ -982,17 +991,22 @@
     private static final String CONTACTS_TAG = "contacts";
     private static final String VOICEMAIL_TAG = "voicemail";
 
-    private final FragmentManager fragmentManager;
     private final Context context;
+    private final FragmentManager fragmentManager;
+    private final FloatingActionButton fab;
+
     @TabIndex private int selectedTab = -1;
 
-    private MainBottomNavBarBottomNavTabListener(Context context, FragmentManager fragmentManager) {
-      this.fragmentManager = fragmentManager;
+    private MainBottomNavBarBottomNavTabListener(
+        Context context, FragmentManager fragmentManager, FloatingActionButton fab) {
       this.context = context;
+      this.fragmentManager = fragmentManager;
+      this.fab = fab;
     }
 
     @Override
     public void onSpeedDialSelected() {
+      LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onSpeedDialSelected");
       if (selectedTab != TabIndex.SPEED_DIAL) {
         Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_FAVORITE);
         selectedTab = TabIndex.SPEED_DIAL;
@@ -1007,10 +1021,12 @@
       } else {
         fragmentManager.beginTransaction().show(fragment).commit();
       }
+      fab.show();
     }
 
     @Override
     public void onCallLogSelected() {
+      LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onCallLogSelected");
       if (selectedTab != TabIndex.CALL_LOG) {
         Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_CALL_LOG);
         selectedTab = TabIndex.CALL_LOG;
@@ -1025,10 +1041,12 @@
       } else {
         fragmentManager.beginTransaction().show(fragment).commit();
       }
+      fab.show();
     }
 
     @Override
     public void onContactsSelected() {
+      LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onContactsSelected");
       if (selectedTab != TabIndex.CONTACTS) {
         Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_CONTACTS);
         selectedTab = TabIndex.CONTACTS;
@@ -1047,10 +1065,12 @@
       } else {
         fragmentManager.beginTransaction().show(fragment).commit();
       }
+      fab.show();
     }
 
     @Override
     public void onVoicemailSelected() {
+      LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onVoicemailSelected");
       if (selectedTab != TabIndex.VOICEMAIL) {
         Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_VOICEMAIL);
         selectedTab = TabIndex.VOICEMAIL;
@@ -1059,13 +1079,16 @@
       VisualVoicemailCallLogFragment fragment =
           (VisualVoicemailCallLogFragment) fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
       if (fragment == null) {
+        fragment = new VisualVoicemailCallLogFragment();
         fragmentManager
             .beginTransaction()
-            .add(R.id.fragment_container, new VisualVoicemailCallLogFragment(), VOICEMAIL_TAG)
+            .add(R.id.fragment_container, fragment, VOICEMAIL_TAG)
             .commit();
       } else {
         fragmentManager.beginTransaction().show(fragment).commit();
       }
+      fragment.setUserVisibleHint(true);
+      fragment.onVisible();
     }
 
     private void hideAllFragments() {
@@ -1082,7 +1105,11 @@
       }
       if (fragmentManager.findFragmentByTag(VOICEMAIL_TAG) != null) {
         // Old VisualVoicemailFragment
-        transaction.hide(fragmentManager.findFragmentByTag(VOICEMAIL_TAG));
+        VisualVoicemailCallLogFragment fragment =
+            (VisualVoicemailCallLogFragment) fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
+        fragment.setUserVisibleHint(false);
+        fragment.onNotVisible();
+        transaction.hide(fragment);
       }
       transaction.commit();
     }
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 4f02841..b69625e 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
@@ -44,6 +44,7 @@
         android:layout_margin="16dp"
         android:layout_gravity="end|bottom"
         android:src="@drawable/quantum_ic_dialpad_white_24"
+        android:contentDescription="@string/dialpad_button_content_description"
         app:backgroundTint="?android:attr/colorAccent"/>
   </android.support.design.widget.CoordinatorLayout>
 
diff --git a/java/com/android/dialer/main/impl/res/values/strings.xml b/java/com/android/dialer/main/impl/res/values/strings.xml
index c842bee..4e65432 100644
--- a/java/com/android/dialer/main/impl/res/values/strings.xml
+++ b/java/com/android/dialer/main/impl/res/values/strings.xml
@@ -40,4 +40,8 @@
 
   <!-- Message displayed when there is no application available to handle voice search. [CHAR LIMIT=NONE] -->
   <string name="voice_search_not_available">Voice search not available</string>
+
+  <!-- Content description for the button that displays the dialpad
+       [CHAR LIMIT=NONE] -->
+  <string name="dialpad_button_content_description">key pad</string>
 </resources>
diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2ExtendedDirectoryPhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2ExtendedDirectoryPhoneLookup.java
index df164bd..519ec5f 100644
--- a/java/com/android/dialer/phonelookup/cp2/Cp2ExtendedDirectoryPhoneLookup.java
+++ b/java/com/android/dialer/phonelookup/cp2/Cp2ExtendedDirectoryPhoneLookup.java
@@ -22,12 +22,12 @@
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
 import android.provider.ContactsContract;
-import android.provider.ContactsContract.Directory;
 import android.support.annotation.VisibleForTesting;
 import com.android.dialer.DialerPhoneNumber;
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
 import com.android.dialer.common.concurrent.Annotations.LightweightExecutor;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.inject.ApplicationContext;
 import com.android.dialer.phonelookup.PhoneLookup;
 import com.android.dialer.phonelookup.PhoneLookupInfo;
@@ -80,7 +80,7 @@
               appContext
                   .getContentResolver()
                   .query(
-                      getContentUriForDirectoryIds(),
+                      DirectoryCompat.getContentUri(),
                       /* projection = */ new String[] {ContactsContract.Directory._ID},
                       /* selection = */ null,
                       /* selectionArgs = */ null,
@@ -177,13 +177,6 @@
   }
 
   @VisibleForTesting
-  static Uri getContentUriForDirectoryIds() {
-    return VERSION.SDK_INT >= VERSION_CODES.N
-        ? ContactsContract.Directory.ENTERPRISE_CONTENT_URI
-        : ContactsContract.Directory.CONTENT_URI;
-  }
-
-  @VisibleForTesting
   static Uri getContentUriForContacts(String number, long directoryId) {
     Uri baseUri =
         VERSION.SDK_INT >= VERSION_CODES.N
@@ -204,13 +197,8 @@
   }
 
   private static boolean isExtendedDirectory(long directoryId) {
-    // TODO(a bug): Moving the logic to utility shared with the search fragment.
-    return VERSION.SDK_INT >= VERSION_CODES.N
-        ? Directory.isRemoteDirectoryId(directoryId)
-            || Directory.isEnterpriseDirectoryId(directoryId)
-        : (directoryId != Directory.DEFAULT
-            && directoryId != Directory.LOCAL_INVISIBLE
-            && directoryId != Directory.ENTERPRISE_LOCAL_INVISIBLE);
+    return DirectoryCompat.isRemoteDirectoryId(directoryId)
+        || DirectoryCompat.isEnterpriseDirectoryId(directoryId);
   }
 
   @Override
diff --git a/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java b/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
index e99533a..f094be8 100644
--- a/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
+++ b/java/com/android/dialer/phonenumbercache/ContactInfoHelper.java
@@ -35,10 +35,10 @@
 import android.text.TextUtils;
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.ContactsUtils.UserType;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.contacts.common.util.Constants;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.logging.ContactSource;
 import com.android.dialer.oem.CequintCallerIdManager;
 import com.android.dialer.oem.CequintCallerIdManager.CequintCallerIdContact;
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
index 57e253c..7caa314 100644
--- a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
@@ -103,7 +103,8 @@
   static class SmartDialCursor extends MergeCursor implements SearchCursor {
 
     static SmartDialCursor newInstance(Context context, Cursor smartDialCursor) {
-      if (smartDialCursor.getCount() == 0) {
+      if (smartDialCursor == null || smartDialCursor.getCount() == 0) {
+        LogUtil.i("SmartDialCursor.newInstance", "Cursor was null or empty");
         return new SmartDialCursor(new Cursor[] {new MatrixCursor(Projections.CP2_PROJECTION)});
       }
 
@@ -173,7 +174,8 @@
   static class RegularSearchCursor extends MergeCursor implements SearchCursor {
 
     static RegularSearchCursor newInstance(Context context, Cursor regularSearchCursor) {
-      if (regularSearchCursor.getCount() == 0) {
+      if (regularSearchCursor == null || regularSearchCursor.getCount() == 0) {
+        LogUtil.i("RegularSearchCursor.newInstance", "Cursor was null or empty");
         return new RegularSearchCursor(new Cursor[] {new MatrixCursor(Projections.CP2_PROJECTION)});
       }
 
diff --git a/java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java b/java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java
index dbe11dd..4d7ea3f 100644
--- a/java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java
@@ -71,6 +71,11 @@
    * @return A list of directories.
    */
   public static List<Directory> toDirectories(Cursor cursor) {
+    if (cursor == null) {
+      LogUtil.i("DirectoriesCursorLoader.toDirectories", "Cursor was null");
+      return new ArrayList<>();
+    }
+
     List<Directory> directories = new ArrayList<>();
     cursor.moveToPosition(-1);
     while (cursor.moveToNext()) {
diff --git a/java/com/android/dialer/searchfragment/directories/DirectoryContactViewHolder.java b/java/com/android/dialer/searchfragment/directories/DirectoryContactViewHolder.java
index fc5bce1..aef1e9e 100644
--- a/java/com/android/dialer/searchfragment/directories/DirectoryContactViewHolder.java
+++ b/java/com/android/dialer/searchfragment/directories/DirectoryContactViewHolder.java
@@ -29,9 +29,9 @@
 import android.widget.ImageView;
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.contactphoto.ContactPhotoManager;
 import com.android.dialer.lettertile.LetterTileDrawable;
 import com.android.dialer.precall.PreCall;
@@ -73,14 +73,11 @@
     String secondaryInfo =
         TextUtils.isEmpty(label)
             ? number
-            : context.getString(
-                com.android.contacts.common.R.string.call_subject_type_and_number, label, number);
+            : context.getString(R.string.call_subject_type_and_number, label, number);
 
     nameView.setText(QueryBoldingUtil.getNameWithQueryBolded(query, name, context));
     numberView.setText(QueryBoldingUtil.getNameWithQueryBolded(query, secondaryInfo, context));
     workBadge.setVisibility(
-        // TODO(a bug): Consider moving DirectoryCompat out of "contacts/common" and share it
-        // with PhoneLookups.
         DirectoryCompat.isOnlyEnterpriseDirectoryId(cursor.getDirectoryId())
             ? View.VISIBLE
             : View.GONE);
diff --git a/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursor.java b/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursor.java
index 8f9ab0e..0c1ad83 100644
--- a/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursor.java
+++ b/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursor.java
@@ -22,8 +22,8 @@
 import android.database.MergeCursor;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
-import com.android.contacts.common.compat.DirectoryCompat;
 import com.android.dialer.common.Assert;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.searchfragment.common.SearchCursor;
 import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader.Directory;
 import java.util.ArrayList;
@@ -101,8 +101,6 @@
 
   private static MatrixCursor createHeaderCursor(Context context, String name, long id) {
     MatrixCursor headerCursor = new MatrixCursor(PROJECTION, 1);
-    // TODO(a bug): Consider moving DirectoryCompat out of "contacts/common" and share it
-    // with PhoneLookups.
     if (DirectoryCompat.isOnlyEnterpriseDirectoryId(id)) {
       headerCursor.addRow(
           new Object[] {context.getString(R.string.directory_search_label_work), id});
diff --git a/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursorLoader.java b/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursorLoader.java
index a948785..d719cb9 100644
--- a/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/directories/DirectoryContactsCursorLoader.java
@@ -27,7 +27,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
-import com.android.contacts.common.compat.DirectoryCompat;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.searchfragment.common.Projections;
 import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader.Directory;
 import java.util.ArrayList;
@@ -71,8 +71,6 @@
     for (int i = 0; i < directories.size(); i++) {
       Directory directory = directories.get(i);
 
-      // TODO(a bug): Consider moving DirectoryCompat out of "contacts/common" and share it
-      // with PhoneLookups.
       if (!DirectoryCompat.isRemoteDirectoryId(directory.getId())
           && !DirectoryCompat.isEnterpriseDirectoryId(directory.getId())) {
         cursors[i] = null;
diff --git a/java/com/android/dialer/searchfragment/directories/res/values/strings.xml b/java/com/android/dialer/searchfragment/directories/res/values/strings.xml
index beabba1..097f353 100644
--- a/java/com/android/dialer/searchfragment/directories/res/values/strings.xml
+++ b/java/com/android/dialer/searchfragment/directories/res/values/strings.xml
@@ -17,4 +17,10 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <!-- Label for a list of contacts stored in a seperate directory [CHAR LIMIT=30]-->
   <string name="directory">Directory <xliff:g example="google.com" id="email">%1$s</xliff:g></string>
+
+  <!-- String used to build a phone number type and phone number string.
+     Example: Mobile 650-555-1212  -->
+  <string name="call_subject_type_and_number">
+    <xliff:g example="Mobile" id="type">%1$s</xliff:g> <xliff:g example="(650) 555-1212" id="number">%2$s</xliff:g>
+  </string>
 </resources>
\ No newline at end of file
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java b/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
index 19104be..8430e24 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConnectionService.java
@@ -84,7 +84,6 @@
       return null;
     }
     SimulatorConnection connection = new SimulatorConnection(this, request);
-    connection.setDialing();
     if (SimulatorSimCallManager.isSimulatorConnectionRequest(request)) {
       simulatorConnectionsBank.add(connection);
       connection.setAddress(
@@ -92,6 +91,7 @@
           request
               .getExtras()
               .getInt(Simulator.PRESENTATION_CHOICE, TelecomManager.PRESENTATION_ALLOWED));
+      connection.setDialing();
       ThreadUtil.postOnUiThread(
           () ->
               SimulatorComponent.get(instance)
@@ -107,6 +107,8 @@
       connection.putExtras(extras);
       simulatorConnectionsBank.add(connection);
       connection.addListener(new NonSimulatorConnectionListener());
+      connection.setDialing();
+      ThreadUtil.postOnUiThread(connection::setActive);
     }
     return connection;
   }
diff --git a/java/com/android/dialer/voicemail/listui/menu/Modules.java b/java/com/android/dialer/voicemail/listui/menu/Modules.java
index 84921bd..9473b80 100644
--- a/java/com/android/dialer/voicemail/listui/menu/Modules.java
+++ b/java/com/android/dialer/voicemail/listui/menu/Modules.java
@@ -17,10 +17,12 @@
 package com.android.dialer.voicemail.listui.menu;
 
 import android.content.Context;
-import com.android.dialer.contactactions.ContactActionModule;
-import com.android.dialer.contactactions.DividerModule;
-import com.android.dialer.contactactions.SharedModules;
+import com.android.dialer.historyitemactions.DividerModule;
+import com.android.dialer.historyitemactions.HistoryItemActionModule;
+import com.android.dialer.historyitemactions.SharedModules;
+import com.android.dialer.logging.ReportingLocation;
 import com.android.dialer.voicemail.model.VoicemailEntry;
+import com.google.common.base.Optional;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -28,42 +30,57 @@
  * Configures the modules for the voicemail bottom sheet; these are the rows below the top row
  * (primary action) in the bottom sheet.
  */
+@SuppressWarnings("Guava")
 final class Modules {
 
-  static List<ContactActionModule> fromVoicemailEntry(
+  static List<HistoryItemActionModule> fromVoicemailEntry(
       Context context, VoicemailEntry voicemailEntry) {
     // Conditionally add each module, which are items in the bottom sheet's menu.
-    List<ContactActionModule> modules = new ArrayList<>();
+    List<HistoryItemActionModule> modules = new ArrayList<>();
 
     // TODO(uabdullah): Handle maybeAddModuleForVideoOrAudioCall(context, modules, row);
-    SharedModules.maybeAddModuleForAddingToContacts(
-        context,
-        modules,
-        voicemailEntry.number(),
-        voicemailEntry.numberAttributes().getName(),
-        voicemailEntry.numberAttributes().getLookupUri(),
-        voicemailEntry.numberAttributes().getIsBlocked(),
-        voicemailEntry.numberAttributes().getIsSpam());
+    Optional<HistoryItemActionModule> moduleForAddingContacts =
+        SharedModules.createModuleForAddingToContacts(
+            context,
+            voicemailEntry.number(),
+            voicemailEntry.numberAttributes().getName(),
+            voicemailEntry.numberAttributes().getLookupUri(),
+            voicemailEntry.numberAttributes().getIsBlocked(),
+            voicemailEntry.numberAttributes().getIsSpam());
+    if (moduleForAddingContacts.isPresent()) {
+      modules.add(moduleForAddingContacts.get());
+    }
 
-    String normalizedNumber = voicemailEntry.number().getNormalizedNumber();
-    SharedModules.maybeAddModuleForSendingTextMessage(
-        context, modules, normalizedNumber, voicemailEntry.numberAttributes().getIsBlocked());
+    Optional<HistoryItemActionModule> moduleForSendingTextMessage =
+        SharedModules.createModuleForSendingTextMessage(
+            context,
+            voicemailEntry.number().getNormalizedNumber(),
+            voicemailEntry.numberAttributes().getIsBlocked());
+    if (moduleForSendingTextMessage.isPresent()) {
+      modules.add(moduleForSendingTextMessage.get());
+    }
 
     if (!modules.isEmpty()) {
       modules.add(new DividerModule());
     }
 
-    SharedModules.addModulesHandlingBlockedOrSpamNumber(
-        context,
-        modules,
-        voicemailEntry.number().getNormalizedNumber(),
-        voicemailEntry.number().getCountryIso(),
-        voicemailEntry.callType(),
-        voicemailEntry.numberAttributes().getIsBlocked(),
-        voicemailEntry.numberAttributes().getIsSpam());
+    modules.addAll(
+        SharedModules.createModulesHandlingBlockedOrSpamNumber(
+            context,
+            voicemailEntry.number().getNormalizedNumber(),
+            voicemailEntry.number().getCountryIso(),
+            voicemailEntry.callType(),
+            voicemailEntry.numberAttributes().getIsBlocked(),
+            voicemailEntry.numberAttributes().getIsSpam(),
+            ReportingLocation.Type.VOICEMAIL_HISTORY));
 
     // TODO(zachh): Module for CallComposer.
-    SharedModules.maybeAddModuleForCopyingNumber(context, modules, normalizedNumber);
+    Optional<HistoryItemActionModule> moduleForCopyingNumber =
+        SharedModules.createModuleForCopyingNumber(
+            context, voicemailEntry.number().getNormalizedNumber());
+    if (moduleForCopyingNumber.isPresent()) {
+      modules.add(moduleForCopyingNumber.get());
+    }
 
     return modules;
   }
diff --git a/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java b/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java
index fbd7fe8..7c669e1 100644
--- a/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java
+++ b/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.view.View;
-import com.android.dialer.contactactions.ContactActionBottomSheet;
 import com.android.dialer.glidephotomanager.GlidePhotoManager;
+import com.android.dialer.historyitemactions.HistoryItemActionBottomSheet;
 import com.android.dialer.voicemail.model.VoicemailEntry;
 
 /** Handles configuration of the bottom sheet menus for voicemail entries. */
@@ -29,7 +29,7 @@
   public static View.OnClickListener createOnClickListener(
       Context context, VoicemailEntry voicemailEntry, GlidePhotoManager glidePhotoManager) {
     return (view) ->
-        ContactActionBottomSheet.show(
+        HistoryItemActionBottomSheet.show(
             context,
             PrimaryAction.fromVoicemailEntry(context, voicemailEntry),
             Modules.fromVoicemailEntry(context, voicemailEntry),
diff --git a/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java b/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java
index 91f505c..9a5aa18 100644
--- a/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java
+++ b/java/com/android/dialer/voicemail/listui/menu/PrimaryAction.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.text.TextUtils;
 import com.android.dialer.calllogutils.NumberAttributesConverter;
-import com.android.dialer.contactactions.ContactPrimaryActionInfo;
+import com.android.dialer.historyitemactions.HistoryItemPrimaryActionInfo;
 import com.android.dialer.voicemail.model.VoicemailEntry;
 
 /** Configures the primary action row (top row) for theottom sheet for the Voicemail Tab */
@@ -31,9 +31,9 @@
   // setIntent - allow video calling
   // setPrimaryText - check in with UX
   // setSecondaryText - check in with UX
-  static ContactPrimaryActionInfo fromVoicemailEntry(
+  static HistoryItemPrimaryActionInfo fromVoicemailEntry(
       Context context, VoicemailEntry voicemailEntry) {
-    return ContactPrimaryActionInfo.builder()
+    return HistoryItemPrimaryActionInfo.builder()
         .setNumber(voicemailEntry.number())
         .setPhotoInfo(
             NumberAttributesConverter.toPhotoInfoBuilder(voicemailEntry.numberAttributes())
diff --git a/java/com/android/incallui/AndroidManifest.xml b/java/com/android/incallui/AndroidManifest.xml
index eb080bc..a45330b 100644
--- a/java/com/android/incallui/AndroidManifest.xml
+++ b/java/com/android/incallui/AndroidManifest.xml
@@ -63,7 +63,8 @@
         android:resizeableActivity="true"
         android:screenOrientation="nosensor"
         android:taskAffinity="com.android.incallui"
-        android:theme="@style/Theme.InCallScreen">
+        android:theme="@style/Theme.InCallScreen"
+        android:windowSoftInputMode="adjustResize">
     </activity>
 
     <activity
diff --git a/java/com/android/incallui/CallerInfoAsyncQuery.java b/java/com/android/incallui/CallerInfoAsyncQuery.java
index 52ca8ca..3358952 100644
--- a/java/com/android/incallui/CallerInfoAsyncQuery.java
+++ b/java/com/android/incallui/CallerInfoAsyncQuery.java
@@ -37,7 +37,7 @@
 import android.support.annotation.WorkerThread;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
-import com.android.contacts.common.compat.DirectoryCompat;
+import com.android.dialer.common.cp2.DirectoryCompat;
 import com.android.dialer.phonenumbercache.CachedNumberLookupService;
 import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo;
 import com.android.dialer.phonenumbercache.ContactInfoHelper;
diff --git a/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml b/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml
index 5ba9f4e..ef3c1f9 100644
--- a/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml
+++ b/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml
@@ -17,8 +17,7 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/dialer_theme_color"
-    android:fitsSystemWindows="true">
+    android:background="@color/dialer_theme_color">
 
   <include layout="@layout/rtt_banner"/>
 
diff --git a/packages.mk b/packages.mk
index abe9eb5..187f969 100644
--- a/packages.mk
+++ b/packages.mk
@@ -27,7 +27,6 @@
 	com.android.dialer.commandline \
 	com.android.dialer.common \
 	com.android.dialer.configprovider \
-	com.android.dialer.contactactions \
 	com.android.dialer.contactphoto \
 	com.android.dialer.contactsfragment \
 	com.android.dialer.databasepopulator \
@@ -35,6 +34,7 @@
 	com.android.dialer.enrichedcall.simulator \
 	com.android.dialer.feedback \
 	com.android.dialer.glidephotomanager.impl \
+  com.android.dialer.historyitemactions \
 	com.android.dialer.interactions \
 	com.android.dialer.lettertile \
 	com.android.dialer.location \