summaryrefslogtreecommitdiff
path: root/java/com/android
diff options
context:
space:
mode:
authorwangqi <wangqi@google.com>2018-04-12 14:44:06 -0700
committerCopybara-Service <copybara-piper@google.com>2018-04-12 16:20:40 -0700
commitd6b10d559f345eab2dd3dd89b07cfc3fd79c59bc (patch)
tree0f1f4cc08e164cde9f891f83749edff34eb94a89 /java/com/android
parent9ef6d8c84b7b33e069258d41db9eef16e3d2b9fa (diff)
Add RTT transcript to call details.
1. Save RTT transcript when call is destroyed 2. Show RTT transcript link when it's available Bug: 67596257,77717594 Test: manual PiperOrigin-RevId: 192673172 Change-Id: If541ad9137c965166548d2fb449e835b95566727
Diffstat (limited to 'java/com/android')
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivity.java1
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivityCommon.java50
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java3
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java17
-rw-r--r--java/com/android/dialer/calldetails/proto/call_details_entries.proto1
-rw-r--r--java/com/android/dialer/calldetails/res/layout/call_details_entry.xml37
-rw-r--r--java/com/android/dialer/calldetails/res/values/strings.xml6
-rw-r--r--java/com/android/dialer/calldetails/res/values/styles.xml12
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptContract.java40
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptDatabaseHelper.java56
-rw-r--r--java/com/android/dialer/rtt/RttTranscriptUtil.java97
-rw-r--r--java/com/android/dialer/theme/res/values/colors.xml2
-rw-r--r--java/com/android/incallui/RttCallPresenter.java22
-rw-r--r--java/com/android/incallui/call/CallList.java1
-rw-r--r--java/com/android/incallui/call/DialerCall.java28
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatFragment.java3
-rw-r--r--java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java2
17 files changed, 355 insertions, 23 deletions
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivity.java b/java/com/android/dialer/calldetails/CallDetailsActivity.java
index 4dc294e76..f0f9711ca 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivity.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivity.java
@@ -134,7 +134,6 @@ public final class CallDetailsActivity extends CallDetailsActivityCommon {
private void updateCallDetailsEntries(CallDetailsEntries newEntries) {
activity.setCallDetailsEntries(newEntries);
- activity.getAdapter().updateCallDetailsEntries(newEntries);
EnrichedCallComponent.get(activity)
.getEnrichedCallManager()
.requestAllHistoricalData(activity.getNumber(), newEntries);
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
index dea1b8cda..46705eb2a 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
@@ -26,9 +26,11 @@ import android.os.Bundle;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.support.annotation.CallSuper;
+import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
+import android.support.annotation.WorkerThread;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@@ -45,6 +47,7 @@ import com.android.dialer.common.concurrent.DialerExecutor.FailureListener;
import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.UiListener;
import com.android.dialer.common.database.Selection;
import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.duo.Duo;
@@ -58,7 +61,9 @@ 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.RttTranscriptUtil;
import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
@@ -91,6 +96,7 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
private CallDetailsAdapterCommon adapter;
private CallDetailsEntries callDetailsEntries;
+ private UiListener<CallDetailsEntries> checkRttTranscriptAvailabilityListener;
/**
* Handles the intent that launches {@link OldCallDetailsActivity} or {@link CallDetailsActivity},
@@ -121,6 +127,9 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
});
handleIntent(getIntent());
setupRecyclerViewForEntries();
+ checkRttTranscriptAvailabilityListener =
+ DialerExecutorComponent.get(this)
+ .createUiListener(getFragmentManager(), "Query RTT transcript availability");
}
@Override
@@ -143,6 +152,40 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
EnrichedCallComponent.get(this)
.getEnrichedCallManager()
.requestAllHistoricalData(getNumber(), callDetailsEntries);
+ checkRttTranscriptAvailabilityListener.listen(
+ this,
+ checkRttTranscriptAvailability(),
+ this::setCallDetailsEntries,
+ throwable -> {
+ throw new RuntimeException(throwable);
+ });
+ }
+
+ private ListenableFuture<CallDetailsEntries> checkRttTranscriptAvailability() {
+ return DialerExecutorComponent.get(this)
+ .backgroundExecutor()
+ .submit(() -> checkRttTranscriptAvailabilityInBackground(callDetailsEntries));
+ }
+
+ /**
+ * Check RTT transcript availability.
+ *
+ * @param input the original {@link CallDetailsEntries}
+ * @return {@link CallDetailsEntries} with updated RTT transcript availability.
+ */
+ @WorkerThread
+ private CallDetailsEntries checkRttTranscriptAvailabilityInBackground(
+ @Nullable CallDetailsEntries input) {
+ RttTranscriptUtil rttTranscriptUtil = new RttTranscriptUtil(this);
+
+ CallDetailsEntries.Builder mutableCallDetailsEntries = CallDetailsEntries.newBuilder();
+ for (CallDetailsEntry entry : input.getEntriesList()) {
+ CallDetailsEntry.Builder newEntry = CallDetailsEntry.newBuilder().mergeFrom(entry);
+ newEntry.setHasRttTranscript(
+ rttTranscriptUtil.checkRttTranscriptAvailability(String.valueOf(entry.getDate())));
+ mutableCallDetailsEntries.addEntries(newEntry.build());
+ }
+ return mutableCallDetailsEntries.build();
}
@Override
@@ -185,8 +228,13 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
super.onBackPressed();
}
+ @MainThread
protected final void setCallDetailsEntries(CallDetailsEntries entries) {
+ Assert.isMainThread();
this.callDetailsEntries = entries;
+ if (adapter != null) {
+ adapter.updateCallDetailsEntries(entries);
+ }
}
protected final CallDetailsEntries getCallDetailsEntries() {
@@ -415,7 +463,7 @@ abstract class CallDetailsActivityCommon extends AppCompatActivity {
Map<CallDetailsEntry, List<HistoryResult>> mappedResults =
getAllHistoricalData(activity.getNumber(), activity.callDetailsEntries);
- activity.adapter.updateCallDetailsEntries(
+ activity.setCallDetailsEntries(
generateAndMapNewCallDetailsEntriesHistoryResults(
activity.getNumber(), activity.callDetailsEntries, mappedResults));
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java b/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
index 27feff89d..a79642bad 100644
--- a/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
+++ b/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
@@ -18,6 +18,7 @@ package com.android.dialer.calldetails;
import android.content.Context;
import android.support.annotation.CallSuper;
+import android.support.annotation.MainThread;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
@@ -137,7 +138,9 @@ abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerVie
return callDetailsEntries;
}
+ @MainThread
final void updateCallDetailsEntries(CallDetailsEntries entries) {
+ Assert.isMainThread();
callDetailsEntries = entries;
notifyDataSetChanged();
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
index edf25df99..5c4a196fa 100644
--- a/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
@@ -55,6 +55,7 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
private final TextView multimediaDetails;
private final TextView postCallNote;
+ private final TextView rttTranscript;
private final ImageView multimediaImage;
@@ -81,6 +82,7 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
multimediaImage = (ImageView) container.findViewById(R.id.multimedia_image);
multimediaAttachmentsNumber =
(TextView) container.findViewById(R.id.multimedia_attachments_number);
+ rttTranscript = container.findViewById(R.id.rtt_transcript);
}
void setCallDetails(
@@ -94,6 +96,9 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
(entry.getFeatures() & Calls.FEATURES_PULLED_EXTERNALLY)
== Calls.FEATURES_PULLED_EXTERNALLY;
boolean isDuoCall = entry.getIsDuoCall();
+ boolean isRttCall =
+ BuildCompat.isAtLeastP()
+ && (entry.getFeatures() & Calls.FEATURES_RTT) == Calls.FEATURES_RTT;
callTime.setTextColor(getColorForCallType(context, callType));
callTypeIcon.clear();
@@ -123,6 +128,18 @@ public class CallDetailsEntryViewHolder extends ViewHolder {
context, entry.getDuration(), entry.getDataUsage()));
}
setMultimediaDetails(number, entry, showMultimediaDivider);
+ if (isRttCall) {
+ if (entry.getHasRttTranscript()) {
+ rttTranscript.setText(R.string.rtt_transcript_link);
+ rttTranscript.setTextAppearance(R.style.RttTranscriptLink);
+ rttTranscript.setClickable(true);
+ } else {
+ rttTranscript.setText(R.string.rtt_transcript_not_available);
+ rttTranscript.setTextAppearance(R.style.RttTranscriptMessage);
+ rttTranscript.setClickable(false);
+ }
+ rttTranscript.setVisibility(View.VISIBLE);
+ }
}
private void setMultimediaDetails(String number, CallDetailsEntry entry, boolean showDivider) {
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 7a5700b1c..e0202cda1 100644
--- a/java/com/android/dialer/calldetails/proto/call_details_entries.proto
+++ b/java/com/android/dialer/calldetails/proto/call_details_entries.proto
@@ -19,6 +19,7 @@ message CallDetailsEntries {
optional int64 data_usage = 6;
repeated enrichedcall.historyquery.proto.HistoryResult history_results = 7;
optional bool is_duo_call = 8;
+ optional bool has_rtt_transcript = 9;
}
repeated CallDetailsEntry entries = 1;
diff --git a/java/com/android/dialer/calldetails/res/layout/call_details_entry.xml b/java/com/android/dialer/calldetails/res/layout/call_details_entry.xml
index 3d4750d09..1e989966a 100644
--- a/java/com/android/dialer/calldetails/res/layout/call_details_entry.xml
+++ b/java/com/android/dialer/calldetails/res/layout/call_details_entry.xml
@@ -30,60 +30,71 @@
<TextView
android:id="@+id/call_type"
+ style="@style/PrimaryText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/call_entry_text_left_margin"
android:layout_marginEnd="16dp"
android:layout_toStartOf="@+id/call_duration"
android:gravity="start"
- android:maxLines="100"
- style="@style/PrimaryText"/>
+ android:maxLines="100"/>
<TextView
android:id="@+id/call_time"
+ style="@style/SecondaryText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/call_entry_text_left_margin"
- android:layout_below="@+id/call_type"
android:layout_marginBottom="@dimen/call_entry_bottom_padding"
- style="@style/SecondaryText"/>
+ android:layout_marginStart="@dimen/call_entry_text_left_margin"
+ android:layout_below="@+id/call_type"/>
<TextView
android:id="@+id/call_duration"
+ style="@style/PrimaryText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/call_entry_padding"
- style="@style/PrimaryText"/>
+ android:layout_alignParentEnd="true"/>
<include
- layout="@layout/ec_data_container"
android:id="@+id/ec_container"
- android:layout_height="@dimen/ec_container_height"
+ layout="@layout/ec_data_container"
android:layout_width="match_parent"
+ android:layout_height="@dimen/ec_container_height"
android:layout_below="@+id/call_time"
android:visibility="gone"/>
<TextView
android:id="@+id/post_call_note"
+ style="@style/SecondaryText"
android:layout_width="match_parent"
android:layout_height="@dimen/ec_container_height"
android:layout_below="@+id/ec_container"
android:paddingStart="@dimen/call_entry_text_left_margin"
+ android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:maxLines="2"
- android:visibility="gone"
- android:background="?attr/selectableItemBackground"
- style="@style/SecondaryText"/>
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/rtt_transcript"
+ style="@style/SecondaryText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/call_entry_bottom_padding"
+ android:layout_marginStart="@dimen/call_entry_text_left_margin"
+ android:layout_marginEnd="@dimen/call_entry_padding"
+ android:layout_below="@id/post_call_note"
+ android:maxLines="2"
+ android:visibility="gone"/>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
- android:layout_below="@id/post_call_note"
android:layout_marginTop="@dimen/ec_divider_top_bottom_margin"
android:layout_marginBottom="@dimen/ec_divider_top_bottom_margin"
android:layout_marginStart="@dimen/call_entry_text_left_margin"
+ android:layout_below="@id/rtt_transcript"
android:background="#12000000"
android:visibility="gone"/>
</RelativeLayout> \ No newline at end of file
diff --git a/java/com/android/dialer/calldetails/res/values/strings.xml b/java/com/android/dialer/calldetails/res/values/strings.xml
index f81696034..c3fff20bc 100644
--- a/java/com/android/dialer/calldetails/res/values/strings.xml
+++ b/java/com/android/dialer/calldetails/res/values/strings.xml
@@ -55,4 +55,10 @@
<!-- A fallback string for the assisted dialing header incase parsing failes.. [CHAR LIMIT=NONE] -->
<string name="assisted_dialing_country_code_entry_failure">Assisted dialing was used</string>
+
+ <!-- String shown when RTT transcript is not available for any reason. [CHAR LIMIT=NONE] -->
+ <string name="rtt_transcript_not_available">Transcript available only for calls with messaging</string>
+
+ <!-- String shown when RTT transcript is available. [CHAR LIMIT=NONE] -->
+ <string name="rtt_transcript_link">See transcript</string>
</resources>
diff --git a/java/com/android/dialer/calldetails/res/values/styles.xml b/java/com/android/dialer/calldetails/res/values/styles.xml
index 1a2b52994..93567ef73 100644
--- a/java/com/android/dialer/calldetails/res/values/styles.xml
+++ b/java/com/android/dialer/calldetails/res/values/styles.xml
@@ -27,4 +27,16 @@
<item name="android:textColor">#8A000000</item>
<item name="android:textSize">14sp</item>
</style>
+
+ <style name="RttTranscriptLink">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:textColor">@color/dialer_link_color</item>
+ <item name="android:textAllCaps">true</item>
+ <item name="textAllCaps">true</item>
+ </style>
+ <style name="RttTranscriptMessage" parent="SecondaryText">
+ <item name="android:fontFamily">sans-serif</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="textAllCaps">false</item>
+ </style>
</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/rtt/RttTranscriptContract.java b/java/com/android/dialer/rtt/RttTranscriptContract.java
new file mode 100644
index 000000000..ddc9c5345
--- /dev/null
+++ b/java/com/android/dialer/rtt/RttTranscriptContract.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/** Contract for the RTT transcript database. */
+public final class RttTranscriptContract {
+
+ /** Columns for RTT transcript. */
+ static final class RttTranscriptColumn {
+
+ /**
+ * Unique key that should match {@link android.provider.CallLog.Calls#DATE} of the data row it
+ * is associated with.
+ *
+ * <p>TYPE: TEXT
+ */
+ static final String TRANSCRIPT_ID = "rtt_transcript_id";
+
+ /**
+ * Transcript data, encoded as {@link RttTranscript} proto.
+ *
+ * <p>TYPE: BLOB
+ */
+ static final String TRANSCRIPT_DATA = "transcript_data";
+ }
+}
diff --git a/java/com/android/dialer/rtt/RttTranscriptDatabaseHelper.java b/java/com/android/dialer/rtt/RttTranscriptDatabaseHelper.java
new file mode 100644
index 000000000..934eedb5d
--- /dev/null
+++ b/java/com/android/dialer/rtt/RttTranscriptDatabaseHelper.java
@@ -0,0 +1,56 @@
+/*
+ * 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.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.SystemClock;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.rtt.RttTranscriptContract.RttTranscriptColumn;
+
+/** Database helper class for RTT transcript. */
+final class RttTranscriptDatabaseHelper extends SQLiteOpenHelper {
+
+ static final String TABLE = "rtt_transcript";
+
+ private static final String CREATE_TABLE_SQL =
+ "create table if not exists "
+ + TABLE
+ + " ("
+ + (RttTranscriptColumn.TRANSCRIPT_ID + " integer primary key, ")
+ + (RttTranscriptColumn.TRANSCRIPT_DATA + " blob not null")
+ + ");";
+
+ RttTranscriptDatabaseHelper(Context context) {
+ super(context, "rtt_transcript.db", null, 1);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ LogUtil.enterBlock("RttTranscriptDatabaseHelper.onCreate");
+ long startTime = SystemClock.elapsedRealtime();
+ db.execSQL(CREATE_TABLE_SQL);
+ LogUtil.i(
+ "RttTranscriptDatabaseHelper.onCreate",
+ "took: %dms",
+ SystemClock.elapsedRealtime() - startTime);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
+}
diff --git a/java/com/android/dialer/rtt/RttTranscriptUtil.java b/java/com/android/dialer/rtt/RttTranscriptUtil.java
new file mode 100644
index 000000000..e55d2ea55
--- /dev/null
+++ b/java/com/android/dialer/rtt/RttTranscriptUtil.java
@@ -0,0 +1,97 @@
+/*
+ * 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.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.support.annotation.WorkerThread;
+import com.android.dialer.common.Assert;
+import com.android.dialer.rtt.RttTranscriptContract.RttTranscriptColumn;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+/** Util class to save and load RTT transcript. */
+public final class RttTranscriptUtil {
+
+ private final RttTranscriptDatabaseHelper databaseHelper;
+
+ public RttTranscriptUtil(Context context) {
+ databaseHelper = new RttTranscriptDatabaseHelper(context);
+ }
+
+ /** @return true if there is RTT transcript available. */
+ @WorkerThread
+ public boolean checkRttTranscriptAvailability(String transcriptId) {
+ Assert.isWorkerThread();
+ try (Cursor cursor =
+ databaseHelper
+ .getReadableDatabase()
+ .query(
+ RttTranscriptDatabaseHelper.TABLE,
+ new String[] {RttTranscriptColumn.TRANSCRIPT_ID},
+ RttTranscriptColumn.TRANSCRIPT_ID + " = ?",
+ new String[] {transcriptId},
+ null,
+ null,
+ null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @WorkerThread
+ public RttTranscript getRttTranscript(String transcriptId) {
+ Assert.isWorkerThread();
+ try (Cursor cursor =
+ databaseHelper
+ .getReadableDatabase()
+ .query(
+ RttTranscriptDatabaseHelper.TABLE,
+ new String[] {RttTranscriptColumn.TRANSCRIPT_DATA},
+ RttTranscriptColumn.TRANSCRIPT_ID + " = ?",
+ new String[] {transcriptId},
+ null,
+ null,
+ null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ try {
+ return RttTranscript.parseFrom(cursor.getBlob(0));
+ } catch (InvalidProtocolBufferException e) {
+ throw new RuntimeException("Parse failed for RTT transcript", e);
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+
+ @WorkerThread
+ public void saveRttTranscript(RttTranscript rttTranscript) {
+ Assert.isWorkerThread();
+ ContentValues value = new ContentValues();
+ value.put(RttTranscriptColumn.TRANSCRIPT_ID, rttTranscript.getId());
+ value.put(RttTranscriptColumn.TRANSCRIPT_DATA, rttTranscript.toByteArray());
+ long id =
+ databaseHelper.getWritableDatabase().insert(RttTranscriptDatabaseHelper.TABLE, null, value);
+ if (id < 0) {
+ throw new RuntimeException("Failed to save RTT transcript");
+ }
+ }
+}
diff --git a/java/com/android/dialer/theme/res/values/colors.xml b/java/com/android/dialer/theme/res/values/colors.xml
index 6b98e208b..e80fc4b30 100644
--- a/java/com/android/dialer/theme/res/values/colors.xml
+++ b/java/com/android/dialer/theme/res/values/colors.xml
@@ -46,6 +46,8 @@
<!-- 38% opacity -->
<color name="dialer_secondary_text_color_hiden">#61000000</color>
+ <color name="dialer_link_color">#2A56C6</color>
+
<!-- Color of the theme of the Dialer app -->
<color name="dialtacts_theme_color">@color/dialer_theme_color</color>
diff --git a/java/com/android/incallui/RttCallPresenter.java b/java/com/android/incallui/RttCallPresenter.java
index 5e8390793..21e28cee4 100644
--- a/java/com/android/incallui/RttCallPresenter.java
+++ b/java/com/android/incallui/RttCallPresenter.java
@@ -63,28 +63,34 @@ public class RttCallPresenter implements RttCallScreenDelegate, InCallStateListe
LogUtil.enterBlock("RttCallPresenter.onRttCallScreenUiReady");
InCallPresenter.getInstance().addListener(this);
startListenOnRemoteMessage();
- DialerCall call = CallList.getInstance().getActiveCall();
+ DialerCall call = CallList.getInstance().getCallById(rttCallScreen.getCallId());
if (call != null) {
rttCallScreen.onRestoreRttChat(call.getRttTranscript());
}
}
@Override
+ public void onSaveRttTranscript() {
+ LogUtil.enterBlock("RttCallPresenter.onSaveRttTranscript");
+ DialerCall call = CallList.getInstance().getCallById(rttCallScreen.getCallId());
+ if (call != null) {
+ saveTranscript(call);
+ }
+ }
+
+ @Override
public void onRttCallScreenUiUnready() {
LogUtil.enterBlock("RttCallPresenter.onRttCallScreenUiUnready");
InCallPresenter.getInstance().removeListener(this);
stopListenOnRemoteMessage();
- DialerCall call = CallList.getInstance().getActiveCall();
- if (call != null) {
- saveTranscript(call);
- }
+ onSaveRttTranscript();
}
private void saveTranscript(DialerCall dialerCall) {
LogUtil.enterBlock("RttCallPresenter.saveTranscript");
RttTranscript.Builder builder = RttTranscript.newBuilder();
builder
- .setId(dialerCall.getNumber() + dialerCall.getCreationTimeMillis())
+ .setId(String.valueOf(dialerCall.getCreationTimeMillis()))
.setTimestamp(dialerCall.getCreationTimeMillis())
.setNumber(dialerCall.getNumber())
.addAllMessages(rttCallScreen.getRttTranscriptMessageList());
@@ -100,9 +106,9 @@ public class RttCallPresenter implements RttCallScreenDelegate, InCallStateListe
}
private void startListenOnRemoteMessage() {
- DialerCall call = CallList.getInstance().getActiveCall();
+ DialerCall call = CallList.getInstance().getCallById(rttCallScreen.getCallId());
if (call == null) {
- LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "call is not active yet");
+ LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "call does not exist");
return;
}
rttCall = call.getRttCall();
diff --git a/java/com/android/incallui/call/CallList.java b/java/com/android/incallui/call/CallList.java
index eccdceeca..04e02c45b 100644
--- a/java/com/android/incallui/call/CallList.java
+++ b/java/com/android/incallui/call/CallList.java
@@ -745,6 +745,7 @@ public class CallList implements DialerCallDelegate {
call.setState(DialerCall.State.IDLE);
updateCallInMap(call);
notifyGenericListeners();
+ call.onDestroy();
}
/**
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index 3372c0329..5d32f46ad 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -57,6 +57,8 @@ import com.android.dialer.callintent.CallIntentParser;
import com.android.dialer.callintent.CallSpecificAppData;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.duo.DuoComponent;
@@ -74,6 +76,7 @@ import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.preferredsim.PreferredAccountRecorder;
import com.android.dialer.rtt.RttTranscript;
+import com.android.dialer.rtt.RttTranscriptUtil;
import com.android.dialer.telecom.TelecomCallUtil;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.theme.R;
@@ -86,6 +89,9 @@ import com.android.incallui.videotech.duo.DuoVideoTech;
import com.android.incallui.videotech.empty.EmptyVideoTech;
import com.android.incallui.videotech.ims.ImsVideoTech;
import com.android.incallui.videotech.utils.VideoUtils;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -536,6 +542,28 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
return countryIso;
}
+ /**
+ * Called when call is disconnected and removed from {@link CallList}, UI may already be destroyed
+ * at this point. This is last chance to do something for the call.
+ */
+ public void onDestroy() {
+ LogUtil.enterBlock("DialerCall.onDestroy");
+ if (rttTranscript != null) {
+ RttTranscript rttTranscriptToSave = rttTranscript;
+ ListenableFuture<Void> future =
+ DialerExecutorComponent.get(context)
+ .backgroundExecutor()
+ .submit(
+ () -> {
+ new RttTranscriptUtil(context).saveRttTranscript(rttTranscriptToSave);
+ return null;
+ });
+ Futures.addCallback(future, new DefaultFutureCallback<>(), MoreExecutors.directExecutor());
+ // Sets to null so it won't be saved again when called multiple times.
+ rttTranscript = null;
+ }
+ }
+
private void updateIsVoiceMailNumber() {
if (getHandle() != null && PhoneAccount.SCHEME_VOICEMAIL.equals(getHandle().getScheme())) {
isVoicemailNumber = true;
diff --git a/java/com/android/incallui/rtt/impl/RttChatFragment.java b/java/com/android/incallui/rtt/impl/RttChatFragment.java
index 15baa8cfa..2d70b6b12 100644
--- a/java/com/android/incallui/rtt/impl/RttChatFragment.java
+++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java
@@ -462,6 +462,9 @@ public class RttChatFragment extends Fragment
} else {
hideWaitingForJoinBanner();
}
+ if (primaryCallState.state() == State.DISCONNECTED) {
+ rttCallScreenDelegate.onSaveRttTranscript();
+ }
}
private void showWaitingForJoinBanner() {
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
index 8c484a844..990c0759e 100644
--- a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
@@ -26,4 +26,6 @@ public interface RttCallScreenDelegate {
void onRttCallScreenUiUnready();
void onLocalMessage(String message);
+
+ void onSaveRttTranscript();
}