Merge what's left in InCallActivityCommon into InCallActivity.

Bug: 69272096
Test: None
PiperOrigin-RevId: 176443652
Change-Id: I90da4789deb4b6337a38cfe010b8aee5090d35e0
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 1e5a5fc..28ff7da 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -16,42 +16,56 @@
 
 package com.android.incallui;
 
+import android.app.ActivityManager;
+import android.app.ActivityManager.AppTask;
 import android.app.ActivityManager.TaskDescription;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.GradientDrawable.Orientation;
 import android.os.Bundle;
 import android.os.Trace;
 import android.support.annotation.ColorInt;
 import android.support.annotation.FloatRange;
+import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
 import android.support.v4.content.res.ResourcesCompat;
 import android.support.v4.graphics.ColorUtils;
+import android.telecom.CallAudioState;
+import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
 import android.view.KeyEvent;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
 import android.widget.CheckBox;
 import android.widget.Toast;
 import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
+import com.android.dialer.animation.AnimUtils;
+import com.android.dialer.animation.AnimationListenerAdapter;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.common.concurrent.ThreadUtil;
 import com.android.dialer.compat.ActivityCompat;
+import com.android.dialer.compat.CompatUtils;
 import com.android.dialer.configprovider.ConfigProviderBindings;
 import com.android.dialer.logging.DialerImpression;
 import com.android.dialer.logging.Logger;
 import com.android.dialer.logging.LoggingBindings;
 import com.android.dialer.logging.ScreenEvent;
+import com.android.dialer.util.ViewUtil;
 import com.android.incallui.answer.bindings.AnswerBindings;
 import com.android.incallui.answer.protocol.AnswerScreen;
 import com.android.incallui.answer.protocol.AnswerScreenDelegate;
@@ -76,6 +90,11 @@
 import com.android.incallui.video.protocol.VideoCallScreen;
 import com.android.incallui.video.protocol.VideoCallScreenDelegate;
 import com.android.incallui.video.protocol.VideoCallScreenDelegateFactory;
+import com.google.common.base.Optional;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
 
 /** Version of {@link InCallActivity} that shows the new UI */
 public class InCallActivity extends TransactionSafeFragmentActivity
@@ -85,51 +104,60 @@
         VideoCallScreenDelegateFactory,
         PseudoScreenState.StateChangedListener {
 
-  public static final int PENDING_INTENT_REQUEST_CODE_NON_FULL_SCREEN = 0;
-  public static final int PENDING_INTENT_REQUEST_CODE_FULL_SCREEN = 1;
-  public static final int PENDING_INTENT_REQUEST_CODE_BUBBLE = 2;
+  @Retention(RetentionPolicy.SOURCE)
+  @IntDef({
+    DIALPAD_REQUEST_NONE,
+    DIALPAD_REQUEST_SHOW,
+    DIALPAD_REQUEST_HIDE,
+  })
+  @interface DialpadRequestType {}
 
-  private static final String DIALPAD_TEXT_KEY = "InCallActivity.dialpad_text";
+  private static final int DIALPAD_REQUEST_NONE = 1;
+  private static final int DIALPAD_REQUEST_SHOW = 2;
+  private static final int DIALPAD_REQUEST_HIDE = 3;
 
-  private static final String INTENT_EXTRA_SHOW_DIALPAD = "InCallActivity.show_dialpad";
+  private static Optional<Integer> audioRouteForTesting = Optional.absent();
 
-  private static final String TAG_ANSWER_SCREEN = "tag_answer_screen";
-  private static final String TAG_DIALPAD_FRAGMENT = "tag_dialpad_fragment";
-  private static final String TAG_INTERNATIONAL_CALL_ON_WIFI = "tag_international_call_on_wifi";
-  private static final String TAG_IN_CALL_SCREEN = "tag_in_call_screen";
-  private static final String TAG_VIDEO_CALL_SCREEN = "tag_video_call_screen";
+  private final InternationalCallOnWifiCallback internationalCallOnWifiCallback =
+      new InternationalCallOnWifiCallback();
+  private final SelectPhoneAccountListener selectPhoneAccountListener =
+      new SelectPhoneAccountListener();
 
-  private static final String DID_SHOW_ANSWER_SCREEN_KEY = "did_show_answer_screen";
-  private static final String DID_SHOW_IN_CALL_SCREEN_KEY = "did_show_in_call_screen";
-  private static final String DID_SHOW_VIDEO_CALL_SCREEN_KEY = "did_show_video_call_screen";
-
-  private static final String CONFIG_ANSWER_AND_RELEASE_ENABLED = "answer_and_release_enabled";
-
-  private final InCallActivityCommon common;
+  private Animation dialpadSlideInAnimation;
+  private Animation dialpadSlideOutAnimation;
+  private Dialog errorDialog;
+  private GradientDrawable backgroundDrawable;
   private InCallOrientationEventListener inCallOrientationEventListener;
+  private View pseudoBlackScreenOverlay;
+  private SelectPhoneAccountDialogFragment selectPhoneAccountDialogFragment;
+  private String dtmfTextToPrepopulate;
+  private String showPostCharWaitDialogCallId;
+  private String showPostCharWaitDialogChars;
+  private boolean allowOrientationChange;
+  private boolean animateDialpadOnShow;
   private boolean didShowAnswerScreen;
   private boolean didShowInCallScreen;
   private boolean didShowVideoCallScreen;
   private boolean dismissKeyguard;
-  private int[] backgroundDrawableColors;
-  private GradientDrawable backgroundDrawable;
-  private boolean isVisible;
-  private View pseudoBlackScreenOverlay;
-  private boolean touchDownWhenPseudoScreenOff;
   private boolean isInShowMainInCallFragment;
+  private boolean isRecreating; // whether the activity is going to be recreated
+  private boolean isVisible;
   private boolean needDismissPendingDialogs;
-  private boolean allowOrientationChange;
-
-  public InCallActivity() {
-    common = new InCallActivityCommon(this);
-  }
+  private boolean showPostCharWaitDialogOnResume;
+  private boolean touchDownWhenPseudoScreenOff;
+  private int[] backgroundDrawableColors;
+  @DialpadRequestType private int showDialpadRequest = DIALPAD_REQUEST_NONE;
 
   public static Intent getIntent(
       Context context, boolean showDialpad, boolean newOutgoingCall, boolean isForFullScreen) {
     Intent intent = new Intent(Intent.ACTION_MAIN, null);
     intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
     intent.setClass(context, InCallActivity.class);
-    InCallActivityCommon.setIntentExtras(intent, showDialpad, newOutgoingCall, isForFullScreen);
+    if (showDialpad) {
+      intent.putExtra(IntentExtraNames.SHOW_DIALPAD, true);
+    }
+    intent.putExtra(IntentExtraNames.NEW_OUTGOING_CALL, newOutgoingCall);
+    intent.putExtra(IntentExtraNames.FOR_FULL_SCREEN, isForFullScreen);
     return intent;
   }
 
@@ -142,23 +170,75 @@
   }
 
   @Override
-  protected void onCreate(Bundle icicle) {
+  protected void onCreate(Bundle bundle) {
     Trace.beginSection("InCallActivity.onCreate");
-    LogUtil.i("InCallActivity.onCreate", "");
-    super.onCreate(icicle);
+    super.onCreate(bundle);
 
     if (getIntent().getBooleanExtra(ReturnToCallController.RETURN_TO_CALL_EXTRA_KEY, false)) {
       Logger.get(this).logImpression(DialerImpression.Type.BUBBLE_PRIMARY_BUTTON_RETURN_TO_CALL);
       getIntent().removeExtra(ReturnToCallController.RETURN_TO_CALL_EXTRA_KEY);
     }
 
-    if (icicle != null) {
-      didShowAnswerScreen = icicle.getBoolean(DID_SHOW_ANSWER_SCREEN_KEY);
-      didShowInCallScreen = icicle.getBoolean(DID_SHOW_IN_CALL_SCREEN_KEY);
-      didShowVideoCallScreen = icicle.getBoolean(DID_SHOW_VIDEO_CALL_SCREEN_KEY);
+    if (bundle != null) {
+      didShowAnswerScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_ANSWER_SCREEN);
+      didShowInCallScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_IN_CALL_SCREEN);
+      didShowVideoCallScreen = bundle.getBoolean(KeysForSavedInstance.DID_SHOW_VIDEO_CALL_SCREEN);
     }
 
-    common.onCreate(icicle);
+    setWindowFlags();
+    setContentView(R.layout.incall_screen);
+    internalResolveIntent(getIntent());
+
+    boolean isLandscape =
+        getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
+    boolean isRtl = ViewUtil.isRtl();
+    if (isLandscape) {
+      dialpadSlideInAnimation =
+          AnimationUtils.loadAnimation(
+              this, isRtl ? R.anim.dialpad_slide_in_left : R.anim.dialpad_slide_in_right);
+      dialpadSlideOutAnimation =
+          AnimationUtils.loadAnimation(
+              this, isRtl ? R.anim.dialpad_slide_out_left : R.anim.dialpad_slide_out_right);
+    } else {
+      dialpadSlideInAnimation = AnimationUtils.loadAnimation(this, R.anim.dialpad_slide_in_bottom);
+      dialpadSlideOutAnimation =
+          AnimationUtils.loadAnimation(this, R.anim.dialpad_slide_out_bottom);
+    }
+    dialpadSlideInAnimation.setInterpolator(AnimUtils.EASE_IN);
+    dialpadSlideOutAnimation.setInterpolator(AnimUtils.EASE_OUT);
+    dialpadSlideOutAnimation.setAnimationListener(
+        new AnimationListenerAdapter() {
+          @Override
+          public void onAnimationEnd(Animation animation) {
+            hideDialpadFragment();
+          }
+        });
+
+    if (bundle != null && showDialpadRequest == DIALPAD_REQUEST_NONE) {
+      // If the dialpad was shown before, set related variables so that it can be shown and
+      // populated with the previous DTMF text during onResume().
+      if (bundle.containsKey(IntentExtraNames.SHOW_DIALPAD)) {
+        boolean showDialpad = bundle.getBoolean(IntentExtraNames.SHOW_DIALPAD);
+        showDialpadRequest = showDialpad ? DIALPAD_REQUEST_SHOW : DIALPAD_REQUEST_HIDE;
+        animateDialpadOnShow = false;
+      }
+      dtmfTextToPrepopulate = bundle.getString(KeysForSavedInstance.DIALPAD_TEXT);
+
+      SelectPhoneAccountDialogFragment selectPhoneAccountDialogFragment =
+          (SelectPhoneAccountDialogFragment)
+              getFragmentManager().findFragmentByTag(Tags.SELECT_ACCOUNT_FRAGMENT);
+      if (selectPhoneAccountDialogFragment != null) {
+        selectPhoneAccountDialogFragment.setListener(selectPhoneAccountListener);
+      }
+    }
+
+    InternationalCallOnWifiDialogFragment existingInternationalCallOnWifiDialogFragment =
+        (InternationalCallOnWifiDialogFragment)
+            getSupportFragmentManager().findFragmentByTag(Tags.INTERNATIONAL_CALL_ON_WIFI);
+    if (existingInternationalCallOnWifiDialogFragment != null) {
+      existingInternationalCallOnWifiDialogFragment.setCallback(internationalCallOnWifiCallback);
+    }
+
     inCallOrientationEventListener = new InCallOrientationEventListener(this);
 
     getWindow()
@@ -175,20 +255,138 @@
         .logStopLatencyTimer(LoggingBindings.ON_CALL_ADDED_TO_ON_INCALL_UI_SHOWN_OUTGOING);
   }
 
+  private void setWindowFlags() {
+    // Allow the activity to be shown when the screen is locked and filter out touch events that are
+    // "too fat".
+    int flags =
+        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+            | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+
+    // When the audio stream is not directed through Bluetooth, turn the screen on once the
+    // activity is shown.
+    final int audioRoute = getAudioRoute();
+    if (audioRoute != CallAudioState.ROUTE_BLUETOOTH) {
+      flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
+    }
+
+    getWindow().addFlags(flags);
+  }
+
+  private static int getAudioRoute() {
+    if (audioRouteForTesting.isPresent()) {
+      return audioRouteForTesting.get();
+    }
+
+    return AudioModeProvider.getInstance().getAudioState().getRoute();
+  }
+
+  @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+  public static void setAudioRouteForTesting(int audioRoute) {
+    audioRouteForTesting = Optional.of(audioRoute);
+  }
+
+  private void internalResolveIntent(Intent intent) {
+    if (!intent.getAction().equals(Intent.ACTION_MAIN)) {
+      return;
+    }
+
+    if (intent.hasExtra(IntentExtraNames.SHOW_DIALPAD)) {
+      // IntentExtraNames.SHOW_DIALPAD can be used to specify whether the DTMF dialpad should be
+      // initially visible.  If the extra is absent, leave the dialpad in its previous state.
+      boolean showDialpad = intent.getBooleanExtra(IntentExtraNames.SHOW_DIALPAD, false);
+      relaunchedFromDialer(showDialpad);
+    }
+
+    DialerCall outgoingCall = CallList.getInstance().getOutgoingCall();
+    if (outgoingCall == null) {
+      outgoingCall = CallList.getInstance().getPendingOutgoingCall();
+    }
+    if (intent.getBooleanExtra(IntentExtraNames.NEW_OUTGOING_CALL, false)) {
+      intent.removeExtra(IntentExtraNames.NEW_OUTGOING_CALL);
+
+      // InCallActivity is responsible for disconnecting a new outgoing call if there is no way of
+      // making it (i.e. no valid call capable accounts).
+      // If the version is not MSIM compatible, ignore this code.
+      if (CompatUtils.isMSIMCompatible()
+          && InCallPresenter.isCallWithNoValidAccounts(outgoingCall)) {
+        LogUtil.i(
+            "InCallActivity.internalResolveIntent", "Call with no valid accounts, disconnecting");
+        outgoingCall.disconnect();
+      }
+
+      dismissKeyguard(true);
+    }
+
+    if (showPhoneAccountSelectionDialog()) {
+      hideMainInCallFragment();
+    }
+  }
+
+  /**
+   * When relaunching from the dialer app, {@code showDialpad} indicates whether the dialpad should
+   * be shown on launch.
+   *
+   * @param showDialpad {@code true} to indicate the dialpad should be shown on launch, and {@code
+   *     false} to indicate no change should be made to the dialpad visibility.
+   */
+  private void relaunchedFromDialer(boolean showDialpad) {
+    showDialpadRequest = showDialpad ? DIALPAD_REQUEST_SHOW : DIALPAD_REQUEST_NONE;
+    animateDialpadOnShow = true;
+
+    if (showDialpadRequest == DIALPAD_REQUEST_SHOW) {
+      // If there's only one line in use, AND it's on hold, then we're sure the user
+      // wants to use the dialpad toward the exact line, so un-hold the holding line.
+      DialerCall call = CallList.getInstance().getActiveOrBackgroundCall();
+      if (call != null && call.getState() == State.ONHOLD) {
+        call.unhold();
+      }
+    }
+  }
+
+  /**
+   * Show a phone account selection dialog if there is a call waiting for phone account selection.
+   *
+   * @return true if the dialog was shown.
+   */
+  private boolean showPhoneAccountSelectionDialog() {
+    DialerCall waitingForAccountCall = CallList.getInstance().getWaitingForAccountCall();
+    if (waitingForAccountCall == null) {
+      return false;
+    }
+
+    Bundle extras = waitingForAccountCall.getIntentExtras();
+    List<PhoneAccountHandle> phoneAccountHandles =
+        extras == null
+            ? new ArrayList<>()
+            : extras.getParcelableArrayList(android.telecom.Call.AVAILABLE_PHONE_ACCOUNTS);
+
+    selectPhoneAccountDialogFragment =
+        SelectPhoneAccountDialogFragment.newInstance(
+            R.string.select_phone_account_for_calls,
+            true /* canSetDefault */,
+            0 /* setDefaultResId */,
+            phoneAccountHandles,
+            selectPhoneAccountListener,
+            waitingForAccountCall.getId(),
+            null /* hints */);
+    selectPhoneAccountDialogFragment.show(getFragmentManager(), Tags.SELECT_ACCOUNT_FRAGMENT);
+    return true;
+  }
+
   @Override
   protected void onSaveInstanceState(Bundle out) {
     LogUtil.enterBlock("InCallActivity.onSaveInstanceState");
 
     // TODO: DialpadFragment should handle this as part of its own state
-    out.putBoolean(INTENT_EXTRA_SHOW_DIALPAD, isDialpadVisible());
+    out.putBoolean(IntentExtraNames.SHOW_DIALPAD, isDialpadVisible());
     DialpadFragment dialpadFragment = getDialpadFragment();
     if (dialpadFragment != null) {
-      out.putString(DIALPAD_TEXT_KEY, dialpadFragment.getDtmfText());
+      out.putString(KeysForSavedInstance.DIALPAD_TEXT, dialpadFragment.getDtmfText());
     }
 
-    out.putBoolean(DID_SHOW_ANSWER_SCREEN_KEY, didShowAnswerScreen);
-    out.putBoolean(DID_SHOW_IN_CALL_SCREEN_KEY, didShowInCallScreen);
-    out.putBoolean(DID_SHOW_VIDEO_CALL_SCREEN_KEY, didShowVideoCallScreen);
+    out.putBoolean(KeysForSavedInstance.DID_SHOW_ANSWER_SCREEN, didShowAnswerScreen);
+    out.putBoolean(KeysForSavedInstance.DID_SHOW_IN_CALL_SCREEN, didShowInCallScreen);
+    out.putBoolean(KeysForSavedInstance.DID_SHOW_VIDEO_CALL_SCREEN, didShowVideoCallScreen);
 
     super.onSaveInstanceState(out);
     isVisible = false;
@@ -220,9 +418,45 @@
   @Override
   protected void onResume() {
     Trace.beginSection("InCallActivity.onResume");
-    LogUtil.i("InCallActivity.onResume", "");
     super.onResume();
-    common.onResume();
+
+    if (!InCallPresenter.getInstance().isReadyForTearDown()) {
+      updateTaskDescription();
+      InCallPresenter.getInstance().onUiShowing(true);
+    }
+
+    // If there is a pending request to show or hide the dialpad, handle that now.
+    if (showDialpadRequest != DIALPAD_REQUEST_NONE) {
+      if (showDialpadRequest == DIALPAD_REQUEST_SHOW) {
+        // Exit fullscreen so that the user has access to the dialpad hide/show button.
+        // This is important when showing the dialpad from within dialer.
+        InCallPresenter.getInstance().setFullScreen(false /* isFullScreen */, true /* force */);
+
+        showDialpadFragment(true /* show */, animateDialpadOnShow /* animate */);
+        animateDialpadOnShow = false;
+
+        DialpadFragment dialpadFragment = getDialpadFragment();
+        if (dialpadFragment != null) {
+          dialpadFragment.setDtmfText(dtmfTextToPrepopulate);
+          dtmfTextToPrepopulate = null;
+        }
+      } else {
+        LogUtil.i("InCallActivity.onResume", "Force-hide the dialpad");
+        if (getDialpadFragment() != null) {
+          showDialpadFragment(false /* show */, false /* animate */);
+        }
+      }
+      showDialpadRequest = DIALPAD_REQUEST_NONE;
+    }
+    updateNavigationBar(isDialpadVisible());
+
+    if (showPostCharWaitDialogOnResume) {
+      showDialogForPostCharWait(showPostCharWaitDialogCallId, showPostCharWaitDialogChars);
+    }
+
+    CallList.getInstance()
+        .onInCallUiShown(getIntent().getBooleanExtra(IntentExtraNames.FOR_FULL_SCREEN, false));
+
     PseudoScreenState pseudoScreenState = InCallPresenter.getInstance().getPseudoScreenState();
     pseudoScreenState.addListener(this);
     onPseudoScreenStateChanged(pseudoScreenState.isOn());
@@ -266,7 +500,7 @@
     // be created.
     // Skip this when the screen is locked since the activity may complete its current life cycle
     // and restart.
-    if (!common.getIsRecreating() && !getSystemService(KeyguardManager.class).isKeyguardLocked()) {
+    if (!isRecreating && !getSystemService(KeyguardManager.class).isKeyguardLocked()) {
       DialerCall waitingForAccountCall = CallList.getInstance().getWaitingForAccountCall();
       if (waitingForAccountCall != null) {
         waitingForAccountCall.disconnect();
@@ -276,8 +510,7 @@
     enableInCallOrientationEventListener(false);
     InCallPresenter.getInstance().updateIsChangingConfigurations();
     InCallPresenter.getInstance().onActivityStopped();
-    if (!common.getIsRecreating()) {
-      Dialog errorDialog = common.getErrorDialog();
+    if (!isRecreating) {
       if (errorDialog != null) {
         errorDialog.dismiss();
       }
@@ -319,7 +552,7 @@
   }
 
   private boolean shouldCloseActivityOnFinish() {
-    if (!isVisible()) {
+    if (!isVisible) {
       LogUtil.i(
           "InCallActivity.shouldCloseActivityOnFinish",
           "allowing activity to be closed because it's not visible");
@@ -341,19 +574,40 @@
 
   @Override
   protected void onNewIntent(Intent intent) {
-    LogUtil.i("InCallActivity.onNewIntent", "");
+    LogUtil.enterBlock("InCallActivity.onNewIntent");
 
     // If the screen is off, we need to make sure it gets turned on for incoming calls.
     // This normally works just fine thanks to FLAG_TURN_SCREEN_ON but that only works
     // when the activity is first created. Therefore, to ensure the screen is turned on
     // for the call waiting case, we recreate() the current activity. There should be no jank from
     // this since the screen is already off and will remain so until our new activity is up.
-    if (!isVisible()) {
-      common.onNewIntent(intent, true /* isRecreating */);
+    if (!isVisible) {
+      onNewIntent(intent, true /* isRecreating */);
       LogUtil.i("InCallActivity.onNewIntent", "Restarting InCallActivity to force screen on.");
       recreate();
     } else {
-      common.onNewIntent(intent, false /* isRecreating */);
+      onNewIntent(intent, false /* isRecreating */);
+    }
+  }
+
+  private void onNewIntent(Intent intent, boolean isRecreating) {
+    this.isRecreating = isRecreating;
+
+    // We're being re-launched with a new Intent.  Since it's possible for a single InCallActivity
+    // instance to persist indefinitely (even if we finish() ourselves), this sequence can
+    // happen any time the InCallActivity needs to be displayed.
+
+    // Stash away the new intent so that we can get it in the future by calling getIntent().
+    // Otherwise getIntent() will return the original Intent from when we first got created.
+    setIntent(intent);
+
+    // Activities are always paused before receiving a new intent, so we can count on our onResume()
+    // method being called next.
+
+    // Just like in onCreate(), handle the intent.
+    // Skip if InCallActivity is going to be recreated since this will be called in onCreate().
+    if (!isRecreating) {
+      internalResolveIntent(intent);
     }
   }
 
@@ -361,7 +615,7 @@
   public void onBackPressed() {
     LogUtil.enterBlock("InCallActivity.onBackPressed");
 
-    if (!isVisible()) {
+    if (!isVisible) {
       return;
     }
 
@@ -483,14 +737,78 @@
     }
   }
 
-  public boolean showDialpadFragment(boolean show, boolean animate) {
-    boolean didChange = common.showDialpadFragment(show, animate);
-    if (didChange) {
-      // Note:  onInCallScreenDialpadVisibilityChange is called here to ensure that the dialpad FAB
-      // repositions itself.
-      getInCallScreen().onInCallScreenDialpadVisibilityChange(show);
+  public void showDialpadFragment(boolean show, boolean animate) {
+    if (show == isDialpadVisible()) {
+      return;
     }
-    return didChange;
+
+    FragmentManager dialpadFragmentManager = getDialpadFragmentManager();
+    if (dialpadFragmentManager == null) {
+      LogUtil.i("InCallActivity.showDialpadFragment", "Unable to obtain a FragmentManager");
+      return;
+    }
+
+    if (!animate) {
+      if (show) {
+        showDialpadFragment();
+      } else {
+        hideDialpadFragment();
+      }
+    } else {
+      if (show) {
+        showDialpadFragment();
+        getDialpadFragment().animateShowDialpad();
+      }
+      getDialpadFragment()
+          .getView()
+          .startAnimation(show ? dialpadSlideInAnimation : dialpadSlideOutAnimation);
+    }
+
+    ProximitySensor sensor = InCallPresenter.getInstance().getProximitySensor();
+    if (sensor != null) {
+      sensor.onDialpadVisible(show);
+    }
+    showDialpadRequest = DIALPAD_REQUEST_NONE;
+
+    // Note:  onInCallScreenDialpadVisibilityChange is called here to ensure that the dialpad FAB
+    // repositions itself.
+    getInCallScreen().onInCallScreenDialpadVisibilityChange(show);
+  }
+
+  private void showDialpadFragment() {
+    FragmentManager dialpadFragmentManager = getDialpadFragmentManager();
+    if (dialpadFragmentManager == null) {
+      return;
+    }
+
+    FragmentTransaction transaction = dialpadFragmentManager.beginTransaction();
+    DialpadFragment dialpadFragment = getDialpadFragment();
+    if (dialpadFragment == null) {
+      transaction.add(getDialpadContainerId(), new DialpadFragment(), Tags.DIALPAD_FRAGMENT);
+    } else {
+      transaction.show(dialpadFragment);
+    }
+    transaction.commitAllowingStateLoss();
+    dialpadFragmentManager.executePendingTransactions();
+
+    Logger.get(this).logScreenView(ScreenEvent.Type.INCALL_DIALPAD, this);
+    updateNavigationBar(true /* isDialpadVisible */);
+  }
+
+  private void hideDialpadFragment() {
+    FragmentManager dialpadFragmentManager = getDialpadFragmentManager();
+    if (dialpadFragmentManager == null) {
+      return;
+    }
+
+    Fragment dialpadFragment = dialpadFragmentManager.findFragmentByTag(Tags.DIALPAD_FRAGMENT);
+    if (dialpadFragment != null) {
+      FragmentTransaction transaction = dialpadFragmentManager.beginTransaction();
+      transaction.hide(dialpadFragment);
+      transaction.commitAllowingStateLoss();
+      dialpadFragmentManager.executePendingTransactions();
+    }
+    updateNavigationBar(false /* isDialpadVisible */);
   }
 
   public boolean isDialpadVisible() {
@@ -498,17 +816,14 @@
     return dialpadFragment != null && dialpadFragment.isVisible();
   }
 
-  /**
-   * Returns the {@link DialpadFragment} that's shown by this activity, or {@code null}
-   * TODO(a bug): Make this method private after InCallActivityCommon is deleted.
-   */
+  /** Returns the {@link DialpadFragment} that's shown by this activity, or {@code null} */
   @Nullable
-  DialpadFragment getDialpadFragment() {
+  private DialpadFragment getDialpadFragment() {
     FragmentManager fragmentManager = getDialpadFragmentManager();
     if (fragmentManager == null) {
       return null;
     }
-    return (DialpadFragment) fragmentManager.findFragmentByTag(TAG_DIALPAD_FRAGMENT);
+    return (DialpadFragment) fragmentManager.findFragmentByTag(Tags.DIALPAD_FRAGMENT);
   }
 
   public void onForegroundCallChanged(DialerCall newForegroundCall) {
@@ -520,8 +835,7 @@
     }
   }
 
-  // TODO(a bug): Make this method private after InCallActivityCommon is deleted.
-  void updateTaskDescription() {
+  private void updateTaskDescription() {
     int color =
         getResources().getBoolean(R.bool.is_layout_landscape)
             ? ResourcesCompat.getColor(
@@ -605,8 +919,19 @@
     }
   }
 
-  public void showPostCharWaitDialog(String callId, String chars) {
-    common.showPostCharWaitDialog(callId, chars);
+  public void showDialogForPostCharWait(String callId, String chars) {
+    if (isVisible) {
+      PostCharDialogFragment fragment = new PostCharDialogFragment(callId, chars);
+      fragment.show(getSupportFragmentManager(), Tags.POST_CHAR_DIALOG_FRAGMENT);
+
+      showPostCharWaitDialogOnResume = false;
+      showPostCharWaitDialogCallId = null;
+      showPostCharWaitDialogChars = null;
+    } else {
+      showPostCharWaitDialogOnResume = true;
+      showPostCharWaitDialogCallId = callId;
+      showPostCharWaitDialogChars = chars;
+    }
   }
 
   public void showDialogOrToastForDisconnectedCall(DisconnectMessage disconnectMessage) {
@@ -629,7 +954,7 @@
     }
 
     // Show the dialog.
-    common.setErrorDialog(disconnectMessage.dialog);
+    errorDialog = disconnectMessage.dialog;
     InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("showErrorDialog");
     disconnectMessage.dialog.setOnDismissListener(
         dialogInterface -> {
@@ -641,12 +966,12 @@
   }
 
   private void onDialogDismissed() {
-    common.setErrorDialog(null);
+    errorDialog = null;
     CallList.getInstance().onErrorDialogDismissed();
   }
 
   public void dismissPendingDialogs() {
-    LogUtil.i("InCallActivity.dismissPendingDialogs", "");
+    LogUtil.enterBlock("InCallActivity.dismissPendingDialogs");
 
     if (!isVisible) {
       // Defer the dismissing action as the activity is not visible and onSaveInstanceState may have
@@ -658,24 +983,21 @@
     }
 
     // Dismiss the error dialog
-    Dialog errorDialog = common.getErrorDialog();
     if (errorDialog != null) {
       errorDialog.dismiss();
-      common.setErrorDialog(null);
+      errorDialog = null;
     }
 
     // Dismiss the phone account selection dialog
-    SelectPhoneAccountDialogFragment selectPhoneAccountDialogFragment =
-        common.getSelectPhoneAccountDialogFragment();
     if (selectPhoneAccountDialogFragment != null) {
       selectPhoneAccountDialogFragment.dismiss();
-      common.setSelectPhoneAccountDialogFragment(null);
+      selectPhoneAccountDialogFragment = null;
     }
 
     // Dismiss the dialog for international call on WiFi
     InternationalCallOnWifiDialogFragment internationalCallOnWifiFragment =
         (InternationalCallOnWifiDialogFragment)
-            getSupportFragmentManager().findFragmentByTag(TAG_INTERNATIONAL_CALL_ON_WIFI);
+            getSupportFragmentManager().findFragmentByTag(Tags.INTERNATIONAL_CALL_ON_WIFI);
     if (internationalCallOnWifiFragment != null) {
       internationalCallOnWifiFragment.dismiss();
     }
@@ -689,8 +1011,7 @@
     needDismissPendingDialogs = false;
   }
 
-  // TODO(a bug): Make this method private after InCallActivityCommon is deleted.
-  void enableInCallOrientationEventListener(boolean enable) {
+  private void enableInCallOrientationEventListener(boolean enable) {
     if (enable) {
       inCallOrientationEventListener.enable(true /* notifyDeviceOrientationChange */);
     } else {
@@ -699,7 +1020,18 @@
   }
 
   public void setExcludeFromRecents(boolean exclude) {
-    common.setExcludeFromRecents(exclude);
+    int taskId = getTaskId();
+
+    List<AppTask> tasks = getSystemService(ActivityManager.class).getAppTasks();
+    for (AppTask task : tasks) {
+      try {
+        if (task.getTaskInfo().id == taskId) {
+          task.setExcludeFromRecents(exclude);
+        }
+      } catch (RuntimeException e) {
+        LogUtil.e("InCallActivity.setExcludeFromRecents", "RuntimeException:\n%s", e);
+      }
+    }
   }
 
   @Nullable
@@ -756,7 +1088,6 @@
 
   public void onPrimaryCallStateChanged() {
     Trace.beginSection("InCallActivity.onPrimaryCallStateChanged");
-    LogUtil.i("InCallActivity.onPrimaryCallStateChanged", "");
     showMainInCallFragment();
     Trace.endSection();
   }
@@ -790,7 +1121,7 @@
     wifiHandoverFailureCheckbox.setChecked(false);
 
     InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("WifiFailedDialog");
-    Dialog errorDialog =
+    errorDialog =
         builder
             .setView(dialogCheckBoxView)
             .setMessage(R.string.video_call_lte_to_wifi_failed_message)
@@ -805,8 +1136,6 @@
                 })
             .setOnDismissListener(dialogInterface -> lock.release())
             .create();
-
-    common.setErrorDialog(errorDialog);
     errorDialog.show();
   }
 
@@ -820,8 +1149,8 @@
 
     InternationalCallOnWifiDialogFragment fragment =
         InternationalCallOnWifiDialogFragment.newInstance(
-            call.getId(), common.getCallbackForInternationalCallOnWifiDialog());
-    fragment.show(getSupportFragmentManager(), TAG_INTERNATIONAL_CALL_ON_WIFI);
+            call.getId(), internationalCallOnWifiCallback);
+    fragment.show(getSupportFragmentManager(), Tags.INTERNATIONAL_CALL_ON_WIFI);
   }
 
   @Override
@@ -830,8 +1159,7 @@
     updateNavigationBar(isDialpadVisible());
   }
 
-  // TODO(a bug): Make this method private after InCallActivityCommon is deleted.
-  void updateNavigationBar(boolean isDialpadVisible) {
+  private void updateNavigationBar(boolean isDialpadVisible) {
     if (ActivityCompat.isInMultiWindowMode(this)) {
       return;
     }
@@ -856,8 +1184,8 @@
   }
 
   public void hideMainInCallFragment() {
-    LogUtil.i("InCallActivity.hideMainInCallFragment", "");
-    if (didShowInCallScreen || didShowVideoCallScreen) {
+    LogUtil.enterBlock("InCallActivity.hideMainInCallFragment");
+    if (getCallCardFragmentVisible()) {
       FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
       hideInCallScreenFragment(transaction);
       hideVideoCallScreenFragment(transaction);
@@ -1017,7 +1345,7 @@
             call.getVideoTech().isSelfManagedCamera(),
             shouldAllowAnswerAndRelease(call),
             CallList.getInstance().getBackgroundCall() != null);
-    transaction.add(R.id.main, answerScreen.getAnswerScreenFragment(), TAG_ANSWER_SCREEN);
+    transaction.add(R.id.main, answerScreen.getAnswerScreenFragment(), Tags.ANSWER_SCREEN);
 
     Logger.get(this).logScreenView(ScreenEvent.Type.INCOMING_CALL, this);
     didShowAnswerScreen = true;
@@ -1038,7 +1366,8 @@
       LogUtil.i("InCallActivity.shouldAllowAnswerAndRelease", "video call");
       return false;
     }
-    if (!ConfigProviderBindings.get(this).getBoolean(CONFIG_ANSWER_AND_RELEASE_ENABLED, true)) {
+    if (!ConfigProviderBindings.get(this)
+        .getBoolean(ConfigNames.ANSWER_AND_RELEASE_ENABLED, true)) {
       LogUtil.i("InCallActivity.shouldAllowAnswerAndRelease", "disabled by config");
       return false;
     }
@@ -1064,7 +1393,7 @@
       return false;
     }
     InCallScreen inCallScreen = InCallBindings.createInCallScreen();
-    transaction.add(R.id.main, inCallScreen.getInCallScreenFragment(), TAG_IN_CALL_SCREEN);
+    transaction.add(R.id.main, inCallScreen.getInCallScreenFragment(), Tags.IN_CALL_SCREEN);
     Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
     didShowInCallScreen = true;
     return true;
@@ -1099,7 +1428,8 @@
     VideoCallScreen videoCallScreen =
         VideoBindings.createVideoCallScreen(
             call.getId(), call.getVideoTech().shouldUseSurfaceView());
-    transaction.add(R.id.main, videoCallScreen.getVideoCallScreenFragment(), TAG_VIDEO_CALL_SCREEN);
+    transaction.add(
+        R.id.main, videoCallScreen.getVideoCallScreenFragment(), Tags.VIDEO_CALL_SCREEN);
 
     Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
     didShowVideoCallScreen = true;
@@ -1118,16 +1448,16 @@
     return true;
   }
 
-  AnswerScreen getAnswerScreen() {
-    return (AnswerScreen) getSupportFragmentManager().findFragmentByTag(TAG_ANSWER_SCREEN);
+  private AnswerScreen getAnswerScreen() {
+    return (AnswerScreen) getSupportFragmentManager().findFragmentByTag(Tags.ANSWER_SCREEN);
   }
 
-  InCallScreen getInCallScreen() {
-    return (InCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_IN_CALL_SCREEN);
+  private InCallScreen getInCallScreen() {
+    return (InCallScreen) getSupportFragmentManager().findFragmentByTag(Tags.IN_CALL_SCREEN);
   }
 
-  VideoCallScreen getVideoCallScreen() {
-    return (VideoCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_VIDEO_CALL_SCREEN);
+  private VideoCallScreen getVideoCallScreen() {
+    return (VideoCallScreen) getSupportFragmentManager().findFragmentByTag(Tags.VIDEO_CALL_SCREEN);
   }
 
   @Override
@@ -1171,4 +1501,86 @@
       this.call = call;
     }
   }
+
+  private static final class IntentExtraNames {
+    static final String FOR_FULL_SCREEN = "InCallActivity.for_full_screen_intent";
+    static final String NEW_OUTGOING_CALL = "InCallActivity.new_outgoing_call";
+    static final String SHOW_DIALPAD = "InCallActivity.show_dialpad";
+  }
+
+  private static final class KeysForSavedInstance {
+    static final String DIALPAD_TEXT = "InCallActivity.dialpad_text";
+    static final String DID_SHOW_ANSWER_SCREEN = "did_show_answer_screen";
+    static final String DID_SHOW_IN_CALL_SCREEN = "did_show_in_call_screen";
+    static final String DID_SHOW_VIDEO_CALL_SCREEN = "did_show_video_call_screen";
+  }
+
+  /** Request codes for pending intents. */
+  public static final class PendingIntentRequestCodes {
+    static final int NON_FULL_SCREEN = 0;
+    static final int FULL_SCREEN = 1;
+    static final int BUBBLE = 2;
+  }
+
+  private static final class Tags {
+    static final String ANSWER_SCREEN = "tag_answer_screen";
+    static final String DIALPAD_FRAGMENT = "tag_dialpad_fragment";
+    static final String IN_CALL_SCREEN = "tag_in_call_screen";
+    static final String INTERNATIONAL_CALL_ON_WIFI = "tag_international_call_on_wifi";
+    static final String SELECT_ACCOUNT_FRAGMENT = "tag_select_account_fragment";
+    static final String VIDEO_CALL_SCREEN = "tag_video_call_screen";
+    static final String POST_CHAR_DIALOG_FRAGMENT = "tag_post_char_dialog_fragment";
+  }
+
+  private static final class ConfigNames {
+    static final String ANSWER_AND_RELEASE_ENABLED = "answer_and_release_enabled";
+  }
+
+  private static final class InternationalCallOnWifiCallback
+      implements InternationalCallOnWifiDialogFragment.Callback {
+    private static final String TAG = InternationalCallOnWifiCallback.class.getCanonicalName();
+
+    @Override
+    public void continueCall(@NonNull String callId) {
+      LogUtil.i(TAG, "Continuing call with ID: %s", callId);
+    }
+
+    @Override
+    public void cancelCall(@NonNull String callId) {
+      DialerCall call = CallList.getInstance().getCallById(callId);
+      if (call == null) {
+        LogUtil.i(TAG, "Call destroyed before the dialog is closed");
+        return;
+      }
+
+      LogUtil.i(TAG, "Disconnecting international call on WiFi");
+      call.disconnect();
+    }
+  }
+
+  private static final class SelectPhoneAccountListener
+      extends SelectPhoneAccountDialogFragment.SelectPhoneAccountListener {
+    private static final String TAG = SelectPhoneAccountListener.class.getCanonicalName();
+
+    @Override
+    public void onPhoneAccountSelected(
+        PhoneAccountHandle selectedAccountHandle, boolean setDefault, String callId) {
+      DialerCall call = CallList.getInstance().getCallById(callId);
+      LogUtil.i(TAG, "Phone account select with call:\n%s", call);
+
+      if (call != null) {
+        call.phoneAccountSelected(selectedAccountHandle, setDefault);
+      }
+    }
+
+    @Override
+    public void onDialogDismissed(String callId) {
+      DialerCall call = CallList.getInstance().getCallById(callId);
+      LogUtil.i(TAG, "Disconnecting call:\n%s" + call);
+
+      if (call != null) {
+        call.disconnect();
+      }
+    }
+  }
 }