Add simulator RTT call.

This change will also:
1. Disable proximity sensor for RTT call
2. Update RTT call screen, including colors and banner buttons

Bug: 67596257
Test: presubmit
PiperOrigin-RevId: 185541897
Change-Id: I571373efbb8ced4ee2ad94879e9d37bed33b6a28
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 8769be5..67f5cfe 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -83,6 +83,10 @@
 import com.android.incallui.incall.protocol.InCallScreenDelegate;
 import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
 import com.android.incallui.incalluilock.InCallUiLock;
+import com.android.incallui.rtt.bindings.RttBindings;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegateFactory;
 import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment;
 import com.android.incallui.video.bindings.VideoBindings;
 import com.android.incallui.video.protocol.VideoCallScreen;
@@ -100,6 +104,7 @@
         InCallScreenDelegateFactory,
         InCallButtonUiDelegateFactory,
         VideoCallScreenDelegateFactory,
+        RttCallScreenDelegateFactory,
         PseudoScreenState.StateChangedListener {
 
   @Retention(RetentionPolicy.SOURCE)
@@ -136,6 +141,7 @@
   private boolean didShowAnswerScreen;
   private boolean didShowInCallScreen;
   private boolean didShowVideoCallScreen;
+  private boolean didShowRttCallScreen;
   private boolean dismissKeyguard;
   private boolean isInShowMainInCallFragment;
   private boolean isRecreating; // whether the activity is going to be recreated
@@ -1220,37 +1226,47 @@
     isInShowMainInCallFragment = true;
     ShouldShowUiResult shouldShowAnswerUi = getShouldShowAnswerUi();
     ShouldShowUiResult shouldShowVideoUi = getShouldShowVideoUi();
+    ShouldShowUiResult shouldShowRttUi = getShouldShowRttUi();
     LogUtil.i(
         "InCallActivity.showMainInCallFragment",
-        "shouldShowAnswerUi: %b, shouldShowVideoUi: %b, "
-            + "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowVideoCallScreen: %b",
+        "shouldShowAnswerUi: %b, shouldShowRttUi: %b, shouldShowVideoUi: %b "
+            + "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowRttCallScreen: %b, "
+            + "didShowVideoCallScreen: %b",
         shouldShowAnswerUi.shouldShow,
+        shouldShowRttUi.shouldShow,
         shouldShowVideoUi.shouldShow,
         didShowAnswerScreen,
         didShowInCallScreen,
+        didShowRttCallScreen,
         didShowVideoCallScreen);
     // Only video call ui allows orientation change.
     setAllowOrientationChange(shouldShowVideoUi.shouldShow);
 
     FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-    boolean didChangeInCall;
-    boolean didChangeVideo;
-    boolean didChangeAnswer;
+    boolean didChange;
     if (shouldShowAnswerUi.shouldShow) {
-      didChangeInCall = hideInCallScreenFragment(transaction);
-      didChangeVideo = hideVideoCallScreenFragment(transaction);
-      didChangeAnswer = showAnswerScreenFragment(transaction, shouldShowAnswerUi.call);
+      didChange = hideInCallScreenFragment(transaction);
+      didChange |= hideVideoCallScreenFragment(transaction);
+      didChange |= hideRttCallScreenFragment(transaction);
+      didChange |= showAnswerScreenFragment(transaction, shouldShowAnswerUi.call);
     } else if (shouldShowVideoUi.shouldShow) {
-      didChangeInCall = hideInCallScreenFragment(transaction);
-      didChangeVideo = showVideoCallScreenFragment(transaction, shouldShowVideoUi.call);
-      didChangeAnswer = hideAnswerScreenFragment(transaction);
+      didChange = hideInCallScreenFragment(transaction);
+      didChange |= showVideoCallScreenFragment(transaction, shouldShowVideoUi.call);
+      didChange |= hideRttCallScreenFragment(transaction);
+      didChange |= hideAnswerScreenFragment(transaction);
+    } else if (shouldShowRttUi.shouldShow) {
+      didChange = hideInCallScreenFragment(transaction);
+      didChange |= hideVideoCallScreenFragment(transaction);
+      didChange |= hideAnswerScreenFragment(transaction);
+      didChange |= showRttCallScreenFragment(transaction, shouldShowRttUi.call);
     } else {
-      didChangeInCall = showInCallScreenFragment(transaction);
-      didChangeVideo = hideVideoCallScreenFragment(transaction);
-      didChangeAnswer = hideAnswerScreenFragment(transaction);
+      didChange = showInCallScreenFragment(transaction);
+      didChange |= hideVideoCallScreenFragment(transaction);
+      didChange |= hideRttCallScreenFragment(transaction);
+      didChange |= hideAnswerScreenFragment(transaction);
     }
 
-    if (didChangeInCall || didChangeVideo || didChangeAnswer) {
+    if (didChange) {
       Trace.beginSection("InCallActivity.commitTransaction");
       transaction.commitNow();
       Trace.endSection();
@@ -1308,6 +1324,26 @@
     return new ShouldShowUiResult(false, null);
   }
 
+  private static ShouldShowUiResult getShouldShowRttUi() {
+    DialerCall call = CallList.getInstance().getFirstCall();
+    if (call == null) {
+      LogUtil.i("InCallActivity.getShouldShowRttUi", "null call");
+      return new ShouldShowUiResult(false, null);
+    }
+
+    if (call.isRttCall()) {
+      LogUtil.i("InCallActivity.getShouldShowRttUi", "found rtt call");
+      return new ShouldShowUiResult(true, call);
+    }
+
+    if (call.hasSentRttUpgradeRequest()) {
+      LogUtil.i("InCallActivity.getShouldShowRttUi", "upgrading to rtt");
+      return new ShouldShowUiResult(true, call);
+    }
+
+    return new ShouldShowUiResult(false, null);
+  }
+
   private boolean showAnswerScreenFragment(FragmentTransaction transaction, DialerCall call) {
     // When rejecting a call the active call can become null in which case we should continue
     // showing the answer screen.
@@ -1347,6 +1383,7 @@
     AnswerScreen answerScreen =
         AnswerBindings.createAnswerScreen(
             call.getId(),
+            call.isRttCall(),
             call.isVideoCall(),
             isVideoUpgradeRequest,
             call.getVideoTech().isSelfManagedCamera(),
@@ -1418,6 +1455,33 @@
     return true;
   }
 
+  private boolean showRttCallScreenFragment(FragmentTransaction transaction, DialerCall call) {
+    if (didShowRttCallScreen) {
+      // This shouldn't happen since only one RTT call is allow at same time.
+      if (!getRttCallScreen().getCallId().equals(call.getId())) {
+        LogUtil.e("InCallActivity.showRttCallScreenFragment", "RTT call id doesn't match");
+      }
+      return false;
+    }
+    RttCallScreen rttCallScreen = RttBindings.createRttCallScreen(call.getId());
+    transaction.add(R.id.main, rttCallScreen.getRttCallScreenFragment(), Tags.RTT_CALL_SCREEN);
+    Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
+    didShowRttCallScreen = true;
+    return true;
+  }
+
+  private boolean hideRttCallScreenFragment(FragmentTransaction transaction) {
+    if (!didShowRttCallScreen) {
+      return false;
+    }
+    RttCallScreen rttCallScreen = getRttCallScreen();
+    if (rttCallScreen != null) {
+      transaction.remove(rttCallScreen.getRttCallScreenFragment());
+    }
+    didShowRttCallScreen = false;
+    return true;
+  }
+
   private boolean showVideoCallScreenFragment(FragmentTransaction transaction, DialerCall call) {
     if (didShowVideoCallScreen) {
       VideoCallScreen videoCallScreen = getVideoCallScreen();
@@ -1467,6 +1531,10 @@
     return (VideoCallScreen) getSupportFragmentManager().findFragmentByTag(Tags.VIDEO_CALL_SCREEN);
   }
 
+  private RttCallScreen getRttCallScreen() {
+    return (RttCallScreen) getSupportFragmentManager().findFragmentByTag(Tags.RTT_CALL_SCREEN);
+  }
+
   @Override
   public void onPseudoScreenStateChanged(boolean isOn) {
     LogUtil.i("InCallActivity.onPseudoScreenStateChanged", "isOn: " + isOn);
@@ -1499,6 +1567,11 @@
     return super.dispatchTouchEvent(event);
   }
 
+  @Override
+  public RttCallScreenDelegate newRttCallScreenDelegate(RttCallScreen videoCallScreen) {
+    return new RttCallPresenter();
+  }
+
   private static class ShouldShowUiResult {
     public final boolean shouldShow;
     public final DialerCall call;
@@ -1536,6 +1609,7 @@
     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 RTT_CALL_SCREEN = "tag_rtt_call_screen";
     static final String POST_CHAR_DIALOG_FRAGMENT = "tag_post_char_dialog_fragment";
   }
 
diff --git a/java/com/android/incallui/ProximitySensor.java b/java/com/android/incallui/ProximitySensor.java
index f82b75d..4b03344 100644
--- a/java/com/android/incallui/ProximitySensor.java
+++ b/java/com/android/incallui/ProximitySensor.java
@@ -55,6 +55,7 @@
   private boolean dialpadVisible;
   private boolean isAttemptingVideoCall;
   private boolean isVideoCall;
+  private boolean isRttCall;
 
   public ProximitySensor(
       @NonNull Context context,
@@ -112,10 +113,14 @@
 
     DialerCall activeCall = callList.getActiveCall();
     boolean isVideoCall = activeCall != null && activeCall.isVideoCall();
+    boolean isRttCall = activeCall != null && activeCall.isRttCall();
 
-    if (isOffhook != isPhoneOffhook || this.isVideoCall != isVideoCall) {
+    if (isOffhook != isPhoneOffhook
+        || this.isVideoCall != isVideoCall
+        || this.isRttCall != isRttCall) {
       isPhoneOffhook = isOffhook;
       this.isVideoCall = isVideoCall;
+      this.isRttCall = isRttCall;
 
       orientation = AccelerometerListener.ORIENTATION_UNKNOWN;
       accelerometerListener.enable(isPhoneOffhook);
@@ -217,7 +222,8 @@
             || CallAudioState.ROUTE_SPEAKER == audioRoute
             || CallAudioState.ROUTE_BLUETOOTH == audioRoute
             || isAttemptingVideoCall
-            || isVideoCall);
+            || isVideoCall
+            || isRttCall);
 
     // We do not keep the screen off when the user is outside in-call screen and we are
     // horizontal, but we do not force it on when we become horizontal until the
diff --git a/java/com/android/incallui/RttCallPresenter.java b/java/com/android/incallui/RttCallPresenter.java
new file mode 100644
index 0000000..b90d56b
--- /dev/null
+++ b/java/com/android/incallui/RttCallPresenter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.incallui;
+
+import android.content.Context;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+
+/**
+ * Logic related to the {@link RttCallScreen} and for managing changes to the RTT calling surfaces
+ * based on other user interface events and incoming events.
+ */
+public class RttCallPresenter implements RttCallScreenDelegate {
+
+  private Context appContext;
+  private RttCallScreen rttCallScreen;
+
+  @Override
+  public void initRttCallScreenDelegate(Context context, RttCallScreen rttCallScreen) {
+    this.appContext = context.getApplicationContext();
+    this.rttCallScreen = rttCallScreen;
+  }
+
+  @Override
+  public void onRttCallScreenUiReady() {}
+
+  @Override
+  public void onRttCallScreenUiUnready() {}
+}
diff --git a/java/com/android/incallui/answer/bindings/AnswerBindings.java b/java/com/android/incallui/answer/bindings/AnswerBindings.java
index 0b546db..9f4199b 100644
--- a/java/com/android/incallui/answer/bindings/AnswerBindings.java
+++ b/java/com/android/incallui/answer/bindings/AnswerBindings.java
@@ -24,6 +24,7 @@
 
   public static AnswerScreen createAnswerScreen(
       String callId,
+      boolean isRttCall,
       boolean isVideoCall,
       boolean isVideoUpgradeRequest,
       boolean isSelfManagedCamera,
@@ -31,6 +32,7 @@
       boolean hasCallOnHold) {
     return AnswerFragment.newInstance(
         callId,
+        isRttCall,
         isVideoCall,
         isVideoUpgradeRequest,
         isSelfManagedCamera,
diff --git a/java/com/android/incallui/answer/impl/AnswerFragment.java b/java/com/android/incallui/answer/impl/AnswerFragment.java
index d687b6e..8626e6d 100644
--- a/java/com/android/incallui/answer/impl/AnswerFragment.java
+++ b/java/com/android/incallui/answer/impl/AnswerFragment.java
@@ -103,6 +103,8 @@
   @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
   static final String ARG_CALL_ID = "call_id";
 
+  static final String ARG_IS_RTT_CALL = "is_rtt_call";
+
   @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
   static final String ARG_IS_VIDEO_CALL = "is_video_call";
 
@@ -344,6 +346,7 @@
 
   public static AnswerFragment newInstance(
       String callId,
+      boolean isRttCall,
       boolean isVideoCall,
       boolean isVideoUpgradeRequest,
       boolean isSelfManagedCamera,
@@ -351,6 +354,7 @@
       boolean hasCallOnHold) {
     Bundle bundle = new Bundle();
     bundle.putString(ARG_CALL_ID, Assert.isNotNull(callId));
+    bundle.putBoolean(ARG_IS_RTT_CALL, isRttCall);
     bundle.putBoolean(ARG_IS_VIDEO_CALL, isVideoCall);
     bundle.putBoolean(ARG_IS_VIDEO_UPGRADE_REQUEST, isVideoUpgradeRequest);
     bundle.putBoolean(ARG_IS_SELF_MANAGED_CAMERA, isSelfManagedCamera);
@@ -663,6 +667,7 @@
     Trace.beginSection("AnswerFragment.onCreateView");
     Bundle arguments = getArguments();
     Assert.checkState(arguments.containsKey(ARG_CALL_ID));
+    Assert.checkState(arguments.containsKey(ARG_IS_RTT_CALL));
     Assert.checkState(arguments.containsKey(ARG_IS_VIDEO_CALL));
     Assert.checkState(arguments.containsKey(ARG_IS_VIDEO_UPGRADE_REQUEST));
 
@@ -836,6 +841,11 @@
   }
 
   @Override
+  public boolean isRttCall() {
+    return getArguments().getBoolean(ARG_IS_RTT_CALL);
+  }
+
+  @Override
   public boolean isVideoCall() {
     return getArguments().getBoolean(ARG_IS_VIDEO_CALL);
   }
diff --git a/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java b/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java
index afa194f..0f1455c 100644
--- a/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java
+++ b/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java
@@ -46,4 +46,6 @@
   boolean isVideoCall();
 
   boolean isVideoUpgradeRequest();
+
+  boolean isRttCall();
 }
diff --git a/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java b/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java
index fe6bbbc..b5dbc0c 100644
--- a/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java
+++ b/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java
@@ -335,6 +335,8 @@
     }
     if (getParent().isVideoCall() || getParent().isVideoUpgradeRequest()) {
       contactPuckIcon.setImageResource(R.drawable.quantum_ic_videocam_white_24);
+    } else if (getParent().isRttCall()) {
+      contactPuckIcon.setImageResource(R.drawable.quantum_ic_call_white_24);
     } else {
       contactPuckIcon.setImageResource(R.drawable.quantum_ic_call_white_24);
     }
diff --git a/java/com/android/incallui/answer/protocol/AnswerScreen.java b/java/com/android/incallui/answer/protocol/AnswerScreen.java
index 5ad5002..f030ce9 100644
--- a/java/com/android/incallui/answer/protocol/AnswerScreen.java
+++ b/java/com/android/incallui/answer/protocol/AnswerScreen.java
@@ -24,6 +24,8 @@
 
   String getCallId();
 
+  boolean isRttCall();
+
   boolean isVideoCall();
 
   boolean isVideoUpgradeRequest();
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index 1785ece..cbe7c57 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -32,6 +32,7 @@
 import android.support.v4.os.BuildCompat;
 import android.telecom.Call;
 import android.telecom.Call.Details;
+import android.telecom.Call.RttCall;
 import android.telecom.CallAudioState;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
@@ -263,6 +264,28 @@
         }
 
         @Override
+        public void onRttModeChanged(Call call, int mode) {
+          LogUtil.v("TelecomCallCallback.onRttModeChanged", "mode=%d", mode);
+        }
+
+        @Override
+        public void onRttRequest(Call call, int id) {
+          LogUtil.v("TelecomCallCallback.onRttRequest", "id=%d", id);
+        }
+
+        @Override
+        public void onRttInitiationFailure(Call call, int reason) {
+          LogUtil.v("TelecomCallCallback.onRttInitiationFailure", "reason=%d", reason);
+          update();
+        }
+
+        @Override
+        public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {
+          LogUtil.v("TelecomCallCallback.onRttStatusChanged", "enabled=%b", enabled);
+          update();
+        }
+
+        @Override
         public void onConnectionEvent(android.telecom.Call call, String event, Bundle extras) {
           LogUtil.v(
               "TelecomCallCallback.onConnectionEvent",
@@ -906,6 +929,14 @@
     return getVideoTech().isTransmittingOrReceiving() || VideoProfile.isVideo(getVideoState());
   }
 
+  public boolean isRttCall() {
+    if (BuildCompat.isAtLeastP()) {
+      return getTelecomCall().isRttActive();
+    } else {
+      return false;
+    }
+  }
+
   public boolean hasReceivedVideoUpgradeRequest() {
     return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState());
   }
@@ -914,6 +945,11 @@
     return VideoUtils.hasSentVideoUpgradeRequest(getVideoTech().getSessionModificationState());
   }
 
+  public boolean hasSentRttUpgradeRequest() {
+    // TODO(wangqi): Implement this.
+    return false;
+  }
+
   /**
    * Determines if the call handle is an emergency number or not and caches the result to avoid
    * repeated calls to isEmergencyNumber.
diff --git a/java/com/android/incallui/rtt/bindings/RttBindings.java b/java/com/android/incallui/rtt/bindings/RttBindings.java
new file mode 100644
index 0000000..8f9a143
--- /dev/null
+++ b/java/com/android/incallui/rtt/bindings/RttBindings.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui.rtt.bindings;
+
+import com.android.incallui.rtt.impl.RttChatFragment;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+
+/** Bindings for RTT module. */
+public class RttBindings {
+
+  public static RttCallScreen createRttCallScreen(String callId) {
+    return RttChatFragment.newInstance(callId);
+  }
+}
diff --git a/java/com/android/incallui/rtt/impl/AndroidManifest.xml b/java/com/android/incallui/rtt/impl/AndroidManifest.xml
index fc0705d..7f58f71 100644
--- a/java/com/android/incallui/rtt/impl/AndroidManifest.xml
+++ b/java/com/android/incallui/rtt/impl/AndroidManifest.xml
@@ -13,14 +13,5 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<manifest
-    package="com.android.incallui.rtt.impl"
-    xmlns:android="http://schemas.android.com/apk/res/android">
-  <application android:theme="@style/Theme.AppCompat">
-  <activity
-      android:name=".RttChatActivity"
-      android:exported="false"
-      android:theme="@style/DialerThemeBase.NoActionBar"
-      android:windowSoftInputMode="adjustResize"/>
-  </application>
+<manifest package="com.android.incallui.rtt.impl">
 </manifest>
diff --git a/java/com/android/incallui/rtt/impl/RttChatActivity.java b/java/com/android/incallui/rtt/impl/RttChatActivity.java
deleted file mode 100644
index 96056f7..0000000
--- a/java/com/android/incallui/rtt/impl/RttChatActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.incallui.rtt.impl;
-
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.support.annotation.Nullable;
-import android.support.v4.app.FragmentActivity;
-import android.view.View;
-
-/** Activity to for RTT chat window. */
-public class RttChatActivity extends FragmentActivity {
-
-  @Override
-  protected void onCreate(@Nullable Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    setContentView(R.layout.activity_rtt);
-    getSupportFragmentManager()
-        .beginTransaction()
-        .add(
-            R.id.fragment_rtt,
-            RttChatFragment.newInstance("", "Jane Williamson", SystemClock.elapsedRealtime()))
-        .commit();
-    getWindow().setStatusBarColor(getColor(R.color.rtt_status_bar_color));
-    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
-  }
-}
diff --git a/java/com/android/incallui/rtt/impl/RttChatFragment.java b/java/com/android/incallui/rtt/impl/RttChatFragment.java
index 0b0ad2a..82dce3e 100644
--- a/java/com/android/incallui/rtt/impl/RttChatFragment.java
+++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java
@@ -16,21 +16,25 @@
 
 package com.android.incallui.rtt.impl;
 
+import android.app.Activity;
 import android.os.Bundle;
 import android.os.SystemClock;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.app.Fragment;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.OnScrollListener;
+import android.telecom.CallAudioState;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.Window;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Chronometer;
@@ -38,11 +42,31 @@
 import android.widget.ImageButton;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.FragmentUtils;
+import com.android.dialer.common.LogUtil;
+import com.android.incallui.incall.protocol.InCallButtonUi;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
+import com.android.incallui.incall.protocol.InCallScreen;
+import com.android.incallui.incall.protocol.InCallScreenDelegate;
+import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
+import com.android.incallui.incall.protocol.PrimaryCallState;
+import com.android.incallui.incall.protocol.PrimaryInfo;
+import com.android.incallui.incall.protocol.SecondaryInfo;
 import com.android.incallui.rtt.impl.RttChatAdapter.MessageListener;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegateFactory;
 
 /** RTT chat fragment to show chat bubbles. */
 public class RttChatFragment extends Fragment
-    implements OnClickListener, OnEditorActionListener, TextWatcher, MessageListener {
+    implements OnEditorActionListener,
+        TextWatcher,
+        MessageListener,
+        RttCallScreen,
+        InCallScreen,
+        InCallButtonUi {
 
   private static final String ARG_CALL_ID = "call_id";
   private static final String ARG_NAME_OR_NUMBER = "name_or_number";
@@ -63,27 +87,58 @@
           }
         }
       };
+  private InCallScreenDelegate inCallScreenDelegate;
+  private RttCallScreenDelegate rttCallScreenDelegate;
+  private InCallButtonUiDelegate inCallButtonUiDelegate;
+  private View endCallButton;
 
   /**
    * Create a new instance of RttChatFragment.
    *
    * @param callId call id of the RTT call.
-   * @param nameOrNumber name or number of the caller to be displayed
-   * @param sessionStartTimeMillis start time of RTT session in terms of {@link
-   *     SystemClock#elapsedRealtime}.
    * @return new RttChatFragment
    */
-  public static RttChatFragment newInstance(
-      String callId, String nameOrNumber, long sessionStartTimeMillis) {
+  public static RttChatFragment newInstance(String callId) {
     Bundle bundle = new Bundle();
     bundle.putString(ARG_CALL_ID, callId);
-    bundle.putString(ARG_NAME_OR_NUMBER, nameOrNumber);
-    bundle.putLong(ARG_SESSION_START_TIME, sessionStartTimeMillis);
+    bundle.putString(ARG_NAME_OR_NUMBER, "Jane Williamson");
+    bundle.putLong(ARG_SESSION_START_TIME, SystemClock.elapsedRealtime());
     RttChatFragment instance = new RttChatFragment();
     instance.setArguments(bundle);
     return instance;
   }
 
+  @Override
+  public void onCreate(@Nullable Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    LogUtil.i("RttChatFragment.onCreate", null);
+    inCallButtonUiDelegate =
+        FragmentUtils.getParent(this, InCallButtonUiDelegateFactory.class)
+            .newInCallButtonUiDelegate();
+    if (savedInstanceState != null) {
+      inCallButtonUiDelegate.onRestoreInstanceState(savedInstanceState);
+    }
+  }
+
+  @Override
+  public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) {
+    super.onViewCreated(view, bundle);
+    LogUtil.i("RttChatFragment.onViewCreated", null);
+
+    inCallScreenDelegate =
+        FragmentUtils.getParentUnsafe(this, InCallScreenDelegateFactory.class)
+            .newInCallScreenDelegate();
+    rttCallScreenDelegate =
+        FragmentUtils.getParentUnsafe(this, RttCallScreenDelegateFactory.class)
+            .newRttCallScreenDelegate(this);
+
+    rttCallScreenDelegate.initRttCallScreenDelegate(getContext(), this);
+
+    inCallScreenDelegate.onInCallScreenDelegateInit(this);
+    inCallScreenDelegate.onInCallScreenReady();
+    inCallButtonUiDelegate.onInCallButtonUiReady(this);
+  }
+
   @Nullable
   @Override
   public View onCreateView(
@@ -101,8 +156,20 @@
     recyclerView.setAdapter(adapter);
     recyclerView.addOnScrollListener(onScrollListener);
     submitButton = view.findViewById(R.id.rtt_chat_submit_button);
-    submitButton.setOnClickListener(this);
+    submitButton.setOnClickListener(
+        v -> {
+          adapter.submitLocalMessage();
+          isClearingInput = true;
+          editText.setText("");
+          isClearingInput = false;
+        });
     submitButton.setEnabled(false);
+    endCallButton = view.findViewById(R.id.rtt_end_call_button);
+    endCallButton.setOnClickListener(
+        v -> {
+          LogUtil.i("RttChatFragment.onClick", "end call button clicked");
+          inCallButtonUiDelegate.onEndCallClicked();
+        });
 
     String nameOrNumber = null;
     Bundle bundle = getArguments();
@@ -123,16 +190,6 @@
   }
 
   @Override
-  public void onClick(View v) {
-    if (v.getId() == R.id.rtt_chat_submit_button) {
-      adapter.submitLocalMessage();
-      isClearingInput = true;
-      editText.setText("");
-      isClearingInput = false;
-    }
-  }
-
-  @Override
   public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
     if (actionId == EditorInfo.IME_ACTION_DONE) {
       submitButton.performClick();
@@ -166,6 +223,20 @@
     recyclerView.smoothScrollToPosition(adapter.getItemCount());
   }
 
+  @Override
+  public void onStart() {
+    LogUtil.enterBlock("RttChatFragment.onStart");
+    super.onStart();
+    onRttScreenStart();
+  }
+
+  @Override
+  public void onStop() {
+    LogUtil.enterBlock("RttChatFragment.onStop");
+    super.onStop();
+    onRttScreenStop();
+  }
+
   private void hideKeyboard() {
     InputMethodManager inputMethodManager = getContext().getSystemService(InputMethodManager.class);
     if (inputMethodManager.isAcceptingText()) {
@@ -173,4 +244,116 @@
           getActivity().getCurrentFocus().getWindowToken(), 0);
     }
   }
+
+  @Override
+  public void onRttScreenStart() {
+    rttCallScreenDelegate.onRttCallScreenUiReady();
+    Activity activity = getActivity();
+    Window window = getActivity().getWindow();
+    window.setStatusBarColor(activity.getColor(R.color.rtt_status_bar_color));
+    window.setNavigationBarColor(activity.getColor(R.color.rtt_navigation_bar_color));
+    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+  }
+
+  @Override
+  public void onRttScreenStop() {
+    rttCallScreenDelegate.onRttCallScreenUiUnready();
+  }
+
+  @Override
+  public Fragment getRttCallScreenFragment() {
+    return this;
+  }
+
+  @Override
+  public String getCallId() {
+    return Assert.isNotNull(getArguments().getString(ARG_CALL_ID));
+  }
+
+  @Override
+  public void setPrimary(@NonNull PrimaryInfo primaryInfo) {
+    LogUtil.i("RttChatFragment.setPrimary", primaryInfo.toString());
+  }
+
+  @Override
+  public void setSecondary(@NonNull SecondaryInfo secondaryInfo) {}
+
+  @Override
+  public void setCallState(@NonNull PrimaryCallState primaryCallState) {}
+
+  @Override
+  public void setEndCallButtonEnabled(boolean enabled, boolean animate) {}
+
+  @Override
+  public void showManageConferenceCallButton(boolean visible) {}
+
+  @Override
+  public boolean isManageConferenceVisible() {
+    return false;
+  }
+
+  @Override
+  public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {}
+
+  @Override
+  public void showNoteSentToast() {}
+
+  @Override
+  public void updateInCallScreenColors() {}
+
+  @Override
+  public void onInCallScreenDialpadVisibilityChange(boolean isShowing) {}
+
+  @Override
+  public int getAnswerAndDialpadContainerResourceId() {
+    return 0;
+  }
+
+  @Override
+  public void showLocationUi(Fragment locationUi) {}
+
+  @Override
+  public boolean isShowingLocationUi() {
+    return false;
+  }
+
+  @Override
+  public Fragment getInCallScreenFragment() {
+    return this;
+  }
+
+  @Override
+  public void showButton(int buttonId, boolean show) {}
+
+  @Override
+  public void enableButton(int buttonId, boolean enable) {}
+
+  @Override
+  public void setEnabled(boolean on) {}
+
+  @Override
+  public void setHold(boolean on) {}
+
+  @Override
+  public void setCameraSwitched(boolean isBackFacingCamera) {}
+
+  @Override
+  public void setVideoPaused(boolean isPaused) {}
+
+  @Override
+  public void setAudioState(CallAudioState audioState) {}
+
+  @Override
+  public void updateButtonStates() {}
+
+  @Override
+  public void updateInCallButtonUiColors(int color) {}
+
+  @Override
+  public Fragment getInCallButtonUiFragment() {
+    return this;
+  }
+
+  @Override
+  public void showAudioRouteSelector() {}
 }
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 7ba6a09..5ba9f4e 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,7 +17,8 @@
 <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:background="@color/dialer_theme_color"
+    android:fitsSystemWindows="true">
 
   <include layout="@layout/rtt_banner"/>
 
@@ -52,6 +53,8 @@
         android:inputType="textMultiLine|text"
         android:maxLines="4"
         android:minHeight="53dp"
+        android:textColor="#DD000000"
+        android:textColorHint="#757575"
         android:textSize="16sp"/>
     <ImageButton
         android:id="@+id/rtt_chat_submit_button"
diff --git a/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml b/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml
index 4ce94f9..f193805 100644
--- a/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml
+++ b/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml
@@ -17,79 +17,61 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
-    android:layout_height="56dp"
-    android:background="#FAFAFA"
+    android:layout_height="?attr/actionBarSize"
+    android:background="#F305228F"
     android:elevation="3dp">
   <ImageButton
-      android:id="@+id/rtt_back"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
+      android:id="@+id/rtt_end_call_button"
+      android:layout_width="32dp"
+      android:layout_height="32dp"
       android:layout_marginStart="16dp"
       android:layout_alignParentStart="true"
       android:layout_centerVertical="true"
       android:background="@android:color/transparent"
-      android:contentDescription="@string/content_description_rtt_back_button"
-      android:src="@drawable/quantum_ic_arrow_back_vd_theme_24"
-      android:tint="#DF000000"/>
+      android:contentDescription="@string/incall_content_description_end_call"
+      android:scaleType="fitXY"
+      android:src="@drawable/quantum_ic_call_end_vd_theme_24"
+      android:tint="#FFDF0000"/>
   <LinearLayout
-      android:layout_width="wrap_content"
+      android:layout_width="260dp"
       android:layout_height="match_parent"
       android:layout_marginTop="8dp"
       android:layout_marginBottom="8dp"
       android:layout_marginStart="32dp"
-      android:layout_toEndOf="@id/rtt_back"
+      android:layout_toEndOf="@id/rtt_end_call_button"
       android:orientation="vertical">
     <TextView
         android:id="@+id/rtt_name_or_number"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
         android:fontFamily="sans-serif-medium"
         android:includeFontPadding="false"
-        android:textColor="#DD000000"
+        android:textColor="#FFFFFF"
         android:textSize="20sp"
         tools:text="Bruce Graham"/>
     <Chronometer
         android:id="@+id/rtt_timer"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
         android:fontFamily="sans-serif-medium"
         android:includeFontPadding="false"
-        android:textColor="#DD000000"
+        android:textColor="#FFFFFF"
         android:textSize="14sp"
         tools:text="00:09"/>
   </LinearLayout>
   <ImageButton
-      android:id="@+id/rtt_hang_up_button"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_marginEnd="16dp"
+      android:id="@+id/rtt_overflow_button"
+      android:layout_width="32dp"
+      android:layout_height="32dp"
+      android:layout_marginEnd="12dp"
       android:layout_alignParentEnd="true"
       android:layout_centerVertical="true"
       android:background="@android:color/transparent"
-      android:contentDescription="@string/incall_content_description_end_call"
-      android:src="@drawable/quantum_ic_call_end_vd_theme_24"
-      android:tint="#FFDF0000"/>
-  <ImageButton
-      android:id="@+id/rtt_speaker_button"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_marginEnd="24dp"
-      android:layout_centerVertical="true"
-      android:layout_toStartOf="@id/rtt_hang_up_button"
-      android:background="@android:color/transparent"
-      android:contentDescription="@string/incall_content_description_speaker"
-      android:src="@drawable/quantum_ic_volume_up_vd_theme_24"
-      android:tint="#DD000000"/>
-  <ImageButton
-      android:id="@+id/rtt_mic_button"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_marginEnd="24dp"
-      android:layout_centerVertical="true"
-      android:layout_toStartOf="@id/rtt_speaker_button"
-      android:background="@android:color/transparent"
-      android:contentDescription="@string/incall_content_description_unmuted"
-      android:src="@drawable/quantum_ic_mic_off_vd_theme_24"
-      android:tint="#DD000000"/>
+      android:contentDescription="@string/content_description_overflow"
+      android:scaleType="fitXY"
+      android:src="@drawable/quantum_ic_more_vert_vd_theme_24"
+      android:tint="#FFFFFF"/>
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/values/colors.xml b/java/com/android/incallui/rtt/impl/res/values/colors.xml
index 402cac4..c25ad21 100644
--- a/java/com/android/incallui/rtt/impl/res/values/colors.xml
+++ b/java/com/android/incallui/rtt/impl/res/values/colors.xml
@@ -15,5 +15,6 @@
   ~ limitations under the License
   -->
 <resources>
-  <color name="rtt_status_bar_color">#E0E0E0</color>
+  <color name="rtt_status_bar_color">#03165C</color>
+  <color name="rtt_navigation_bar_color">#FAFAFA</color>
 </resources>
\ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/values/strings.xml b/java/com/android/incallui/rtt/impl/res/values/strings.xml
index 523abdc..0b9eb71 100644
--- a/java/com/android/incallui/rtt/impl/res/values/strings.xml
+++ b/java/com/android/incallui/rtt/impl/res/values/strings.xml
@@ -18,9 +18,6 @@
   <!-- Content description for submit chat input button. [CHAR LIMIT=NONE] -->
   <string name="content_description_rtt_check_button">Go ahead</string>
 
-  <!-- Content description for navigate back button on RTT chat window. [CHAR LIMIT=NONE] -->
-  <string name="content_description_rtt_back_button">Back</string>
-
   <!-- Hint text for input box. [CHAR LIMIT=NONE] -->
   <string name="rtt_input_hint">Type a message</string>
 
diff --git a/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml b/java/com/android/incallui/rtt/protocol/AndroidManifest.xml
similarity index 62%
rename from java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml
rename to java/com/android/incallui/rtt/protocol/AndroidManifest.xml
index b48e8d4..52514a5 100644
--- a/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml
+++ b/java/com/android/incallui/rtt/protocol/AndroidManifest.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
   ~ Copyright (C) 2018 The Android Open Source Project
   ~
@@ -14,13 +13,10 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-  <FrameLayout
-      android:id="@+id/fragment_rtt"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent"/>
 
-</LinearLayout>
\ No newline at end of file
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.incallui.rtt.protocol">
+  <uses-sdk
+      android:minSdkVersion="23"
+      android:targetSdkVersion="26"/>
+</manifest>
\ No newline at end of file
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreen.java b/java/com/android/incallui/rtt/protocol/RttCallScreen.java
new file mode 100644
index 0000000..afacbae
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreen.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui.rtt.protocol;
+
+import android.support.v4.app.Fragment;
+
+/** Interface for call RTT call module. */
+public interface RttCallScreen {
+
+  void onRttScreenStart();
+
+  void onRttScreenStop();
+
+  Fragment getRttCallScreenFragment();
+
+  String getCallId();
+}
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
new file mode 100644
index 0000000..e29c43d
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui.rtt.protocol;
+
+import android.content.Context;
+
+/** Callbacks from the module out to the container. */
+public interface RttCallScreenDelegate {
+
+  void initRttCallScreenDelegate(Context context, RttCallScreen rttCallScreen);
+
+  void onRttCallScreenUiReady();
+
+  void onRttCallScreenUiUnready();
+}
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java
new file mode 100644
index 0000000..0dbcc91
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui.rtt.protocol;
+
+/** Callbacks from the module out to the container. */
+public interface RttCallScreenDelegateFactory {
+
+  RttCallScreenDelegate newRttCallScreenDelegate(RttCallScreen rttCallScreen);
+}