summaryrefslogtreecommitdiff
path: root/java/com/android/incallui/rtt
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-01-09 16:40:28 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-01-09 16:40:28 +0000
commit8c19b0ac8f79eb7f653ee3e07018ca7342f4e190 (patch)
tree92e2a480370fd53fdb210d1035a6c3d666628819 /java/com/android/incallui/rtt
parent455a7c27d5c5d4c25236d940f088a25a5bf57c2a (diff)
parent517fbff5c15c9270323b4099a39514d2487eec99 (diff)
Merge changes Iddf5ef33,I1b718e30,I0c7386f6,I81069948,I3bec477d, ...
* changes: Update strings for Duo "Set up" and "Invite" buttons Hide emergency calls in the call log Simplifying implementation of the coalescing logic in the new call log. Updating Dialer v16 licenses. Use ContactsContract.PhoneLookup for invalid numbers in Cp2PhoneLookup. Add RTT call chat window. Updated T9 search bolding to include wrapping to the next word. Initial setup of voicemail error messages Automated rollback of changelist 178323108 Add "delete" option in the 3-dot menu of the new call log
Diffstat (limited to 'java/com/android/incallui/rtt')
-rw-r--r--java/com/android/incallui/rtt/impl/AndroidManifest.xml26
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatActivity.java41
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatAdapter.java218
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatFragment.java176
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatMessage.java132
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java65
-rw-r--r--java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml21
-rw-r--r--java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml21
-rw-r--r--java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml21
-rw-r--r--java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml74
-rw-r--r--java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml21
-rw-r--r--java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml22
-rw-r--r--java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml26
-rw-r--r--java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml69
-rw-r--r--java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml91
-rw-r--r--java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml48
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/colors.xml19
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/dimens.xml20
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/strings.xml29
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/styles.xml35
20 files changed, 1175 insertions, 0 deletions
diff --git a/java/com/android/incallui/rtt/impl/AndroidManifest.xml b/java/com/android/incallui/rtt/impl/AndroidManifest.xml
new file mode 100644
index 000000000..fc0705d7e
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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
+ -->
+<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>
diff --git a/java/com/android/incallui/rtt/impl/RttChatActivity.java b/java/com/android/incallui/rtt/impl/RttChatActivity.java
new file mode 100644
index 000000000..96056f746
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/RttChatActivity.java
@@ -0,0 +1,41 @@
+/*
+ * 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/RttChatAdapter.java b/java/com/android/incallui/rtt/impl/RttChatAdapter.java
new file mode 100644
index 000000000..1db4c6bad
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/RttChatAdapter.java
@@ -0,0 +1,218 @@
+/*
+ * 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.content.Context;
+import android.support.annotation.MainThread;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/** Adapter class for holding RTT chat data. */
+public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolder> {
+
+ interface MessageListener {
+ void newMessageAdded();
+ }
+
+ private final Context context;
+ private final List<RttChatMessage> rttMessages = new ArrayList<>();
+ private int lastIndexOfLocalMessage = -1;
+ private int lastIndexOfRemoteMessage = -1;
+ private final TypeBot typeBot;
+ private final MessageListener messageListener;
+
+ RttChatAdapter(Context context, MessageListener listener) {
+ this.context = context;
+ this.messageListener = listener;
+ typeBot = new TypeBot(text -> ThreadUtil.postOnUiThread(() -> addRemoteMessage(text)));
+ }
+
+ @Override
+ public RttChatMessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ LayoutInflater layoutInflater = LayoutInflater.from(context);
+ View view = layoutInflater.inflate(R.layout.rtt_chat_list_item, parent, false);
+ return new RttChatMessageViewHolder(view);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return super.getItemViewType(position);
+ }
+
+ @Override
+ public void onBindViewHolder(RttChatMessageViewHolder rttChatMessageViewHolder, int i) {
+ boolean isSameGroup = false;
+ if (i > 0) {
+ isSameGroup = rttMessages.get(i).isRemote == rttMessages.get(i - 1).isRemote;
+ }
+ rttChatMessageViewHolder.setMessage(rttMessages.get(i), isSameGroup);
+ }
+
+ @Override
+ public int getItemCount() {
+ return rttMessages.size();
+ }
+
+ private void updateCurrentRemoteMessage(String newText) {
+ RttChatMessage rttChatMessage = null;
+ if (lastIndexOfRemoteMessage >= 0) {
+ rttChatMessage = rttMessages.get(lastIndexOfRemoteMessage);
+ }
+ RttChatMessage[] newMessages = RttChatMessage.getRemoteRttChatMessage(rttChatMessage, newText);
+
+ if (rttChatMessage == null) {
+ lastIndexOfRemoteMessage = rttMessages.size();
+ rttMessages.add(lastIndexOfRemoteMessage, newMessages[0]);
+ rttMessages.addAll(Arrays.asList(newMessages).subList(1, newMessages.length));
+ notifyItemRangeInserted(lastIndexOfRemoteMessage, newMessages.length);
+ lastIndexOfRemoteMessage = rttMessages.size() - 1;
+ } else {
+ rttMessages.set(lastIndexOfRemoteMessage, newMessages[0]);
+ int lastIndex = rttMessages.size();
+ rttMessages.addAll(Arrays.asList(newMessages).subList(1, newMessages.length));
+
+ notifyItemChanged(lastIndexOfRemoteMessage);
+ notifyItemRangeInserted(lastIndex, newMessages.length);
+ }
+ if (rttMessages.get(lastIndexOfRemoteMessage).isFinished()) {
+ lastIndexOfRemoteMessage = -1;
+ }
+ }
+
+ private void updateCurrentLocalMessage(String newMessage) {
+ RttChatMessage rttChatMessage = null;
+ if (lastIndexOfLocalMessage >= 0) {
+ rttChatMessage = rttMessages.get(lastIndexOfLocalMessage);
+ }
+ if (rttChatMessage == null || rttChatMessage.isFinished()) {
+ rttChatMessage = new RttChatMessage();
+ rttChatMessage.append(newMessage);
+ rttMessages.add(rttChatMessage);
+ lastIndexOfLocalMessage = rttMessages.size() - 1;
+ notifyItemInserted(lastIndexOfLocalMessage);
+ } else {
+ rttChatMessage.append(newMessage);
+ notifyItemChanged(lastIndexOfLocalMessage);
+ }
+ }
+
+ void addLocalMessage(String message) {
+ LogUtil.enterBlock("RttChatAdapater.addLocalMessage");
+ updateCurrentLocalMessage(message);
+ if (messageListener != null) {
+ messageListener.newMessageAdded();
+ }
+ }
+
+ void submitLocalMessage() {
+ LogUtil.enterBlock("RttChatAdapater.submitLocalMessage");
+ rttMessages.get(lastIndexOfLocalMessage).finish();
+ notifyItemChanged(lastIndexOfLocalMessage);
+ lastIndexOfLocalMessage = -1;
+ startChatBot();
+ }
+
+ void addRemoteMessage(String message) {
+ LogUtil.enterBlock("RttChatAdapater.addRemoteMessage");
+ if (TextUtils.isEmpty(message)) {
+ return;
+ }
+ updateCurrentRemoteMessage(message);
+ if (messageListener != null) {
+ messageListener.newMessageAdded();
+ }
+ }
+
+ private void startChatBot() {
+ typeBot.scheduleMessage();
+ }
+
+ // TODO(wangqi): Move this out of this class once a bug is fixed.
+ private static class TypeBot {
+ interface Callback {
+ void type(String text);
+ }
+
+ private static final String[] CANDIDATE_MESSAGES =
+ new String[] {
+ "To RTT or not to RTT, that is the question...",
+ "Making TTY great again!",
+ "I would be more comfortable with real \"Thyme\" chatting."
+ + " I don't know how to end this pun",
+ "お疲れ様でした",
+ "The FCC has mandated that I respond... I will do so begrudgingly",
+ "😂😂😂💯"
+ };
+ private final Random random = new Random();
+ private final Callback callback;
+ private final List<String> messageQueue = new ArrayList<>();
+ private int currentTypingPosition = -1;
+ private String currentTypingMessage = null;
+
+ TypeBot(Callback callback) {
+ this.callback = callback;
+ }
+
+ @MainThread
+ public void scheduleMessage() {
+ Assert.isMainThread();
+ if (random.nextDouble() < 0.5) {
+ return;
+ }
+
+ String text = CANDIDATE_MESSAGES[random.nextInt(CANDIDATE_MESSAGES.length)];
+ messageQueue.add(text);
+ typeMessage();
+ }
+
+ @MainThread
+ private void typeMessage() {
+ Assert.isMainThread();
+ if (currentTypingPosition < 0 || currentTypingMessage == null) {
+ if (messageQueue.size() <= 0) {
+ return;
+ }
+ currentTypingMessage = messageQueue.remove(0);
+ currentTypingPosition = 0;
+ }
+ if (currentTypingPosition < currentTypingMessage.length()) {
+ int size = random.nextInt(currentTypingMessage.length() - currentTypingPosition + 1);
+ callback.type(
+ currentTypingMessage.substring(currentTypingPosition, currentTypingPosition + size));
+ currentTypingPosition = currentTypingPosition + size;
+ // Wait up to 2s between typing.
+ ThreadUtil.postDelayedOnUiThread(this::typeMessage, 200 * random.nextInt(10));
+ } else {
+ callback.type(RttChatMessage.BUBBLE_BREAKER);
+ currentTypingPosition = -1;
+ currentTypingMessage = null;
+ // Wait 1-11s between two messages.
+ ThreadUtil.postDelayedOnUiThread(this::typeMessage, 1000 * (1 + random.nextInt(10)));
+ }
+ }
+ }
+}
diff --git a/java/com/android/incallui/rtt/impl/RttChatFragment.java b/java/com/android/incallui/rtt/impl/RttChatFragment.java
new file mode 100644
index 000000000..0b0ad2a8e
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java
@@ -0,0 +1,176 @@
+/*
+ * 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.Fragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+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.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Chronometer;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+import com.android.incallui.rtt.impl.RttChatAdapter.MessageListener;
+
+/** RTT chat fragment to show chat bubbles. */
+public class RttChatFragment extends Fragment
+ implements OnClickListener, OnEditorActionListener, TextWatcher, MessageListener {
+
+ private static final String ARG_CALL_ID = "call_id";
+ private static final String ARG_NAME_OR_NUMBER = "name_or_number";
+ private static final String ARG_SESSION_START_TIME = "session_start_time";
+
+ private RecyclerView recyclerView;
+ private RttChatAdapter adapter;
+ private EditText editText;
+ private ImageButton submitButton;
+ private boolean isClearingInput;
+
+ private final OnScrollListener onScrollListener =
+ new OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ if (dy < 0) {
+ hideKeyboard();
+ }
+ }
+ };
+
+ /**
+ * 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) {
+ Bundle bundle = new Bundle();
+ bundle.putString(ARG_CALL_ID, callId);
+ bundle.putString(ARG_NAME_OR_NUMBER, nameOrNumber);
+ bundle.putLong(ARG_SESSION_START_TIME, sessionStartTimeMillis);
+ RttChatFragment instance = new RttChatFragment();
+ instance.setArguments(bundle);
+ return instance;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(
+ LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.frag_rtt_chat, container, false);
+ editText = view.findViewById(R.id.rtt_chat_input);
+ editText.setOnEditorActionListener(this);
+ editText.addTextChangedListener(this);
+ recyclerView = view.findViewById(R.id.rtt_recycler_view);
+ LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
+ layoutManager.setStackFromEnd(true);
+ recyclerView.setLayoutManager(layoutManager);
+ recyclerView.setHasFixedSize(false);
+ adapter = new RttChatAdapter(getContext(), this);
+ recyclerView.setAdapter(adapter);
+ recyclerView.addOnScrollListener(onScrollListener);
+ submitButton = view.findViewById(R.id.rtt_chat_submit_button);
+ submitButton.setOnClickListener(this);
+ submitButton.setEnabled(false);
+
+ String nameOrNumber = null;
+ Bundle bundle = getArguments();
+ if (bundle != null) {
+ nameOrNumber = bundle.getString(ARG_NAME_OR_NUMBER, getString(R.string.unknown));
+ }
+ TextView nameTextView = view.findViewById(R.id.rtt_name_or_number);
+ nameTextView.setText(nameOrNumber);
+
+ long sessionStartTime = SystemClock.elapsedRealtime();
+ if (bundle != null) {
+ sessionStartTime = bundle.getLong(ARG_SESSION_START_TIME, sessionStartTime);
+ }
+ Chronometer chronometer = view.findViewById(R.id.rtt_timer);
+ chronometer.setBase(sessionStartTime);
+ chronometer.start();
+ return view;
+ }
+
+ @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();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ if (isClearingInput) {
+ return;
+ }
+ adapter.addLocalMessage(RttChatMessage.getChangedString(s, start, before, count));
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (TextUtils.isEmpty(s)) {
+ submitButton.setEnabled(false);
+ } else {
+ submitButton.setEnabled(true);
+ }
+ }
+
+ @Override
+ public void newMessageAdded() {
+ recyclerView.smoothScrollToPosition(adapter.getItemCount());
+ }
+
+ private void hideKeyboard() {
+ InputMethodManager inputMethodManager = getContext().getSystemService(InputMethodManager.class);
+ if (inputMethodManager.isAcceptingText()) {
+ inputMethodManager.hideSoftInputFromWindow(
+ getActivity().getCurrentFocus().getWindowToken(), 0);
+ }
+ }
+}
diff --git a/java/com/android/incallui/rtt/impl/RttChatMessage.java b/java/com/android/incallui/rtt/impl/RttChatMessage.java
new file mode 100644
index 000000000..85b045183
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/RttChatMessage.java
@@ -0,0 +1,132 @@
+/*
+ * 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.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextWatcher;
+import com.google.common.base.Splitter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/** Message class that holds one RTT chat content. */
+final class RttChatMessage {
+
+ static final String BUBBLE_BREAKER = "\n\n";
+ private static final Splitter SPLITTER = Splitter.on(BUBBLE_BREAKER);
+
+ boolean isRemote;
+ public boolean hasAvatar;
+ private final StringBuilder content = new StringBuilder();
+ private boolean isFinished;
+
+ public boolean isFinished() {
+ return isFinished;
+ }
+
+ public void finish() {
+ isFinished = true;
+ }
+
+ public void append(String text) {
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ if (c != '\b') {
+ content.append(c);
+ } else if (content.length() > 0) {
+ content.deleteCharAt(content.length() - 1);
+ }
+ }
+ }
+
+ public String getContent() {
+ return content.toString();
+ }
+
+ /**
+ * Generates delta change to a text.
+ *
+ * <p>This is used to track text change of input. See more details in {@link
+ * TextWatcher#onTextChanged}
+ *
+ * <p>e.g. "hello world" -> "hello" : "\b\b\b\b\b\b"
+ *
+ * <p>"hello world" -> "hello mom!" : "\b\b\b\b\bmom!"
+ *
+ * <p>"hello world" -> "hello d" : "\b\b\b\b\bd"
+ *
+ * <p>"hello world" -> "hello new world" : "\b\b\b\b\bnew world"
+ */
+ static String getChangedString(CharSequence s, int start, int before, int count) {
+ StringBuilder modify = new StringBuilder();
+ if (before > count) {
+ int deleteStart = start + count;
+ int deleted = before - count;
+ int numberUnModifiedCharsAfterDeleted = s.length() - start - count;
+ char c = '\b';
+ for (int i = 0; i < deleted + numberUnModifiedCharsAfterDeleted; i++) {
+ modify.append(c);
+ }
+ modify.append(s, deleteStart, s.length());
+ } else {
+ int insertStart = start + before;
+ int numberUnModifiedCharsAfterInserted = s.length() - start - count;
+ char c = '\b';
+ for (int i = 0; i < numberUnModifiedCharsAfterInserted; i++) {
+ modify.append(c);
+ }
+ modify.append(s, insertStart, s.length());
+ }
+ return modify.toString();
+ }
+
+ /** Convert remote input text into an array of {@code RttChatMessage}. */
+ static RttChatMessage[] getRemoteRttChatMessage(
+ @Nullable RttChatMessage currentMessage, @NonNull String text) {
+ Iterator<String> splitText = SPLITTER.split(text).iterator();
+ List<RttChatMessage> messageList = new ArrayList<>();
+
+ String firstMessageContent = splitText.next();
+ RttChatMessage firstMessage = currentMessage;
+ if (firstMessage == null) {
+ firstMessage = new RttChatMessage();
+ firstMessage.isRemote = true;
+ }
+ firstMessage.append(firstMessageContent);
+ if (splitText.hasNext() || text.endsWith(BUBBLE_BREAKER)) {
+ firstMessage.finish();
+ }
+ messageList.add(firstMessage);
+
+ while (splitText.hasNext()) {
+ String singleMessageContent = splitText.next();
+ if (singleMessageContent.isEmpty()) {
+ continue;
+ }
+ RttChatMessage message = new RttChatMessage();
+ message.append(singleMessageContent);
+ message.isRemote = true;
+ if (splitText.hasNext()) {
+ message.finish();
+ }
+ messageList.add(message);
+ }
+
+ return messageList.toArray(new RttChatMessage[0]);
+ }
+}
diff --git a/java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java b/java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java
new file mode 100644
index 000000000..c88786aa4
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java
@@ -0,0 +1,65 @@
+/*
+ * 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.content.res.Resources;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.TextView;
+
+/** ViewHolder class for RTT chat message bubble. */
+public class RttChatMessageViewHolder extends ViewHolder {
+
+ private final TextView messageTextView;
+ private final Resources resources;
+ private final ImageView avatarImageView;
+ private final View container;
+
+ RttChatMessageViewHolder(View view) {
+ super(view);
+ container = view.findViewById(R.id.rtt_chat_message_container);
+ messageTextView = view.findViewById(R.id.rtt_chat_message);
+ avatarImageView = view.findViewById(R.id.rtt_chat_avatar);
+ resources = view.getResources();
+ }
+
+ void setMessage(RttChatMessage message, boolean isSameGroup) {
+ messageTextView.setText(message.getContent());
+ LinearLayout.LayoutParams params = (LayoutParams) container.getLayoutParams();
+ params.gravity = message.isRemote ? Gravity.START : Gravity.END;
+ params.topMargin =
+ isSameGroup
+ ? resources.getDimensionPixelSize(R.dimen.rtt_same_group_message_margin_top)
+ : resources.getDimensionPixelSize(R.dimen.rtt_message_margin_top);
+ container.setLayoutParams(params);
+ messageTextView.setEnabled(message.isRemote);
+ if (message.isRemote) {
+ if (isSameGroup) {
+ avatarImageView.setVisibility(View.INVISIBLE);
+ } else {
+ avatarImageView.setVisibility(View.VISIBLE);
+ avatarImageView.setImageResource(R.drawable.product_logo_avatar_anonymous_white_color_120);
+ }
+ } else {
+ avatarImageView.setVisibility(View.GONE);
+ }
+ }
+}
diff --git a/java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml b/java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml
new file mode 100644
index 000000000..b3729ee20
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="#E0E0E0" />
+ <item android:color="@android:color/white" />
+</selector> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml b/java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml
new file mode 100644
index 000000000..0da2c374a
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="#BDBDBD" />
+ <item android:color="#FFFFFF" />
+</selector> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml b/java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml
new file mode 100644
index 000000000..2fe748f77
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="#EEEEEE" />
+ <item android:color="#2A56C6" />
+</selector> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml b/java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml
new file mode 100644
index 000000000..ae372332e
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml
@@ -0,0 +1,74 @@
+<?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
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/pill_stroke">
+ <shape android:shape="rectangle">
+ <padding
+ android:bottom="0dp"
+ android:left="1dp"
+ android:right="1dp"
+ android:top="0dp"/>
+ <solid android:color="@android:color/transparent"/>
+ <corners android:radius="24dp"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <padding
+ android:bottom="1dp"
+ android:left="1dp"
+ android:right="1dp"
+ android:top="1dp"/>
+ <solid android:color="#102C3558"/>
+ <corners android:radius="24dp"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <padding
+ android:bottom="1dp"
+ android:left="1dp"
+ android:right="1dp"
+ android:top="0dp"/>
+ <solid android:color="#202C3558"/>
+ <corners android:radius="24dp"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <padding
+ android:bottom="1dp"
+ android:left="1dp"
+ android:right="1dp"
+ android:top="1dp"/>
+ <solid android:color="#382C3558"/>
+ <corners android:radius="24dp"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <padding
+ android:bottom="1dp"
+ android:left="0dp"
+ android:right="0dp"
+ android:top="0dp"/>
+ <solid android:color="#582C3558"/>
+ <corners android:radius="24dp"/>
+ </shape>
+ </item>
+ <item android:drawable="@drawable/pill_background"/>
+</layer-list> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml b/java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml
new file mode 100644
index 000000000..2b01f62f9
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="20dp"/>
+</shape> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml b/java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml
new file mode 100644
index 000000000..cfad8df57
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml
@@ -0,0 +1,22 @@
+<?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
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <!-- Color is theme dependent and will be overridden in code. -->
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="24dp"/>
+</shape> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml b/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml
new file mode 100644
index 000000000..b48e8d43f
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml
@@ -0,0 +1,26 @@
+<?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: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
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
new file mode 100644
index 000000000..7ba6a09e3
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml
@@ -0,0 +1,69 @@
+<?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
+ -->
+<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">
+
+ <include layout="@layout/rtt_banner"/>
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/rtt_recycler_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="70dp"
+ android:clipToPadding="false"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="4dp"
+ android:layout_marginStart="5dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="bottom"
+ android:orientation="horizontal">
+ <EditText
+ android:id="@+id/rtt_chat_input"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingTop="10dp"
+ android:paddingBottom="12dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:background="@drawable/input_bubble_background"
+ android:hint="@string/rtt_input_hint"
+ android:imeOptions="actionDone"
+ android:inputType="textMultiLine|text"
+ android:maxLines="4"
+ android:minHeight="53dp"
+ android:textSize="16sp"/>
+ <ImageButton
+ android:id="@+id/rtt_chat_submit_button"
+ android:layout_width="55dp"
+ android:layout_height="53dp"
+ android:layout_gravity="bottom"
+ android:background="@drawable/input_bubble_background"
+ android:backgroundTint="@color/submit_button_background_color"
+ android:backgroundTintMode="multiply"
+ android:contentDescription="@string/content_description_rtt_check_button"
+ android:src="@drawable/quantum_ic_done_vd_theme_24"
+ android:tint="@color/submit_button_color"/>
+ </LinearLayout>
+
+</FrameLayout> \ No newline at end of file
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
new file mode 100644
index 000000000..7d9cd6fc8
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml
@@ -0,0 +1,91 @@
+<?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
+ -->
+<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:elevation="3dp">
+ <ImageButton
+ android:id="@+id/rtt_back"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ 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_close_vd_theme_24"
+ android:tint="#DF000000"/>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:layout_marginStart="32dp"
+ android:layout_toEndOf="@id/rtt_back"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/rtt_name_or_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:includeFontPadding="false"
+ android:textAppearance="@style/Dialer.Incall.TextAppearance.RttTitle"
+ tools:text="Bruce Graham"/>
+ <Chronometer
+ android:id="@+id/rtt_timer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:includeFontPadding="false"
+ android:textAppearance="@style/Dialer.Incall.TextAppearance.RttTimer"
+ 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: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"/>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml b/java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml
new file mode 100644
index 000000000..54b0f4f6a
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml
@@ -0,0 +1,48 @@
+<?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="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:orientation="vertical">
+ <LinearLayout
+ android:id="@+id/rtt_chat_message_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/rtt_chat_avatar"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:visibility="gone"
+ android:contentDescription="@string/content_description_rtt_chat_avatar"/>
+ <TextView
+ android:id="@+id/rtt_chat_message"
+ style="@style/Dialer.Incall.TextAppearance.RttMessage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="9dp"
+ android:paddingBottom="9dp"
+ android:background="@drawable/message_bubble"
+ android:backgroundTint="@color/message_bubble_color"
+ android:maxWidth="292dp"/>
+ </LinearLayout>
+</LinearLayout> \ 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
new file mode 100644
index 000000000..402cac4a0
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?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
+ -->
+<resources>
+ <color name="rtt_status_bar_color">#E0E0E0</color>
+</resources> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/values/dimens.xml b/java/com/android/incallui/rtt/impl/res/values/dimens.xml
new file mode 100644
index 000000000..a3f230c08
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?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
+ -->
+<resources>
+ <dimen name="rtt_message_margin_top">16dp</dimen>
+ <dimen name="rtt_same_group_message_margin_top">2dp</dimen>
+</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
new file mode 100644
index 000000000..79377acda
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?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
+ -->
+<resources>
+ <!-- Content description for submit chat input button. [CHAR LIMIT=NONE] -->
+ <string name="content_description_rtt_check_button">Go ahead</string>
+
+ <!-- Content description for button of closing RTT chat window. [CHAR LIMIT=NONE] -->
+ <string name="content_description_rtt_back_button">Close RTT chat</string>
+
+ <!-- Hint text for input box. [CHAR LIMIT=NONE] -->
+ <string name="rtt_input_hint">Type a message</string>
+
+ <!-- Content description for avatar of RTT chat message. [CHAR LIMIT=NONE] -->
+ <string name="content_description_rtt_chat_avatar">Avatar</string>
+</resources> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/impl/res/values/styles.xml b/java/com/android/incallui/rtt/impl/res/values/styles.xml
new file mode 100644
index 000000000..b4bb91474
--- /dev/null
+++ b/java/com/android/incallui/rtt/impl/res/values/styles.xml
@@ -0,0 +1,35 @@
+<?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
+ -->
+<resources>
+ <style name="Dialer.Incall.TextAppearance.RttTitle" parent="Dialer.Incall.TextAppearance">
+ <item name="android:fontFamily">sans-serif</item>
+ <item name="android:textColor">#DD000000</item>
+ <item name="android:textSize">20sp</item>
+ </style>
+
+ <style name="Dialer.Incall.TextAppearance.RttMessage" parent="Dialer.Incall.TextAppearance">
+ <item name="android:fontFamily">sans-serif</item>
+ <item name="android:textColor">#DD000000</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+
+ <style name="Dialer.Incall.TextAppearance.RttTimer" parent="Dialer.Incall.TextAppearance">
+ <item name="android:fontFamily">sans-serif</item>
+ <item name="android:textColor">#DD000000</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+</resources> \ No newline at end of file