Implement dialog for responding RTT request.

Bug: 67596257
Test: manual
PiperOrigin-RevId: 191365412
Change-Id: Ida741a837d6495c0d5f51b748f4d6c09a1beafec
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 1ba3683..65ef323 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -35,6 +35,7 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
+import android.support.v4.app.DialogFragment;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
@@ -1221,6 +1222,12 @@
     fragment.show(getSupportFragmentManager(), Tags.INTERNATIONAL_CALL_ON_WIFI);
   }
 
+  public void showDialogForRttRequest(DialerCall call, int rttRequestId) {
+    LogUtil.enterBlock("InCallActivity.showDialogForRttRequest");
+    DialogFragment fragment = RttRequestDialogFragment.newInstance(call.getId(), rttRequestId);
+    fragment.show(getSupportFragmentManager(), Tags.RTT_REQUEST_DIALOG);
+  }
+
   @Override
   public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
     super.onMultiWindowModeChanged(isInMultiWindowMode);
@@ -1763,6 +1770,7 @@
     static final String RTT_CALL_SCREEN = "tag_rtt_call_screen";
     static final String POST_CHAR_DIALOG_FRAGMENT = "tag_post_char_dialog_fragment";
     static final String SPEAK_EASY_SCREEN = "tag_speak_easy_screen";
+    static final String RTT_REQUEST_DIALOG = "tag_rtt_request_dialog";
   }
 
   private static final class ConfigNames {
diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java
index e11b376..6300dac 100644
--- a/java/com/android/incallui/InCallPresenter.java
+++ b/java/com/android/incallui/InCallPresenter.java
@@ -894,6 +894,13 @@
   }
 
   @Override
+  public void onUpgradeToRtt(DialerCall call, int rttRequestId) {
+    if (inCallActivity != null) {
+      inCallActivity.showDialogForRttRequest(call, rttRequestId);
+    }
+  }
+
+  @Override
   public void onSessionModificationStateChange(DialerCall call) {
     int newState = call.getVideoTech().getSessionModificationState();
     LogUtil.i("InCallPresenter.onSessionModificationStateChange", "state: %d", newState);
diff --git a/java/com/android/incallui/RttRequestDialogFragment.java b/java/com/android/incallui/RttRequestDialogFragment.java
new file mode 100644
index 0000000..fa9b0e5
--- /dev/null
+++ b/java/com/android/incallui/RttRequestDialogFragment.java
@@ -0,0 +1,149 @@
+/*
+ * 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.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.telephony.PhoneNumberUtils;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+import com.android.contacts.common.util.ContactDisplayUtils;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.incallui.ContactInfoCache.ContactCacheEntry;
+import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
+import com.android.incallui.call.CallList;
+import com.android.incallui.call.DialerCall;
+import java.lang.ref.WeakReference;
+
+/** Dialog that shown to user when receiving RTT request mid call. */
+public class RttRequestDialogFragment extends DialogFragment {
+
+  /**
+   * Returns a new instance of {@link RttRequestDialogFragment} with the given callback.
+   *
+   * <p>Prefer this method over the default constructor.
+   */
+  public static RttRequestDialogFragment newInstance(String callId, int rttRequestId) {
+    RttRequestDialogFragment fragment = new RttRequestDialogFragment();
+    Bundle args = new Bundle();
+    args.putString(ARG_CALL_ID, Assert.isNotNull(callId));
+    args.putInt(ARG_RTT_REQUEST_ID, rttRequestId);
+    fragment.setArguments(args);
+    return fragment;
+  }
+
+  /** Key in the arguments bundle for call id. */
+  private static final String ARG_CALL_ID = "call_id";
+
+  private static final String ARG_RTT_REQUEST_ID = "rtt_request_id";
+
+  private TextView detailsTextView;
+
+  @NonNull
+  @Override
+  public Dialog onCreateDialog(Bundle bundle) {
+    super.onCreateDialog(bundle);
+    LogUtil.enterBlock("RttRequestDialogFragment.onCreateDialog");
+
+    View dialogView = View.inflate(getActivity(), R.layout.frag_rtt_request_dialog, null);
+    detailsTextView = dialogView.findViewById(R.id.details);
+
+    ContactInfoCache cache = ContactInfoCache.getInstance(getContext());
+    DialerCall dialerCall =
+        CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID));
+    cache.findInfo(dialerCall, false, new ContactLookupCallback(this));
+
+    dialogView
+        .findViewById(R.id.rtt_button_decline_request)
+        .setOnClickListener(v -> onNegativeButtonClick());
+    dialogView
+        .findViewById(R.id.rtt_button_accept_request)
+        .setOnClickListener(v -> onPositiveButtonClick());
+
+    AlertDialog alertDialog =
+        new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
+            .setCancelable(false)
+            .setView(dialogView)
+            .setTitle(R.string.rtt_request_dialog_title)
+            .create();
+
+    alertDialog.setCanceledOnTouchOutside(false);
+    return alertDialog;
+  }
+
+  private void onPositiveButtonClick() {
+    LogUtil.enterBlock("RttRequestDialogFragment.onPositiveButtonClick");
+
+    DialerCall call = CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID));
+    call.respondToRttRequest(true, getArguments().getInt(ARG_RTT_REQUEST_ID));
+    dismiss();
+  }
+
+  private void onNegativeButtonClick() {
+    LogUtil.enterBlock("RttRequestDialogFragment.onNegativeButtonClick");
+
+    DialerCall call = CallList.getInstance().getCallById(getArguments().getString(ARG_CALL_ID));
+    call.respondToRttRequest(false, getArguments().getInt(ARG_RTT_REQUEST_ID));
+    dismiss();
+  }
+
+  private void setNameOrNumber(CharSequence nameOrNumber) {
+    detailsTextView.setText(getString(R.string.rtt_request_dialog_details, nameOrNumber));
+  }
+
+  private static class ContactLookupCallback implements ContactInfoCacheCallback {
+    private final WeakReference<RttRequestDialogFragment> rttRequestDialogFragmentWeakReference;
+
+    private ContactLookupCallback(RttRequestDialogFragment rttRequestDialogFragment) {
+      rttRequestDialogFragmentWeakReference = new WeakReference<>(rttRequestDialogFragment);
+    }
+
+    @Override
+    public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
+      RttRequestDialogFragment fragment = rttRequestDialogFragmentWeakReference.get();
+      if (fragment != null) {
+        fragment.setNameOrNumber(getNameOrNumber(entry, fragment.getContext()));
+      }
+    }
+
+    private CharSequence getNameOrNumber(ContactCacheEntry entry, Context context) {
+      String preferredName =
+          ContactDisplayUtils.getPreferredDisplayName(
+              entry.namePrimary,
+              entry.nameAlternative,
+              ContactsPreferencesFactory.newContactsPreferences(context));
+      if (TextUtils.isEmpty(preferredName)) {
+        return TextUtils.isEmpty(entry.number)
+            ? null
+            : PhoneNumberUtils.createTtsSpannable(
+                BidiFormatter.getInstance().unicodeWrap(entry.number, TextDirectionHeuristics.LTR));
+      }
+      return preferredName;
+    }
+
+    @Override
+    public void onImageLoadComplete(String callId, ContactCacheEntry entry) {}
+  }
+}
diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java
index 01f3b9d..eccdcee 100644
--- a/java/com/android/incallui/call/CallList.java
+++ b/java/com/android/incallui/call/CallList.java
@@ -784,6 +784,12 @@
      */
     void onUpgradeToVideo(DialerCall call);
 
+    /**
+     * Called when a new RTT call request comes in This is the only method that gets called for RTT
+     * requests.
+     */
+    default void onUpgradeToRtt(DialerCall call, int rttRequestId) {}
+
     /** Called when the session modification state of a call changes. */
     void onSessionModificationStateChange(DialerCall call);
 
@@ -855,6 +861,13 @@
     public void onDialerCallLastForwardedNumberChange() {}
 
     @Override
+    public void onDialerCallUpgradeToRtt(int rttRequestId) {
+      for (Listener listener : listeners) {
+        listener.onUpgradeToRtt(call, rttRequestId);
+      }
+    }
+
+    @Override
     public void onDialerCallUpgradeToVideo() {
       for (Listener listener : listeners) {
         listener.onUpgradeToVideo(call);
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index e08c926..35f9481 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -282,6 +282,9 @@
         @Override
         public void onRttRequest(Call call, int id) {
           LogUtil.v("TelecomCallCallback.onRttRequest", "id=%d", id);
+          for (DialerCallListener listener : listeners) {
+            listener.onDialerCallUpgradeToRtt(id);
+          }
         }
 
         @Override
@@ -1033,6 +1036,11 @@
     getTelecomCall().sendRttRequest();
   }
 
+  @TargetApi(28)
+  public void respondToRttRequest(boolean accept, int rttRequestId) {
+    getTelecomCall().respondToRttRequest(rttRequestId, accept);
+  }
+
   public boolean hasReceivedVideoUpgradeRequest() {
     return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState());
   }
diff --git a/java/com/android/incallui/call/DialerCallListener.java b/java/com/android/incallui/call/DialerCallListener.java
index 5d24a4d..37c30d3 100644
--- a/java/com/android/incallui/call/DialerCallListener.java
+++ b/java/com/android/incallui/call/DialerCallListener.java
@@ -29,6 +29,8 @@
 
   void onDialerCallUpgradeToVideo();
 
+  default void onDialerCallUpgradeToRtt(int rttRequestId) {}
+
   void onDialerCallSessionModificationStateChange();
 
   void onWiFiToLteHandover();
diff --git a/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml b/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml
new file mode 100644
index 0000000..c6d9e99
--- /dev/null
+++ b/java/com/android/incallui/res/layout/frag_rtt_request_dialog.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+  <TextView
+      android:id="@+id/details"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:paddingTop="20dp"
+      android:paddingBottom="12dp"
+      android:paddingStart="24dp"
+      android:paddingEnd="24dp"
+      android:textColor="#DE000000"
+      android:textSize="16sp"/>
+
+  <TextView
+      android:id="@+id/more_information"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:paddingBottom="16dp"
+      android:paddingStart="24dp"
+      android:paddingEnd="24dp"
+      android:text="@string/rtt_request_dialog_more_information"
+      android:textColor="#8A000000"
+      android:textSize="14sp"/>
+
+  <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:padding="8dp"
+      android:orientation="horizontal">
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"/>
+    <Button
+        android:id="@+id/rtt_button_decline_request"
+        style="@style/Widget.MaterialComponents.Button.TextButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:backgroundTint="@android:color/white"
+        android:fontFamily="sans-serif-medium"
+        android:text="@string/rtt_button_decline_request"
+        android:textColor="#757575"/>
+    <Button
+        android:id="@+id/rtt_button_accept_request"
+        style="@style/Widget.MaterialComponents.Button.TextButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:backgroundTint="@color/dialer_theme_color"
+        android:fontFamily="sans-serif-medium"
+        android:text="@string/rtt_button_accept_request"
+        android:textColor="@android:color/white"/>
+  </LinearLayout>
+
+</LinearLayout>
+
diff --git a/java/com/android/incallui/res/values/strings.xml b/java/com/android/incallui/res/values/strings.xml
index 15cd2e0..c7e5677 100644
--- a/java/com/android/incallui/res/values/strings.xml
+++ b/java/com/android/incallui/res/values/strings.xml
@@ -202,4 +202,19 @@
   <!-- Text for bubble return-to-call button -->
   <string name="bubble_return_to_call">Back to call</string>
 
+  <!-- Title for RTT request dialog. [CHAR LIMIT=60] -->
+  <string name="rtt_request_dialog_title">Join RTT call?</string>
+
+  <!-- Details for RTT request dialog. [CHAR LIMIT=NONE] -->
+  <string name="rtt_request_dialog_details"><xliff:g id="caller">%1$s</xliff:g> wants to use messaging within your voice call.</string>
+
+  <!-- More information for RTT request dialog. [CHAR LIMIT=NONE] -->
+  <string name="rtt_request_dialog_more_information">RTT assists callers who are deaf, hard of hearing, have a speech disability, or need more than voice alone.</string>
+
+  <!-- Text for button to decline RTT request. [CHAR LIMIT=20] -->
+  <string name="rtt_button_decline_request">No thanks</string>
+
+  <!-- Text for button to accept RTT request. [CHAR LIMIT=20] -->
+  <string name="rtt_button_accept_request">Join RTT</string>
+
 </resources>
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 b0ac205..1d09f54 100644
--- a/java/com/android/incallui/rtt/impl/res/values/strings.xml
+++ b/java/com/android/incallui/rtt/impl/res/values/strings.xml
@@ -27,7 +27,7 @@
   <!-- Text for back button. [CHAR LIMIT=20] -->
   <string name="rtt_button_back">Back</string>
 
-  <!-- Text for status banner. [CHAT LIMIT=100] -->
+  <!-- Text for status banner. [CHAR LIMIT=100] -->
   <string name="rtt_status_banner_text">Waiting for <xliff:g id="name">%s</xliff:g> to join RTT call&#8230;</string>
 
 </resources>
\ No newline at end of file