Missed calls now go to MainActivity if you have the component enabled.

This CL has a few changes of varying relevance:

Most Relevance:
 - MissedCallNotifications will open MainActivity if the component is enabled
   (Meaning the launcher is in their app drawer and the flag is flipped).
 - Implemented show tab intent (open MainActivity directly to a specific tab)
 - Tests

Some Relevance:
 - Implemented checking for ACTION_DIAL intents (dialpad will open immediately)
 - Tests

Not Relevant but nice QoL changes:
 - Added tests for missed calls being marked as read
 - Makes espresso tests more horizontal to reduce timeouts
 -

Bug: 72525550,72525615
Test: implemented
PiperOrigin-RevId: 184600627
Change-Id: If96a44ce252e97c022ebc1b58fa783b3326035e7
diff --git a/java/com/android/dialer/app/MainComponent.java b/java/com/android/dialer/app/MainComponent.java
index b19ad90..9d32849 100644
--- a/java/com/android/dialer/app/MainComponent.java
+++ b/java/com/android/dialer/app/MainComponent.java
@@ -46,6 +46,16 @@
     }
   }
 
+  public static boolean isNuiComponentEnabled(Context context) {
+    if (!isNewUiEnabled(context)) {
+      return false;
+    }
+    return context
+            .getPackageManager()
+            .getComponentEnabledSetting(new ComponentName(context, getComponentName()))
+        == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+  }
+
   /**
    * Enables the NUI activity component. By default the component is disabled and can't be accessed.
    * Once the component has been enabled the user will get an option to use the new UI to handle
@@ -55,7 +65,7 @@
     context
         .getPackageManager()
         .setComponentEnabledSetting(
-            new ComponentName(context, "com.android.dialer.main.impl.MainActivity"),
+            new ComponentName(context, getComponentName()),
             PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
             PackageManager.DONT_KILL_APP);
   }
@@ -87,9 +97,21 @@
    */
   public static Intent getIntent(Context context) {
     Intent intent = new Intent();
-    intent.setComponent(new ComponentName(context, "com.android.dialer.main.impl.MainActivity"));
+    intent.setComponent(new ComponentName(context, getComponentName()));
     intent.setAction(Intent.ACTION_VIEW);
     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     return intent;
   }
+
+  public static Intent getShowCallLogIntent(Context context) {
+    Intent intent = new Intent();
+    intent.setComponent(new ComponentName(context, getComponentName()));
+    intent.setAction("ACTION_SHOW_TAB");
+    intent.putExtra("EXTRA_SHOW_TAB", 1);
+    return intent;
+  }
+
+  private static String getComponentName() {
+    return "com.android.dialer.main.impl.MainActivity";
+  }
 }
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index b8ec168..51df702 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -85,6 +85,7 @@
 import com.android.dialer.logging.DialerImpression;
 import com.android.dialer.logging.Logger;
 import com.android.dialer.logging.UiAction;
+import com.android.dialer.main.MainActivityPeer;
 import com.android.dialer.performancereport.PerformanceReport;
 import com.android.dialer.phonenumbercache.CallLogQuery;
 import com.android.dialer.phonenumbercache.ContactInfo;
@@ -382,10 +383,11 @@
               if (activityType == ACTIVITY_TYPE_DIALTACTS) {
                 if (v.getContext() instanceof CallLogFragmentListener) {
                   ((CallLogFragmentListener) v.getContext()).updateTabUnreadCounts();
-                } else if (v.getContext() instanceof FragmentUtilListener) {
+                } else if (v.getContext() instanceof MainActivityPeer.PeerSupplier) {
                   // This is really bad, but we must do this to prevent a dependency cycle, enforce
                   // best practices in new code, and avoid refactoring DialtactsActivity.
-                  ((FragmentUtilListener) v.getContext())
+                  ((FragmentUtilListener)
+                          ((MainActivityPeer.PeerSupplier) v.getContext()).getPeer())
                       .getImpl(CallLogFragmentListener.class)
                       .updateTabUnreadCounts();
                 } else {
diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
index dd92bb4..417f8f0 100644
--- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java
+++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
@@ -43,6 +43,7 @@
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
 import com.android.dialer.app.DialtactsActivity;
+import com.android.dialer.app.MainComponent;
 import com.android.dialer.app.R;
 import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall;
 import com.android.dialer.app.contactinfo.ContactPhotoLoader;
@@ -470,8 +471,13 @@
    * @param callUri Uri of the call to jump to. May be null
    */
   private PendingIntent createCallLogPendingIntent(@Nullable Uri callUri) {
-    Intent contentIntent =
-        DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_HISTORY);
+    Intent contentIntent;
+    if (MainComponent.isNuiComponentEnabled(context)) {
+      contentIntent = MainComponent.getShowCallLogIntent(context);
+    } else {
+      contentIntent =
+          DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_HISTORY);
+    }
     // TODO (a bug): scroll to call
     contentIntent.setData(callUri);
     return PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
diff --git a/java/com/android/dialer/main/impl/BottomNavBar.java b/java/com/android/dialer/main/impl/BottomNavBar.java
index 6d43ee2..97f5262 100644
--- a/java/com/android/dialer/main/impl/BottomNavBar.java
+++ b/java/com/android/dialer/main/impl/BottomNavBar.java
@@ -29,7 +29,7 @@
 import java.util.List;
 
 /** Dialer Bottom Nav Bar for {@link MainActivity}. */
-final class BottomNavBar extends LinearLayout {
+public final class BottomNavBar extends LinearLayout {
 
   /** Index for each tab in the bottom nav. */
   @Retention(RetentionPolicy.SOURCE)
diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java
index 1a79fba..24c3df5 100644
--- a/java/com/android/dialer/main/impl/MainActivity.java
+++ b/java/com/android/dialer/main/impl/MainActivity.java
@@ -26,6 +26,7 @@
 import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCode;
 import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorListener;
 import com.android.dialer.main.MainActivityPeer;
+import com.android.dialer.main.impl.BottomNavBar.TabIndex;
 import com.android.dialer.util.TransactionSafeActivity;
 
 /** This is the main activity for dialer. It hosts favorites, call log, search, dialpad, etc... */
@@ -38,6 +39,21 @@
 
   private MainActivityPeer activePeer;
 
+  public static Intent getShowCallLogIntent(Context context) {
+    return getShowTabIntent(context, TabIndex.CALL_LOG);
+  }
+
+  /** Returns intent that will open MainActivity to the specified tab. */
+  public static Intent getShowTabIntent(Context context, @TabIndex int tabIndex) {
+    if (ConfigProviderComponent.get(context)
+        .getConfigProvider()
+        .getBoolean("nui_peer_enabled", false)) {
+      // TODO(calderwoodra): implement this in NewMainActivityPeer
+      return null;
+    }
+    return OldMainActivityPeer.getShowTabIntent(context, tabIndex);
+  }
+
   /**
    * @param context Context of the application package implementing MainActivity class.
    * @return intent for MainActivity.class
diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java
index 1defdf5..62ecc53 100644
--- a/java/com/android/dialer/main/impl/MainSearchController.java
+++ b/java/com/android/dialer/main/impl/MainSearchController.java
@@ -84,8 +84,17 @@
     this.toolbar = toolbar;
   }
 
+  /** Should be called if we're showing the dialpad because of a new ACTION_DIAL intent. */
+  public void showDialpadFromNewIntent(boolean animate) {
+    showDialpad(animate, true);
+  }
+
   /** Shows the dialpad, hides the FAB and slides the toolbar off screen. */
   public void showDialpad(boolean animate) {
+    showDialpad(animate, false);
+  }
+
+  private void showDialpad(boolean animate, boolean fromNewIntent) {
     Assert.checkArgument(!isDialpadVisible());
 
     fab.hide();
@@ -106,9 +115,11 @@
     // Show Dialpad
     if (getDialpadFragment() == null) {
       DialpadFragment dialpadFragment = new DialpadFragment();
+      dialpadFragment.setStartedFromNewIntent(fromNewIntent);
       transaction.add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG);
     } else {
       DialpadFragment dialpadFragment = getDialpadFragment();
+      dialpadFragment.setStartedFromNewIntent(fromNewIntent);
       transaction.show(dialpadFragment);
     }
     transaction.commit();
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 16b74d5..dd766d0 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -31,6 +31,7 @@
 import android.support.annotation.Nullable;
 import android.support.design.widget.FloatingActionButton;
 import android.support.v7.widget.Toolbar;
+import android.telecom.PhoneAccount;
 import android.view.View;
 import android.widget.ImageView;
 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
@@ -91,6 +92,11 @@
   private static final String KEY_CURRENT_TAB = "current_tab";
   private static final String KEY_LAST_TAB = "last_tab";
 
+  /** Action and extra to let the activity know which tab to open up to. */
+  private static final String ACTION_SHOW_TAB = "ACTION_SHOW_TAB";
+
+  private static final String EXTRA_SHOW_TAB = "EXTRA_SHOW_TAB";
+
   private final MainActivity mainActivity;
 
   // Contacts
@@ -125,6 +131,22 @@
   private View snackbarContainer;
   private UiListener<String> getLastOutgoingCallListener;
 
+  public static Intent getShowTabIntent(Context context, @TabIndex int tabIndex) {
+    Intent intent = new Intent(context, MainActivity.class);
+    intent.setAction(ACTION_SHOW_TAB);
+    intent.putExtra(EXTRA_SHOW_TAB, tabIndex);
+    // TODO(calderwoodra): Do we need to set some URI data here
+    return intent;
+  }
+
+  static boolean isShowTabIntent(Intent intent) {
+    return ACTION_SHOW_TAB.equals(intent.getAction()) && intent.hasExtra(EXTRA_SHOW_TAB);
+  }
+
+  static @TabIndex int getTabFromIntent(Intent intent) {
+    return intent.getIntExtra(EXTRA_SHOW_TAB, -1);
+  }
+
   public OldMainActivityPeer(MainActivity mainActivity) {
     this.mainActivity = mainActivity;
   }
@@ -193,13 +215,52 @@
       searchController.onRestoreInstanceState(savedInstanceState);
       bottomNav.selectTab(savedInstanceState.getInt(KEY_CURRENT_TAB));
     } else {
-      lastTabController.selectLastTab();
+      showTabOnIntent(mainActivity.getIntent());
     }
   }
 
   @Override
   public void onNewIntent(Intent intent) {
-    lastTabController.selectLastTab();
+    showTabOnIntent(intent);
+  }
+
+  private void showTabOnIntent(Intent intent) {
+    if (isShowTabIntent(intent)) {
+      bottomNav.selectTab(getTabFromIntent(intent));
+      return;
+    }
+
+    if (isDialIntent(intent)) {
+      searchController.showDialpadFromNewIntent(false);
+      // Dialpad will grab the intent and populate the number
+      return;
+    }
+
+    if (lastTabController.isEnabled) {
+      lastTabController.selectLastTab();
+      return;
+    }
+
+    bottomNav.selectTab(TabIndex.SPEED_DIAL);
+  }
+
+  /** Returns true if the given intent contains a phone number to populate the dialer with */
+  private boolean isDialIntent(Intent intent) {
+    if (intent == null || intent.getData() == null) {
+      return false;
+    }
+
+    if (Intent.ACTION_DIAL.equals(intent.getAction())) {
+      return true;
+    }
+
+    if (Intent.ACTION_VIEW.equals(intent.getAction())) {
+      Uri data = intent.getData();
+      if (data != null && PhoneAccount.SCHEME_TEL.equals(data.getScheme())) {
+        return true;
+      }
+    }
+    return false;
   }
 
   @Override