summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/quantum/res/drawable/quantum_ic_done_vd_theme_24.xml25
-rw-r--r--assets/quantum/res/drawable/quantum_ic_mic_off_vd_theme_24.xml25
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorMainMenu.java6
-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
-rw-r--r--packages.mk1
24 files changed, 1232 insertions, 0 deletions
diff --git a/assets/quantum/res/drawable/quantum_ic_done_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_done_vd_theme_24.xml
new file mode 100644
index 000000000..bd1887e5c
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_done_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
+</vector> \ No newline at end of file
diff --git a/assets/quantum/res/drawable/quantum_ic_mic_off_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_mic_off_vd_theme_24.xml
new file mode 100644
index 000000000..0519c555c
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_mic_off_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,11h-1.7c0,0.74 -0.16,1.43 -0.43,2.05l1.23,1.23c0.56,-0.98 0.9,-2.09 0.9,-3.28zM14.98,11.17c0,-0.06 0.02,-0.11 0.02,-0.17L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v0.18l5.98,5.99zM4.27,3L3,4.27l6.01,6.01L9.01,11c0,1.66 1.33,3 2.99,3 0.22,0 0.44,-0.03 0.65,-0.08l1.66,1.66c-0.71,0.33 -1.5,0.52 -2.31,0.52 -2.76,0 -5.3,-2.1 -5.3,-5.1L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c0.91,-0.13 1.77,-0.45 2.54,-0.9L19.73,21 21,19.73 4.27,3z"/>
+</vector> \ No newline at end of file
diff --git a/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java b/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java
index c48e2836e..4ef579f06 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java
@@ -31,6 +31,7 @@ import com.android.dialer.databasepopulator.VoicemailPopulator;
import com.android.dialer.enrichedcall.simulator.EnrichedCallSimulatorActivity;
import com.android.dialer.persistentlog.PersistentLogger;
import com.android.dialer.preferredsim.PreferredSimFallbackContract;
+import com.android.incallui.rtt.impl.RttChatActivity;
/** Implements the top level simulator menu. */
final class SimulatorMainMenu {
@@ -40,6 +41,7 @@ final class SimulatorMainMenu {
.addItem("Voice call", SimulatorVoiceCall.getActionProvider(activity))
.addItem(
"IMS video", SimulatorVideoCall.getActionProvider(activity.getApplicationContext()))
+ .addItem("Rtt call mock", () -> simulateRttCallMock(activity.getApplicationContext()))
.addItem(
"Notifications",
SimulatorNotifications.getActionProvider(activity.getApplicationContext()))
@@ -61,6 +63,10 @@ final class SimulatorMainMenu {
EnrichedCallSimulatorActivity.newIntent(activity.getApplicationContext())));
}
+ private static void simulateRttCallMock(@NonNull Context context) {
+ context.startActivity(new Intent(context, RttChatActivity.class));
+ }
+
private static void populateDatabase(@NonNull Context context) {
DialerExecutorComponent.get(context)
.dialerExecutorFactory()
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
diff --git a/packages.mk b/packages.mk
index 03268fd57..d01b3f15a 100644
--- a/packages.mk
+++ b/packages.mk
@@ -75,6 +75,7 @@ LOCAL_AAPT_FLAGS := \
com.android.incallui.hold \
com.android.incallui.incall.impl \
com.android.incallui.maps.impl \
+ com.android.incallui.rtt.impl \
com.android.incallui.sessiondata \
com.android.incallui.spam \
com.android.incallui.speakerbuttonlogic \