summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwangqi <wangqi@google.com>2018-04-17 14:48:03 -0700
committerCopybara-Service <copybara-piper@google.com>2018-04-17 15:55:51 -0700
commite00bbaeceb399da24f06c8f1a626cbbf07eab4ad (patch)
tree2f18f4411d650f4a162d03da62936e05bdaa088f
parent9a14f6a71206add856193cd90971d94c39f079fa (diff)
Add RTT transcript screen.
Bug: 67596257 Test: CallDetailsCursorLoaderTest PiperOrigin-RevId: 193259769 Change-Id: I8c6a8eb9a6bf06e9c1c25c45fc035f8db8ae5a65
-rw-r--r--java/com/android/dialer/app/calllog/CallLogAdapter.java5
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivity.java3
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivityCommon.java31
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsAdapter.java14
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java15
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsCursorLoader.java5
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java19
-rw-r--r--java/com/android/dialer/calldetails/OldCallDetailsActivity.java3
-rw-r--r--java/com/android/dialer/calldetails/OldCallDetailsAdapter.java33
-rw-r--r--java/com/android/dialer/calldetails/proto/call_details_entries.proto8
-rw-r--r--java/com/android/dialer/glidephotomanager/GlidePhotoManager.java10
-rw-r--r--java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java12
-rw-r--r--java/com/android/dialer/rtt/AndroidManifest.xml21
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptActivity.java122
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptAdapter.java88
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptMessageViewHolder.java95
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptUtil.java8
-rw-r--r--java/com/android/dialer/rtt/res/color/bubble_background.xml21
-rw-r--r--java/com/android/dialer/rtt/res/drawable/message_bubble.xml21
-rw-r--r--java/com/android/dialer/rtt/res/layout/activity_rtt_transcript.xml30
-rw-r--r--java/com/android/dialer/rtt/res/layout/rtt_transcript_list_item.xml54
-rw-r--r--java/com/android/dialer/rtt/res/values/colors.xml20
-rw-r--r--java/com/android/dialer/rtt/res/values/dimens.xml21
-rw-r--r--java/com/android/dialer/rtt/res/values/styles.xml36
-rw-r--r--java/com/android/incallui/RttCallPresenter.java2
-rw-r--r--packages.mk1
26 files changed, 690 insertions, 8 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index d25a2f38d..2f0c9b274 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -1008,7 +1008,10 @@ public class CallLogAdapter extends GroupingListAdapter
.setDataUsage(cursor.getLong(CallLogQuery.DATA_USAGE))
.setDate(cursor.getLong(CallLogQuery.DATE))
.setDuration(cursor.getLong(CallLogQuery.DURATION))
- .setFeatures(cursor.getInt(CallLogQuery.FEATURES));
+ .setFeatures(cursor.getInt(CallLogQuery.FEATURES))
+
+ .setCallMappingId(String.valueOf(cursor.getLong(CallLogQuery.DATE)));
+
String phoneAccountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
if (DuoConstants.PHONE_ACCOUNT_COMPONENT_NAME
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivity.java b/java/com/android/dialer/calldetails/CallDetailsActivity.java
index 4fab7fd85..f1d0d8487 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivity.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivity.java
@@ -23,6 +23,7 @@ import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import com.android.dialer.CoalescedIds;
+import com.android.dialer.calldetails.CallDetailsEntryViewHolder.CallDetailsEntryListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
@@ -89,6 +90,7 @@ public final class CallDetailsActivity extends CallDetailsActivityCommon {
@Override
protected CallDetailsAdapterCommon createAdapter(
+ CallDetailsEntryListener callDetailsEntryListener,
CallDetailsHeaderListener callDetailsHeaderListener,
ReportCallIdListener reportCallIdListener,
DeleteCallDetailsListener deleteCallDetailsListener) {
@@ -96,6 +98,7 @@ public final class CallDetailsActivity extends CallDetailsActivityCommon {
this,
headerInfo,
getCallDetailsEntries(),
+ callDetailsEntryListener,
callDetailsHeaderListener,
reportCallIdListener,
deleteCallDetailsListener);
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
index 15a010eba..dec1230bd 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
@@ -55,12 +55,14 @@ import com.android.dialer.duo.DuoComponent;
import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.enrichedcall.EnrichedCallManager;
import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult;
+import com.android.dialer.glidephotomanager.PhotoInfo;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.logging.UiAction;
import com.android.dialer.performancereport.PerformanceReport;
import com.android.dialer.postcall.PostCall;
import com.android.dialer.precall.PreCall;
+import com.android.dialer.rtt.RttTranscriptActivity;
import com.android.dialer.rtt.RttTranscriptUtil;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListenableFuture;
@@ -84,6 +86,8 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
public static final String EXTRA_CAN_REPORT_CALLER_ID = "can_report_caller_id";
public static final String EXTRA_CAN_SUPPORT_ASSISTED_DIALING = "can_support_assisted_dialing";
+ private final CallDetailsEntryViewHolder.CallDetailsEntryListener callDetailsEntryListener =
+ new CallDetailsEntryListener(this);
private final CallDetailsHeaderViewHolder.CallDetailsHeaderListener callDetailsHeaderListener =
new CallDetailsHeaderListener(this);
private final CallDetailsFooterViewHolder.DeleteCallDetailsListener deleteCallDetailsListener =
@@ -106,6 +110,7 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
/** Creates an adapter for {@link OldCallDetailsActivity} or {@link CallDetailsActivity}. */
protected abstract CallDetailsAdapterCommon createAdapter(
+ CallDetailsEntryViewHolder.CallDetailsEntryListener callDetailsEntryListener,
CallDetailsHeaderViewHolder.CallDetailsHeaderListener callDetailsHeaderListener,
CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener,
CallDetailsFooterViewHolder.DeleteCallDetailsListener deleteCallDetailsListener);
@@ -212,7 +217,11 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
private void setupRecyclerViewForEntries() {
adapter =
- createAdapter(callDetailsHeaderListener, reportCallIdListener, deleteCallDetailsListener);
+ createAdapter(
+ callDetailsEntryListener,
+ callDetailsHeaderListener,
+ reportCallIdListener,
+ deleteCallDetailsListener);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
@@ -288,6 +297,26 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
}
}
+ private static final class CallDetailsEntryListener
+ implements CallDetailsEntryViewHolder.CallDetailsEntryListener {
+ private final WeakReference<CallDetailsActivityCommon> activityWeakReference;
+
+ CallDetailsEntryListener(CallDetailsActivityCommon activity) {
+ this.activityWeakReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void showRttTranscript(String transcriptId, String primaryText, PhotoInfo photoInfo) {
+ getActivity()
+ .startActivity(
+ RttTranscriptActivity.getIntent(getActivity(), transcriptId, primaryText, photoInfo));
+ }
+
+ private CallDetailsActivityCommon getActivity() {
+ return Preconditions.checkNotNull(activityWeakReference.get());
+ }
+ }
+
private static final class CallDetailsHeaderListener
implements CallDetailsHeaderViewHolder.CallDetailsHeaderListener {
private final WeakReference<CallDetailsActivityCommon> activityWeakReference;
diff --git a/java/com/android/dialer/calldetails/CallDetailsAdapter.java b/java/com/android/dialer/calldetails/CallDetailsAdapter.java
index 2a4c1efca..40d856fa7 100644
--- a/java/com/android/dialer/calldetails/CallDetailsAdapter.java
+++ b/java/com/android/dialer/calldetails/CallDetailsAdapter.java
@@ -20,8 +20,10 @@ package com.android.dialer.calldetails;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
+import com.android.dialer.calldetails.CallDetailsEntryViewHolder.CallDetailsEntryListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
+import com.android.dialer.glidephotomanager.PhotoInfo;
/**
* A {@link RecyclerView.Adapter} for {@link CallDetailsActivity}.
@@ -38,12 +40,14 @@ final class CallDetailsAdapter extends CallDetailsAdapterCommon {
Context context,
CallDetailsHeaderInfo calldetailsHeaderInfo,
CallDetailsEntries callDetailsEntries,
+ CallDetailsEntryListener callDetailsEntryListener,
CallDetailsHeaderListener callDetailsHeaderListener,
CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener,
DeleteCallDetailsListener deleteCallDetailsListener) {
super(
context,
callDetailsEntries,
+ callDetailsEntryListener,
callDetailsHeaderListener,
reportCallIdListener,
deleteCallDetailsListener);
@@ -72,4 +76,14 @@ final class CallDetailsAdapter extends CallDetailsAdapterCommon {
protected String getNumber() {
return headerInfo.getDialerPhoneNumber().getNormalizedNumber();
}
+
+ @Override
+ protected String getPrimaryText() {
+ return headerInfo.getPrimaryText();
+ }
+
+ @Override
+ protected PhotoInfo getPhotoInfo() {
+ return headerInfo.getPhotoInfo();
+ }
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java b/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
index a79642bad..ec9263f1f 100644
--- a/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
+++ b/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
@@ -25,6 +25,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
+import com.android.dialer.calldetails.CallDetailsEntryViewHolder.CallDetailsEntryListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
@@ -33,6 +34,7 @@ import com.android.dialer.calllogutils.CallbackActionHelper;
import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
import com.android.dialer.common.Assert;
import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.glidephotomanager.PhotoInfo;
/**
* Contains common logic shared between {@link OldCallDetailsAdapter} and {@link
@@ -44,6 +46,7 @@ abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerVie
private static final int CALL_ENTRY_VIEW_TYPE = 2;
private static final int FOOTER_VIEW_TYPE = 3;
+ private final CallDetailsEntryListener callDetailsEntryListener;
private final CallDetailsHeaderListener callDetailsHeaderListener;
private final ReportCallIdListener reportCallIdListener;
private final DeleteCallDetailsListener deleteCallDetailsListener;
@@ -60,13 +63,21 @@ abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerVie
/** Returns the phone number of the call details. */
protected abstract String getNumber();
+ /** Returns the primary text shown on call details toolbar, usually contact name or number. */
+ protected abstract String getPrimaryText();
+
+ /** Returns {@link PhotoInfo} of the contact. */
+ protected abstract PhotoInfo getPhotoInfo();
+
CallDetailsAdapterCommon(
Context context,
CallDetailsEntries callDetailsEntries,
+ CallDetailsEntryListener callDetailsEntryListener,
CallDetailsHeaderListener callDetailsHeaderListener,
ReportCallIdListener reportCallIdListener,
DeleteCallDetailsListener deleteCallDetailsListener) {
this.callDetailsEntries = callDetailsEntries;
+ this.callDetailsEntryListener = callDetailsEntryListener;
this.callDetailsHeaderListener = callDetailsHeaderListener;
this.reportCallIdListener = reportCallIdListener;
this.deleteCallDetailsListener = deleteCallDetailsListener;
@@ -84,7 +95,7 @@ abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerVie
inflater.inflate(R.layout.contact_container, parent, false), callDetailsHeaderListener);
case CALL_ENTRY_VIEW_TYPE:
return new CallDetailsEntryViewHolder(
- inflater.inflate(R.layout.call_details_entry, parent, false));
+ inflater.inflate(R.layout.call_details_entry, parent, false), callDetailsEntryListener);
case FOOTER_VIEW_TYPE:
return new CallDetailsFooterViewHolder(
inflater.inflate(R.layout.call_details_footer, parent, false),
@@ -108,6 +119,8 @@ abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerVie
CallDetailsEntry entry = callDetailsEntries.getEntries(position - 1);
viewHolder.setCallDetails(
getNumber(),
+ getPrimaryText(),
+ getPhotoInfo(),
entry,
callTypeHelper,
!entry.getHistoryResultsList().isEmpty() && position != getItemCount() - 2);
diff --git a/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java b/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
index 3b8af4026..c22ec7318 100644
--- a/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
+++ b/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
@@ -139,7 +139,10 @@ public final class CallDetailsCursorLoader extends CursorLoader {
.setFeatures(cursor.getInt(FEATURES))
.setDate(cursor.getLong(TIMESTAMP))
.setDuration(cursor.getLong(DURATION))
- .setDataUsage(cursor.getLong(DATA_USAGE));
+ .setDataUsage(cursor.getLong(DATA_USAGE))
+
+ .setCallMappingId(String.valueOf(cursor.getLong(TIMESTAMP)));
+
String phoneAccountComponentName = cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME);
entry.setIsDuoCall(
diff --git a/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
index 5c4a196fa..37b212a63 100644
--- a/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
@@ -37,6 +37,7 @@ import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.AppCompatConstants;
import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult;
import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult.Type;
+import com.android.dialer.glidephotomanager.PhotoInfo;
import com.android.dialer.oem.MotorolaUtils;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.IntentUtil;
@@ -44,6 +45,14 @@ import com.android.dialer.util.IntentUtil;
/** ViewHolder for call entries in {@link OldCallDetailsActivity} or {@link CallDetailsActivity}. */
public class CallDetailsEntryViewHolder extends ViewHolder {
+ /** Listener for the call details header */
+ interface CallDetailsEntryListener {
+ /** Shows RTT transcript. */
+ void showRttTranscript(String transcriptId, String primaryText, PhotoInfo photoInfo);
+ }
+
+ private final CallDetailsEntryListener callDetailsEntryListener;
+
private final CallTypeIconsView callTypeIcon;
private final TextView callTypeText;
private final TextView callTime;
@@ -65,7 +74,8 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
private final Context context;
- public CallDetailsEntryViewHolder(View container) {
+ public CallDetailsEntryViewHolder(
+ View container, CallDetailsEntryListener callDetailsEntryListener) {
super(container);
context = container.getContext();
@@ -83,10 +93,13 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
multimediaAttachmentsNumber =
(TextView) container.findViewById(R.id.multimedia_attachments_number);
rttTranscript = container.findViewById(R.id.rtt_transcript);
+ this.callDetailsEntryListener = callDetailsEntryListener;
}
void setCallDetails(
String number,
+ String primaryText,
+ PhotoInfo photoInfo,
CallDetailsEntry entry,
CallTypeHelper callTypeHelper,
boolean showMultimediaDivider) {
@@ -133,6 +146,10 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
rttTranscript.setText(R.string.rtt_transcript_link);
rttTranscript.setTextAppearance(R.style.RttTranscriptLink);
rttTranscript.setClickable(true);
+ rttTranscript.setOnClickListener(
+ v ->
+ callDetailsEntryListener.showRttTranscript(
+ entry.getCallMappingId(), primaryText, photoInfo));
} else {
rttTranscript.setText(R.string.rtt_transcript_not_available);
rttTranscript.setTextAppearance(R.style.RttTranscriptMessage);
diff --git a/java/com/android/dialer/calldetails/OldCallDetailsActivity.java b/java/com/android/dialer/calldetails/OldCallDetailsActivity.java
index c97436759..26217ab8a 100644
--- a/java/com/android/dialer/calldetails/OldCallDetailsActivity.java
+++ b/java/com/android/dialer/calldetails/OldCallDetailsActivity.java
@@ -18,6 +18,7 @@ package com.android.dialer.calldetails;
import android.content.Context;
import android.content.Intent;
+import com.android.dialer.calldetails.CallDetailsEntryViewHolder.CallDetailsEntryListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
@@ -76,6 +77,7 @@ public final class OldCallDetailsActivity extends CallDetailsActivityCommon {
@Override
protected CallDetailsAdapterCommon createAdapter(
+ CallDetailsEntryListener callDetailsEntryListener,
CallDetailsHeaderListener callDetailsHeaderListener,
ReportCallIdListener reportCallIdListener,
DeleteCallDetailsListener deleteCallDetailsListener) {
@@ -83,6 +85,7 @@ public final class OldCallDetailsActivity extends CallDetailsActivityCommon {
/* context = */ this,
contact,
getCallDetailsEntries(),
+ callDetailsEntryListener,
callDetailsHeaderListener,
reportCallIdListener,
deleteCallDetailsListener);
diff --git a/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java b/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java
index 010f5cd6c..878803cc3 100644
--- a/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java
+++ b/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java
@@ -20,9 +20,12 @@ package com.android.dialer.calldetails;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
+import com.android.dialer.calldetails.CallDetailsEntryViewHolder.CallDetailsEntryListener;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
import com.android.dialer.dialercontact.DialerContact;
+import com.android.dialer.glidephotomanager.PhotoInfo;
+import com.android.dialer.lettertile.LetterTileDrawable;
/**
* A {@link RecyclerView.Adapter} for {@link OldCallDetailsActivity}.
@@ -39,12 +42,14 @@ final class OldCallDetailsAdapter extends CallDetailsAdapterCommon {
Context context,
DialerContact contact,
CallDetailsEntries callDetailsEntries,
+ CallDetailsEntryListener callDetailsEntryListener,
CallDetailsHeaderListener callDetailsHeaderListener,
CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener,
DeleteCallDetailsListener deleteCallDetailsListener) {
super(
context,
callDetailsEntries,
+ callDetailsEntryListener,
callDetailsHeaderListener,
reportCallIdListener,
deleteCallDetailsListener);
@@ -70,4 +75,32 @@ final class OldCallDetailsAdapter extends CallDetailsAdapterCommon {
protected String getNumber() {
return contact.getNumber();
}
+
+ @Override
+ protected String getPrimaryText() {
+ return contact.getNameOrNumber();
+ }
+
+ @Override
+ protected PhotoInfo getPhotoInfo() {
+ PhotoInfo.Builder builder =
+ PhotoInfo.newBuilder()
+ .setPhotoUri(contact.getPhotoUri())
+ .setPhotoId(contact.getPhotoId())
+ .setName(contact.getNameOrNumber())
+ .setLookupUri(contact.getContactUri());
+ switch (contact.getContactType()) {
+ case LetterTileDrawable.TYPE_VOICEMAIL:
+ builder.setIsVoicemail(true);
+ break;
+ case LetterTileDrawable.TYPE_BUSINESS:
+ builder.setIsBusiness(true);
+ break;
+ case LetterTileDrawable.TYPE_SPAM:
+ builder.setIsSpam(true);
+ break;
+ default: // fall out
+ }
+ return builder.build();
+ }
}
diff --git a/java/com/android/dialer/calldetails/proto/call_details_entries.proto b/java/com/android/dialer/calldetails/proto/call_details_entries.proto
index e0202cda1..0f11b537e 100644
--- a/java/com/android/dialer/calldetails/proto/call_details_entries.proto
+++ b/java/com/android/dialer/calldetails/proto/call_details_entries.proto
@@ -20,6 +20,14 @@ message CallDetailsEntries {
repeated enrichedcall.historyquery.proto.HistoryResult history_results = 7;
optional bool is_duo_call = 8;
optional bool has_rtt_transcript = 9;
+ // A unique ID that could be used to map a call log entry to a {@link
+ // android.telecom.Call}. This is different from call_id which is id of call
+ // log entry.
+ // On pre-Q this will be {@link android.provider.CallLog.Calls#DATE} which
+ // is same as {@link com.android.telecom.Call#getCreationTimeMillis()}.
+ // Starting from Q this will be a call UUID generated by system to associate
+ // a call log to a telecom call.
+ optional string call_mapping_id = 10;
}
repeated CallDetailsEntry entries = 1;
diff --git a/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java b/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java
index 519a39481..de16c387d 100644
--- a/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java
+++ b/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java
@@ -17,6 +17,7 @@
package com.android.dialer.glidephotomanager;
import android.support.annotation.MainThread;
+import android.widget.ImageView;
import android.widget.QuickContactBadge;
/** Class to load photo for call/contacts */
@@ -30,4 +31,13 @@ public interface GlidePhotoManager {
*/
@MainThread
void loadQuickContactBadge(QuickContactBadge badge, PhotoInfo photoInfo);
+
+ /**
+ * Load {@code photoInfo} into the {@code imageView}. The loading is performed in the background
+ * and a placeholder will be used appropriately. {@code imageView} must be already attached to an
+ * activity/fragment, and the load will be automatically canceled if the lifecycle of the activity
+ * ends.
+ */
+ @MainThread
+ void loadContactPhoto(ImageView imageView, PhotoInfo photoInfo);
}
diff --git a/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java b/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java
index 202307a29..562177c48 100644
--- a/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java
+++ b/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java
@@ -25,6 +25,7 @@ import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import android.widget.ImageView;
import android.widget.QuickContactBadge;
import com.android.dialer.common.Assert;
import com.android.dialer.glide.GlideApp;
@@ -54,8 +55,15 @@ public class GlidePhotoManagerImpl implements GlidePhotoManager {
? DefaultLookupUriGenerator.generateUri(photoInfo)
: parseUri(photoInfo.getLookupUri()));
badge.setOverlay(null);
- GlideRequest<Drawable> request = buildRequest(GlideApp.with(badge), photoInfo);
- request.into(badge);
+ loadContactPhoto(badge, photoInfo);
+ }
+
+ @MainThread
+ @Override
+ public void loadContactPhoto(ImageView imageView, PhotoInfo photoInfo) {
+ Assert.isMainThread();
+ GlideRequest<Drawable> request = buildRequest(GlideApp.with(imageView), photoInfo);
+ request.into(imageView);
}
private GlideRequest<Drawable> buildRequest(GlideRequests requestManager, PhotoInfo photoInfo) {
diff --git a/java/com/android/dialer/rtt/AndroidManifest.xml b/java/com/android/dialer/rtt/AndroidManifest.xml
new file mode 100644
index 000000000..c92fb1ceb
--- /dev/null
+++ b/java/com/android/dialer/rtt/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ 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.dialer.rtt"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <application>
+ <activity android:name=".RttTranscriptActivity" />
+ </application>
+</manifest> \ No newline at end of file
diff --git a/java/com/android/dialer/rtt/RttTranscriptActivity.java b/java/com/android/dialer/rtt/RttTranscriptActivity.java
new file mode 100644
index 000000000..2087250b3
--- /dev/null
+++ b/java/com/android/dialer/rtt/RttTranscriptActivity.java
@@ -0,0 +1,122 @@
+/*
+ * 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.dialer.rtt;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.MenuItem;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.UiListener;
+import com.android.dialer.glidephotomanager.PhotoInfo;
+import com.android.dialer.protos.ProtoParsers;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/** Activity holds RTT transcript. */
+public class RttTranscriptActivity extends AppCompatActivity {
+
+ public static final String EXTRA_TRANSCRIPT_ID = "extra_transcript_id";
+ public static final String EXTRA_PRIMARY_TEXT = "extra_primary_text";
+ public static final String EXTRA_PHOTO_INFO = "extra_photo_info";
+
+ private RttTranscriptAdapter adapter;
+ private UiListener<RttTranscript> rttTranscriptUiListener;
+
+ public static Intent getIntent(
+ Context context, String transcriptId, String primaryText, PhotoInfo photoInfo) {
+ Intent intent = new Intent(context, RttTranscriptActivity.class);
+ intent.putExtra(RttTranscriptActivity.EXTRA_TRANSCRIPT_ID, transcriptId);
+ intent.putExtra(RttTranscriptActivity.EXTRA_PRIMARY_TEXT, primaryText);
+ ProtoParsers.put(intent, RttTranscriptActivity.EXTRA_PHOTO_INFO, Assert.isNotNull(photoInfo));
+ return intent;
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.activity_rtt_transcript);
+ ActionBar actionBar = getSupportActionBar();
+ actionBar.setDisplayShowHomeEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+
+ RecyclerView recyclerView = findViewById(R.id.rtt_recycler_view);
+ LinearLayoutManager layoutManager = new LinearLayoutManager(this);
+ layoutManager.setStackFromEnd(true);
+ recyclerView.setLayoutManager(layoutManager);
+ recyclerView.setHasFixedSize(true);
+ adapter = new RttTranscriptAdapter(this);
+ recyclerView.setAdapter(adapter);
+
+ rttTranscriptUiListener =
+ DialerExecutorComponent.get(this)
+ .createUiListener(getFragmentManager(), "Load RTT transcript");
+ handleIntent(getIntent());
+ }
+
+ private void handleIntent(Intent intent) {
+ Assert.checkArgument(intent.hasExtra(EXTRA_TRANSCRIPT_ID));
+ Assert.checkArgument(intent.hasExtra(EXTRA_PRIMARY_TEXT));
+ Assert.checkArgument(intent.hasExtra(EXTRA_PHOTO_INFO));
+
+ String id = intent.getStringExtra(EXTRA_TRANSCRIPT_ID);
+ rttTranscriptUiListener.listen(
+ this,
+ getRttTranscript(id),
+ adapter::setRttTranscript,
+ throwable -> {
+ throw new RuntimeException(throwable);
+ });
+
+ String primaryText = intent.getStringExtra(EXTRA_PRIMARY_TEXT);
+ getSupportActionBar().setTitle(primaryText);
+
+ PhotoInfo photoInfo =
+ ProtoParsers.getTrusted(intent, EXTRA_PHOTO_INFO, PhotoInfo.getDefaultInstance());
+ // Photo shown here shouldn't have video or RTT badge.
+ PhotoInfo sanitizedPhotoInfo =
+ PhotoInfo.newBuilder().mergeFrom(photoInfo).setIsRtt(false).setIsVideo(false).build();
+ adapter.setPhotoInfo(sanitizedPhotoInfo);
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ handleIntent(intent);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private ListenableFuture<RttTranscript> getRttTranscript(String id) {
+ return DialerExecutorComponent.get(this)
+ .backgroundExecutor()
+ .submit(() -> new RttTranscriptUtil(this).getRttTranscript(id));
+ }
+}
diff --git a/java/com/android/dialer/rtt/RttTranscriptAdapter.java b/java/com/android/dialer/rtt/RttTranscriptAdapter.java
new file mode 100644
index 000000000..6e030349d
--- /dev/null
+++ b/java/com/android/dialer/rtt/RttTranscriptAdapter.java
@@ -0,0 +1,88 @@
+/*
+ * 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.dialer.rtt;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.dialer.glidephotomanager.PhotoInfo;
+
+/** Adapter class for holding RTT chat data. */
+public class RttTranscriptAdapter extends RecyclerView.Adapter<RttTranscriptMessageViewHolder> {
+
+ private PhotoInfo photoInfo;
+
+ private final Context context;
+ private RttTranscript rttTranscript;
+
+ RttTranscriptAdapter(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public RttTranscriptMessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ LayoutInflater layoutInflater = LayoutInflater.from(context);
+ View view = layoutInflater.inflate(R.layout.rtt_transcript_list_item, parent, false);
+ return new RttTranscriptMessageViewHolder(view);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return super.getItemViewType(position);
+ }
+
+ @Override
+ public void onBindViewHolder(RttTranscriptMessageViewHolder rttChatMessageViewHolder, int i) {
+ boolean isSameGroup = false;
+ boolean hasMoreInSameGroup = false;
+ RttTranscriptMessage rttTranscriptMessage = rttTranscript.getMessages(i);
+ if (i > 0) {
+ isSameGroup =
+ rttTranscriptMessage.getIsRemote() == rttTranscript.getMessages(i - 1).getIsRemote();
+ }
+ if (i + 1 < getItemCount()) {
+ hasMoreInSameGroup =
+ rttTranscriptMessage.getIsRemote() == rttTranscript.getMessages(i + 1).getIsRemote();
+ }
+ rttChatMessageViewHolder.setMessage(rttTranscriptMessage, isSameGroup, photoInfo);
+ if (hasMoreInSameGroup) {
+ rttChatMessageViewHolder.hideTimestamp();
+ } else {
+ rttChatMessageViewHolder.showTimestamp(
+ rttTranscriptMessage.getTimestamp(), rttTranscriptMessage.getIsRemote(), i == 0);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ if (rttTranscript == null) {
+ return 0;
+ }
+ return rttTranscript.getMessagesCount();
+ }
+
+ void setRttTranscript(RttTranscript rttTranscript) {
+ this.rttTranscript = rttTranscript;
+ notifyDataSetChanged();
+ }
+
+ void setPhotoInfo(PhotoInfo photoInfo) {
+ this.photoInfo = photoInfo;
+ }
+}
diff --git a/java/com/android/dialer/rtt/RttTranscriptMessageViewHolder.java b/java/com/android/dialer/rtt/RttTranscriptMessageViewHolder.java
new file mode 100644
index 000000000..daa8136fe
--- /dev/null
+++ b/java/com/android/dialer/rtt/RttTranscriptMessageViewHolder.java
@@ -0,0 +1,95 @@
+/*
+ * 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.dialer.rtt;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.text.format.DateUtils;
+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;
+import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent;
+import com.android.dialer.glidephotomanager.PhotoInfo;
+
+/** ViewHolder class for RTT chat message bubble. */
+public class RttTranscriptMessageViewHolder extends ViewHolder {
+
+ private final TextView messageTextView;
+ private final Resources resources;
+ private final ImageView avatarImageView;
+ private final View container;
+ private final TextView timestampTextView;
+
+ RttTranscriptMessageViewHolder(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);
+ timestampTextView = view.findViewById(R.id.rtt_chat_timestamp);
+ resources = view.getResources();
+ }
+
+ void setMessage(RttTranscriptMessage message, boolean isSameGroup, PhotoInfo photoInfo) {
+ messageTextView.setText(message.getContent());
+ LinearLayout.LayoutParams params = (LayoutParams) container.getLayoutParams();
+ params.gravity = message.getIsRemote() ? Gravity.START : Gravity.END;
+ params.topMargin =
+ isSameGroup
+ ? resources.getDimensionPixelSize(R.dimen.rtt_transcript_same_group_message_margin_top)
+ : resources.getDimensionPixelSize(R.dimen.rtt_transcript_message_margin_top);
+ container.setLayoutParams(params);
+ messageTextView.setEnabled(message.getIsRemote());
+ if (message.getIsRemote()) {
+ if (isSameGroup) {
+ avatarImageView.setVisibility(View.INVISIBLE);
+ } else {
+ avatarImageView.setVisibility(View.VISIBLE);
+ GlidePhotoManagerComponent.get(container.getContext())
+ .glidePhotoManager()
+ .loadContactPhoto(avatarImageView, photoInfo);
+ }
+ messageTextView.setTextAppearance(R.style.RttTranscriptBubble_Remote);
+ } else {
+ avatarImageView.setVisibility(View.GONE);
+ messageTextView.setTextAppearance(R.style.RttTranscriptBubble_Local);
+ }
+ }
+
+ void showTimestamp(long timestamp, boolean isRemote, boolean showFullDate) {
+ timestampTextView.setVisibility(View.VISIBLE);
+ timestampTextView.setText(
+ getTimestampText(timestampTextView.getContext(), timestamp, showFullDate));
+ timestampTextView.setGravity(isRemote ? Gravity.START : Gravity.END);
+ }
+
+ void hideTimestamp() {
+ timestampTextView.setVisibility(View.GONE);
+ }
+
+ private String getTimestampText(Context context, long timestamp, boolean showFullDate) {
+ return DateUtils.formatDateTime(
+ context,
+ timestamp,
+ showFullDate
+ ? DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME
+ : DateUtils.FORMAT_SHOW_TIME);
+ }
+}
diff --git a/java/com/android/dialer/rtt/RttTranscriptUtil.java b/java/com/android/dialer/rtt/RttTranscriptUtil.java
index e55d2ea55..19b46b01a 100644
--- a/java/com/android/dialer/rtt/RttTranscriptUtil.java
+++ b/java/com/android/dialer/rtt/RttTranscriptUtil.java
@@ -30,7 +30,13 @@ public final class RttTranscriptUtil {
private final RttTranscriptDatabaseHelper databaseHelper;
public RttTranscriptUtil(Context context) {
- databaseHelper = new RttTranscriptDatabaseHelper(context);
+ databaseHelper = new RttTranscriptDatabaseHelper(context.getApplicationContext());
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ databaseHelper.close();
+ super.finalize();
}
/** @return true if there is RTT transcript available. */
diff --git a/java/com/android/dialer/rtt/res/color/bubble_background.xml b/java/com/android/dialer/rtt/res/color/bubble_background.xml
new file mode 100644
index 000000000..fb29ab6c5
--- /dev/null
+++ b/java/com/android/dialer/rtt/res/color/bubble_background.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="@android:color/white" />
+ <item android:color="@color/rtt_transcript_primary_color" />
+</selector> \ No newline at end of file
diff --git a/java/com/android/dialer/rtt/res/drawable/message_bubble.xml b/java/com/android/dialer/rtt/res/drawable/message_bubble.xml
new file mode 100644
index 000000000..2b01f62f9
--- /dev/null
+++ b/java/com/android/dialer/rtt/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/dialer/rtt/res/layout/activity_rtt_transcript.xml b/java/com/android/dialer/rtt/res/layout/activity_rtt_transcript.xml
new file mode 100644
index 000000000..628a7932e
--- /dev/null
+++ b/java/com/android/dialer/rtt/res/layout/activity_rtt_transcript.xml
@@ -0,0 +1,30 @@
+<?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/rtt_transcript_background_color">
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/rtt_recycler_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:clipToPadding="false"/>
+
+</FrameLayout>
diff --git a/java/com/android/dialer/rtt/res/layout/rtt_transcript_list_item.xml b/java/com/android/dialer/rtt/res/layout/rtt_transcript_list_item.xml
new file mode 100644
index 000000000..d86a6823a
--- /dev/null
+++ b/java/com/android/dialer/rtt/res/layout/rtt_transcript_list_item.xml
@@ -0,0 +1,54 @@
+<?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="@dimen/rtt_transcript_avatar_size"
+ android:layout_height="@dimen/rtt_transcript_avatar_size"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/rtt_chat_message"
+ style="@style/RttTranscriptBubble"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="9dp"
+ android:paddingBottom="9dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:background="@drawable/message_bubble"
+ android:backgroundTint="@color/bubble_background"
+ android:maxWidth="292dp"/>
+ </LinearLayout>
+ <TextView
+ android:id="@+id/rtt_chat_timestamp"
+ style="@style/RttTranscriptBubble.Timestamp"
+ android:paddingStart="64dp"
+ android:paddingEnd="8dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+</LinearLayout> \ No newline at end of file
diff --git a/java/com/android/dialer/rtt/res/values/colors.xml b/java/com/android/dialer/rtt/res/values/colors.xml
new file mode 100644
index 000000000..5de06f9f2
--- /dev/null
+++ b/java/com/android/dialer/rtt/res/values/colors.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>
+ <color name="rtt_transcript_primary_color">#37474F</color>
+ <color name="rtt_transcript_background_color">#ECEFF1</color>
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/rtt/res/values/dimens.xml b/java/com/android/dialer/rtt/res/values/dimens.xml
new file mode 100644
index 000000000..a36cdd746
--- /dev/null
+++ b/java/com/android/dialer/rtt/res/values/dimens.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
+ -->
+<resources>
+ <dimen name="rtt_transcript_message_margin_top">16dp</dimen>
+ <dimen name="rtt_transcript_same_group_message_margin_top">2dp</dimen>
+ <dimen name="rtt_transcript_avatar_size">40dp</dimen>
+</resources>
diff --git a/java/com/android/dialer/rtt/res/values/styles.xml b/java/com/android/dialer/rtt/res/values/styles.xml
new file mode 100644
index 000000000..d8bc245ef
--- /dev/null
+++ b/java/com/android/dialer/rtt/res/values/styles.xml
@@ -0,0 +1,36 @@
+<?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="RttTranscriptBubble">
+ <item name="android:fontFamily">sans-serif</item>
+ <item name="android:textColor">#DD000000</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+
+ <style name="RttTranscriptBubble.Remote">
+ <item name="android:textColor">#FFFFFF</item>
+ </style>
+
+ <style name="RttTranscriptBubble.Local">
+ <item name="android:textColor">#DD000000</item>
+ </style>
+
+ <style name="RttTranscriptBubble.Timestamp">
+ <item name="android:textColor">#757575</item>
+ <item name="android:textSize">12sp</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/java/com/android/incallui/RttCallPresenter.java b/java/com/android/incallui/RttCallPresenter.java
index 21e28cee4..211469147 100644
--- a/java/com/android/incallui/RttCallPresenter.java
+++ b/java/com/android/incallui/RttCallPresenter.java
@@ -90,7 +90,9 @@ public class RttCallPresenter implements RttCallScreenDelegate, InCallStateListe
LogUtil.enterBlock("RttCallPresenter.saveTranscript");
RttTranscript.Builder builder = RttTranscript.newBuilder();
builder
+
.setId(String.valueOf(dialerCall.getCreationTimeMillis()))
+
.setTimestamp(dialerCall.getCreationTimeMillis())
.setNumber(dialerCall.getNumber())
.addAllMessages(rttCallScreen.getRttTranscriptMessageList());
diff --git a/packages.mk b/packages.mk
index 5ccef539a..f31066906 100644
--- a/packages.mk
+++ b/packages.mk
@@ -53,6 +53,7 @@ LOCAL_AAPT_FLAGS := \
com.android.dialer.precall.externalreceiver \
com.android.dialer.preferredsim.impl \
com.android.dialer.preferredsim.suggestion \
+ com.android.dialer.rtt \
com.android.dialer.searchfragment.common \
com.android.dialer.searchfragment.cp2 \
com.android.dialer.searchfragment.directories \