summaryrefslogtreecommitdiff
path: root/java/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android')
-rw-r--r--java/com/android/dialer/binary/aosp/AospDialerRootComponent.java2
-rw-r--r--java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java2
-rw-r--r--java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java2
-rw-r--r--java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java20
-rw-r--r--java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java20
-rw-r--r--java/com/android/dialer/calllogutils/CallLogEntryText.java20
-rw-r--r--java/com/android/dialer/calllogutils/NumberAttributesConverter.java26
-rw-r--r--java/com/android/dialer/common/res/values/strings.xml2
-rw-r--r--java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java8
-rw-r--r--java/com/android/dialer/logging/dialer_impression.proto20
-rw-r--r--java/com/android/dialer/main/MainActivityPeer.java2
-rw-r--r--java/com/android/dialer/main/impl/MainSearchController.java40
-rw-r--r--java/com/android/dialer/main/impl/NewMainActivityPeer.java3
-rw-r--r--java/com/android/dialer/main/impl/OldMainActivityPeer.java57
-rw-r--r--java/com/android/dialer/metrics/Metrics.java39
-rw-r--r--java/com/android/dialer/metrics/MetricsComponent.java41
-rw-r--r--java/com/android/dialer/metrics/StubMetrics.java36
-rw-r--r--java/com/android/dialer/metrics/StubMetricsInitializer.java30
-rw-r--r--java/com/android/dialer/metrics/StubMetricsModule.java31
-rw-r--r--java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java22
-rw-r--r--java/com/android/dialer/phonelookup/cp2/Cp2Projections.java45
-rw-r--r--java/com/android/dialer/phonelookup/phone_lookup_info.proto17
-rw-r--r--java/com/android/dialer/searchfragment/list/NewSearchFragment.java4
-rw-r--r--java/com/android/dialer/simulator/Simulator.java6
-rw-r--r--java/com/android/dialer/simulator/impl/RttChatBot.java139
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java3
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorConnection.java18
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorMainMenu.java7
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java3
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorRttCall.java138
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java52
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVideoCall.java6
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java27
-rw-r--r--java/com/android/incallui/InCallActivity.java104
-rw-r--r--java/com/android/incallui/ProximitySensor.java10
-rw-r--r--java/com/android/incallui/RttCallPresenter.java43
-rw-r--r--java/com/android/incallui/answer/bindings/AnswerBindings.java2
-rw-r--r--java/com/android/incallui/answer/impl/AnswerFragment.java10
-rw-r--r--java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java2
-rw-r--r--java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java2
-rw-r--r--java/com/android/incallui/answer/protocol/AnswerScreen.java2
-rw-r--r--java/com/android/incallui/call/DialerCall.java36
-rw-r--r--java/com/android/incallui/rtt/bindings/RttBindings.java28
-rw-r--r--java/com/android/incallui/rtt/impl/AndroidManifest.xml11
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatActivity.java41
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatAdapter.java76
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatFragment.java257
-rw-r--r--java/com/android/incallui/rtt/impl/RttChatMessage.java6
-rw-r--r--java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml5
-rw-r--r--java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml64
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/colors.xml3
-rw-r--r--java/com/android/incallui/rtt/impl/res/values/strings.xml3
-rw-r--r--java/com/android/incallui/rtt/protocol/AndroidManifest.xml (renamed from java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml)16
-rw-r--r--java/com/android/incallui/rtt/protocol/Constants.java24
-rw-r--r--java/com/android/incallui/rtt/protocol/RttCallScreen.java31
-rw-r--r--java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java29
-rw-r--r--java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java23
57 files changed, 1348 insertions, 368 deletions
diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
index 0f00a5d82..35f854010 100644
--- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
+++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
@@ -26,6 +26,7 @@ import com.android.dialer.enrichedcall.stub.StubEnrichedCallModule;
import com.android.dialer.feedback.stub.StubFeedbackModule;
import com.android.dialer.glidephotomanager.GlidePhotoManagerModule;
import com.android.dialer.inject.ContextModule;
+import com.android.dialer.metrics.StubMetricsModule;
import com.android.dialer.phonelookup.PhoneLookupModule;
import com.android.dialer.phonenumbergeoutil.impl.PhoneNumberGeoUtilModule;
import com.android.dialer.precall.impl.PreCallModule;
@@ -63,6 +64,7 @@ import javax.inject.Singleton;
StubDuoModule.class,
StubEnrichedCallModule.class,
StubNewBubbleModule.class,
+ StubMetricsModule.class,
StubFeedbackModule.class,
StubMapsModule.class,
StubSimSuggestionModule.class,
diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
index 3e7db9d8a..cd95c3ee7 100644
--- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
+++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
@@ -27,6 +27,7 @@ import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.feedback.FeedbackComponent;
import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent;
import com.android.dialer.main.MainComponent;
+import com.android.dialer.metrics.MetricsComponent;
import com.android.dialer.phonelookup.PhoneLookupComponent;
import com.android.dialer.phonenumbergeoutil.PhoneNumberGeoUtilComponent;
import com.android.dialer.precall.PreCallComponent;
@@ -59,6 +60,7 @@ public interface BaseDialerRootComponent
GlidePhotoManagerComponent.HasComponent,
MainComponent.HasComponent,
MapsComponent.HasComponent,
+ MetricsComponent.HasComponent,
NewBubbleComponent.HasComponent,
PhoneLookupComponent.HasComponent,
PhoneNumberGeoUtilComponent.HasComponent,
diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
index d4520f33e..497d97724 100644
--- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
+++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
@@ -26,6 +26,7 @@ import com.android.dialer.enrichedcall.stub.StubEnrichedCallModule;
import com.android.dialer.feedback.stub.StubFeedbackModule;
import com.android.dialer.glidephotomanager.GlidePhotoManagerModule;
import com.android.dialer.inject.ContextModule;
+import com.android.dialer.metrics.StubMetricsModule;
import com.android.dialer.phonelookup.PhoneLookupModule;
import com.android.dialer.phonenumbergeoutil.impl.PhoneNumberGeoUtilModule;
import com.android.dialer.precall.impl.PreCallModule;
@@ -67,6 +68,7 @@ import javax.inject.Singleton;
StubDuoModule.class,
StubEnrichedCallModule.class,
StubFeedbackModule.class,
+ StubMetricsModule.class,
StubNewBubbleModule.class,
StubSimSuggestionModule.class,
StubSpamModule.class,
diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
index 52570c05e..8dec43759 100644
--- a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
@@ -28,18 +28,17 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.dialer.DialerPhoneNumber;
-import com.android.dialer.NumberAttributes;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.CallLogMutations;
import com.android.dialer.calllog.datasources.util.RowCombiner;
+import com.android.dialer.calllogutils.NumberAttributesConverter;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
import com.android.dialer.common.concurrent.Annotations.LightweightExecutor;
import com.android.dialer.phonelookup.PhoneLookup;
import com.android.dialer.phonelookup.PhoneLookupInfo;
-import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
import com.google.common.collect.ImmutableMap;
@@ -573,23 +572,8 @@ public final class PhoneLookupDataSource
}
private void updateContentValues(ContentValues contentValues, PhoneLookupInfo phoneLookupInfo) {
- PhoneLookupInfoConsolidator phoneLookupInfoConsolidator =
- new PhoneLookupInfoConsolidator(phoneLookupInfo);
contentValues.put(
AnnotatedCallLog.NUMBER_ATTRIBUTES,
- NumberAttributes.newBuilder()
- .setName(phoneLookupInfoConsolidator.getName())
- .setPhotoUri(phoneLookupInfoConsolidator.getPhotoUri())
- .setPhotoId(phoneLookupInfoConsolidator.getPhotoId())
- .setLookupUri(phoneLookupInfoConsolidator.getLookupUri())
- .setNumberTypeLabel(phoneLookupInfoConsolidator.getNumberLabel())
- .setIsBusiness(phoneLookupInfoConsolidator.isBusiness())
- .setIsVoicemail(phoneLookupInfoConsolidator.isVoicemail())
- .setIsBlocked(phoneLookupInfoConsolidator.isBlocked())
- .setIsSpam(phoneLookupInfoConsolidator.isSpam())
- .setCanReportAsInvalidNumber(phoneLookupInfoConsolidator.canReportAsInvalidNumber())
- .setIsCp2InfoIncomplete(phoneLookupInfoConsolidator.isCp2LocalInfoIncomplete())
- .build()
- .toByteArray());
+ NumberAttributesConverter.fromPhoneLookupInfo(phoneLookupInfo).build().toByteArray());
}
}
diff --git a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java
index 5083a95c5..69c431953 100644
--- a/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java
+++ b/java/com/android/dialer/calllog/ui/RealtimeRowProcessor.java
@@ -23,8 +23,8 @@ import android.support.annotation.MainThread;
import android.support.annotation.VisibleForTesting;
import android.util.ArrayMap;
import com.android.dialer.DialerPhoneNumber;
-import com.android.dialer.NumberAttributes;
import com.android.dialer.calllog.model.CoalescedRow;
+import com.android.dialer.calllogutils.NumberAttributesConverter;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
@@ -33,7 +33,6 @@ import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.inject.ApplicationContext;
import com.android.dialer.phonelookup.PhoneLookup;
import com.android.dialer.phonelookup.PhoneLookupInfo;
-import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract;
import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
import com.google.common.collect.ImmutableMap;
@@ -198,23 +197,8 @@ public final class RealtimeRowProcessor {
private CoalescedRow applyPhoneLookupInfoToRow(
PhoneLookupInfo phoneLookupInfo, CoalescedRow row) {
- PhoneLookupInfoConsolidator phoneLookupInfoConsolidator =
- new PhoneLookupInfoConsolidator(phoneLookupInfo);
return row.toBuilder()
- .setNumberAttributes(
- // TODO(zachh): Put this in a common location.
- NumberAttributes.newBuilder()
- .setName(phoneLookupInfoConsolidator.getName())
- .setPhotoUri(phoneLookupInfoConsolidator.getPhotoUri())
- .setPhotoId(phoneLookupInfoConsolidator.getPhotoId())
- .setLookupUri(phoneLookupInfoConsolidator.getLookupUri())
- .setNumberTypeLabel(phoneLookupInfoConsolidator.getNumberLabel())
- .setIsBusiness(phoneLookupInfoConsolidator.isBusiness())
- .setIsVoicemail(phoneLookupInfoConsolidator.isVoicemail())
- .setIsBlocked(phoneLookupInfoConsolidator.isBlocked())
- .setIsSpam(phoneLookupInfoConsolidator.isSpam())
- .setCanReportAsInvalidNumber(phoneLookupInfoConsolidator.canReportAsInvalidNumber())
- .build())
+ .setNumberAttributes(NumberAttributesConverter.fromPhoneLookupInfo(phoneLookupInfo).build())
.build();
}
}
diff --git a/java/com/android/dialer/calllogutils/CallLogEntryText.java b/java/com/android/dialer/calllogutils/CallLogEntryText.java
index 737b1d30f..ab851cbbd 100644
--- a/java/com/android/dialer/calllogutils/CallLogEntryText.java
+++ b/java/com/android/dialer/calllogutils/CallLogEntryText.java
@@ -70,7 +70,8 @@ public final class CallLogEntryText {
* <ul>
* <li>For numbers that are not spam or blocked: (Duo video, )?$Label|$Location • Date
* <li>For blocked non-spam numbers: Blocked • (Duo video, )?$Label|$Location • Date
- * <li>For spam numbers: Spam • (Duo video, )?$Label • Date
+ * <li>For spam but not blocked numbers: Spam • (Duo video, )?$Label • Date
+ * <li>For blocked spam numbers: Blocked • Spam • (Duo video, )?$Label • Date
* </ul>
*
* <p>Examples:
@@ -84,6 +85,7 @@ public final class CallLogEntryText {
* <li>Blocked • Brooklyn, NJ • 10 min ago
* <li>Spam • Mobile • Now
* <li>Spam • Now
+ * <li>Blocked • Spam • Mobile • Now
* <li>Brooklyn, NJ • Jan 15
* </ul>
*
@@ -93,11 +95,11 @@ public final class CallLogEntryText {
Context context, Clock clock, CoalescedRow row) {
List<CharSequence> components = new ArrayList<>();
- // If a number is both spam and blocked, only show "Spam".
+ if (row.numberAttributes().getIsBlocked()) {
+ components.add(context.getText(R.string.new_call_log_secondary_blocked));
+ }
if (row.numberAttributes().getIsSpam()) {
components.add(context.getText(R.string.new_call_log_secondary_spam));
- } else if (row.numberAttributes().getIsBlocked()) {
- components.add(context.getText(R.string.new_call_log_secondary_blocked));
}
components.add(getNumberTypeLabel(context, row));
@@ -121,8 +123,10 @@ public final class CallLogEntryText {
* (Duo video, )?$Label|$Location [• NumberIfNoName]?
* For blocked non-spam numbers:
* Blocked • (Duo video, )?$Label|$Location [• NumberIfNoName]?
- * For spam numbers:
+ * For spam but not blocked numbers:
* Spam • (Duo video, )?$Label [• NumberIfNoName]?
+ * For blocked spam numbers:
+ * Blocked • Spam • (Duo video, )?$Label [• NumberIfNoName]?
*
* The number is shown at the end if there is no name for the entry. (It is shown in primary
* text otherwise.)
@@ -139,11 +143,11 @@ public final class CallLogEntryText {
*/
List<CharSequence> components = new ArrayList<>();
- // If a number is both spam and blocked, only show "Spam".
+ if (row.numberAttributes().getIsBlocked()) {
+ components.add(context.getText(R.string.new_call_log_secondary_blocked));
+ }
if (row.numberAttributes().getIsSpam()) {
components.add(context.getText(R.string.new_call_log_secondary_spam));
- } else if (row.numberAttributes().getIsBlocked()) {
- components.add(context.getText(R.string.new_call_log_secondary_blocked));
}
components.add(getNumberTypeLabel(context, row));
diff --git a/java/com/android/dialer/calllogutils/NumberAttributesConverter.java b/java/com/android/dialer/calllogutils/NumberAttributesConverter.java
index bed1edd06..efd1d72c2 100644
--- a/java/com/android/dialer/calllogutils/NumberAttributesConverter.java
+++ b/java/com/android/dialer/calllogutils/NumberAttributesConverter.java
@@ -16,13 +16,16 @@
package com.android.dialer.calllogutils;
+import android.text.TextUtils;
import com.android.dialer.NumberAttributes;
import com.android.dialer.glidephotomanager.PhotoInfo;
+import com.android.dialer.phonelookup.PhoneLookupInfo;
+import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator;
/** Converts {@link NumberAttributes} to {@link PhotoInfo} */
public final class NumberAttributesConverter {
- /** Converts to {@link PhotoInfo.Builder} */
+ /** Converts {@link NumberAttributes} to {@link PhotoInfo.Builder} */
public static PhotoInfo.Builder toPhotoInfoBuilder(NumberAttributes numberAttributes) {
return PhotoInfo.builder()
.setName(numberAttributes.getName())
@@ -34,4 +37,25 @@ public final class NumberAttributesConverter {
.setIsVoicemail(numberAttributes.getIsVoicemail())
.setIsBlocked(numberAttributes.getIsBlocked());
}
+
+ /** Converts {@link PhoneLookupInfo} to {@link NumberAttributes.Builder} */
+ public static NumberAttributes.Builder fromPhoneLookupInfo(PhoneLookupInfo phoneLookupInfo) {
+ PhoneLookupInfoConsolidator phoneLookupInfoConsolidator =
+ new PhoneLookupInfoConsolidator(phoneLookupInfo);
+ return NumberAttributes.newBuilder()
+ .setName(phoneLookupInfoConsolidator.getName())
+ .setPhotoUri(
+ !TextUtils.isEmpty(phoneLookupInfoConsolidator.getPhotoThumbnailUri())
+ ? phoneLookupInfoConsolidator.getPhotoThumbnailUri()
+ : phoneLookupInfoConsolidator.getPhotoUri())
+ .setPhotoId(phoneLookupInfoConsolidator.getPhotoId())
+ .setLookupUri(phoneLookupInfoConsolidator.getLookupUri())
+ .setNumberTypeLabel(phoneLookupInfoConsolidator.getNumberLabel())
+ .setIsBusiness(phoneLookupInfoConsolidator.isBusiness())
+ .setIsVoicemail(phoneLookupInfoConsolidator.isVoicemail())
+ .setIsBlocked(phoneLookupInfoConsolidator.isBlocked())
+ .setIsSpam(phoneLookupInfoConsolidator.isSpam())
+ .setCanReportAsInvalidNumber(phoneLookupInfoConsolidator.canReportAsInvalidNumber())
+ .setIsCp2InfoIncomplete(phoneLookupInfoConsolidator.isCp2LocalInfoIncomplete());
+ }
}
diff --git a/java/com/android/dialer/common/res/values/strings.xml b/java/com/android/dialer/common/res/values/strings.xml
index 770f42f37..53a2b56d7 100644
--- a/java/com/android/dialer/common/res/values/strings.xml
+++ b/java/com/android/dialer/common/res/values/strings.xml
@@ -17,4 +17,6 @@
<resources>
<string name="network_name_wifi">Wifi</string>
<string name="network_name_mobile">Mobile</string>
+ <!-- Content description for the overflow menu button. [CHAR LIMIT=NONE] -->
+ <string name="content_description_overflow">More options</string>
</resources>
diff --git a/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java b/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java
index c6d92057d..10c4dfb4c 100644
--- a/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java
+++ b/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java
@@ -68,13 +68,13 @@ public class GlidePhotoManagerImpl implements GlidePhotoManager {
// Warning: Glide ignores extra attributes on BitmapDrawable such as tint and draw the bitmap
// directly so be sure not to set tint in the XML of any drawable referenced below.
- // The spam status takes precedence over whether the number is blocked.
- if (photoInfo.isSpam()) {
- return requestManager.load(R.drawable.ic_report_red_48dp);
- }
+ // Whether the number is blocked takes precedence over the spam status.
if (photoInfo.isBlocked()) {
return requestManager.load(R.drawable.ic_block_grey_48dp);
}
+ if (photoInfo.isSpam()) {
+ return requestManager.load(R.drawable.ic_report_red_48dp);
+ }
if (!TextUtils.isEmpty(photoInfo.photoUri())) {
return requestManager.load(parseUri(photoInfo.photoUri()));
}
diff --git a/java/com/android/dialer/logging/dialer_impression.proto b/java/com/android/dialer/logging/dialer_impression.proto
index f839b1399..635d8fd02 100644
--- a/java/com/android/dialer/logging/dialer_impression.proto
+++ b/java/com/android/dialer/logging/dialer_impression.proto
@@ -12,7 +12,7 @@ message DialerImpression {
// Event enums to be used for Impression Logging in Dialer.
// It's perfectly acceptable for this enum to be large
// Values should be from 1000 to 100000.
- // Next Tag: 1327
+ // Next Tag: 1341
enum Type {
UNKNOWN_AOSP_EVENT_TYPE = 1000;
@@ -657,5 +657,23 @@ message DialerImpression {
DUO_CALL_LOG_SET_UP_INSTALL_SHOWN = 1324;
DUO_CALL_LOG_SET_UP_ACTIVATE_SHOWN = 1325;
DUO_CALL_LOG_INVITE_SHOWN = 1326;
+
+ // NUI bottom navigation bar
+ NUI_SWITCH_TAB_TO_FAVORITE = 1327;
+ NUI_SWITCH_TAB_TO_CALL_LOG = 1328;
+ NUI_SWITCH_TAB_TO_CONTACTS = 1329;
+ NUI_SWITCH_TAB_TO_VOICEMAIL = 1330;
+ // NUI search
+ NUI_TOUCH_DIALPAD_SEARCH_LIST_TO_CLOSE_SEARCH_AND_DIALPAD = 1331;
+ NUI_TOUCH_DIALPAD_SEARCH_LIST_TO_HIDE_DIALPAD = 1332;
+ NUI_TOUCH_SEARCH_LIST_TO_CLOSE_SEARCH = 1333;
+ NUI_TOUCH_SEARCH_LIST_TO_HIDE_KEYBOARD = 1334;
+ NUI_PRESS_BACK_BUTTON_TO_CLOSE_SEARCH = 1335;
+ NUI_PRESS_BACK_BUTTON_TO_CLOSE_SEARCH_AND_DIALPAD = 1336;
+ NUI_PRESS_BACK_BUTTON_TO_HIDE_DIALPAD = 1337;
+ NUI_CLICK_SEARCH_BAR = 1338;
+ NUI_CLICK_SEARCH_BAR_VOICE_BUTTON = 1339;
+ // NUI FAB
+ NUI_CLICK_FAB_TO_OPEN_DIALPAD = 1340;
}
}
diff --git a/java/com/android/dialer/main/MainActivityPeer.java b/java/com/android/dialer/main/MainActivityPeer.java
index 6457b607b..c1a328a65 100644
--- a/java/com/android/dialer/main/MainActivityPeer.java
+++ b/java/com/android/dialer/main/MainActivityPeer.java
@@ -28,6 +28,8 @@ public interface MainActivityPeer {
void onActivityStop();
+ void onActivityDestroyed();
+
void onNewIntent(Intent intent);
void onActivityResult(int requestCode, int resultCode, Intent data);
diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java
index 7098f8844..9b734f40c 100644
--- a/java/com/android/dialer/main/impl/MainSearchController.java
+++ b/java/com/android/dialer/main/impl/MainSearchController.java
@@ -40,6 +40,7 @@ import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.dialpadview.DialpadFragment;
import com.android.dialer.dialpadview.DialpadFragment.DialpadListener;
import com.android.dialer.dialpadview.DialpadFragment.OnDialpadQueryChangedListener;
+import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.logging.ScreenEvent;
import com.android.dialer.main.impl.bottomnav.BottomNavBar;
@@ -204,14 +205,23 @@ public class MainSearchController implements SearchBarListener {
public void onSearchListTouch() {
if (isDialpadVisible()) {
if (TextUtils.isEmpty(getDialpadFragment().getQuery())) {
+ Logger.get(mainActivity)
+ .logImpression(
+ DialerImpression.Type.NUI_TOUCH_DIALPAD_SEARCH_LIST_TO_CLOSE_SEARCH_AND_DIALPAD);
closeSearch(true);
} else {
+ Logger.get(mainActivity)
+ .logImpression(DialerImpression.Type.NUI_TOUCH_DIALPAD_SEARCH_LIST_TO_HIDE_DIALPAD);
hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false);
}
} else if (isSearchVisible()) {
if (TextUtils.isEmpty(toolbar.getQuery())) {
+ Logger.get(mainActivity)
+ .logImpression(DialerImpression.Type.NUI_TOUCH_SEARCH_LIST_TO_CLOSE_SEARCH);
closeSearch(true);
} else {
+ Logger.get(mainActivity)
+ .logImpression(DialerImpression.Type.NUI_TOUCH_SEARCH_LIST_TO_HIDE_KEYBOARD);
toolbar.hideKeyboard();
}
}
@@ -225,10 +235,17 @@ public class MainSearchController implements SearchBarListener {
public boolean onBackPressed() {
if (isDialpadVisible() && !TextUtils.isEmpty(getDialpadFragment().getQuery())) {
LogUtil.i("MainSearchController#onBackPressed", "Dialpad visible with query");
+ Logger.get(mainActivity)
+ .logImpression(DialerImpression.Type.NUI_PRESS_BACK_BUTTON_TO_HIDE_DIALPAD);
hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false);
return true;
} else if (isSearchVisible()) {
LogUtil.i("MainSearchController#onBackPressed", "Search is visible");
+ Logger.get(mainActivity)
+ .logImpression(
+ isDialpadVisible()
+ ? DialerImpression.Type.NUI_PRESS_BACK_BUTTON_TO_CLOSE_SEARCH_AND_DIALPAD
+ : DialerImpression.Type.NUI_PRESS_BACK_BUTTON_TO_CLOSE_SEARCH);
closeSearch(true);
return true;
} else {
@@ -252,16 +269,13 @@ public class MainSearchController implements SearchBarListener {
mainActivity.getFragmentManager().beginTransaction().remove(getSearchFragment()).commit();
// Clear the dialpad so the phone number isn't persisted between search sessions.
- getDialpadFragment().clearDialpad();
+ if (getDialpadFragment() != null) {
+ getDialpadFragment().clearDialpad();
+ }
}
- /**
- * Returns {@link DialpadFragment}.
- *
- * <p>Unless this method is being called for the first time in {@link #openSearch(Optional)} or
- * {@link #showDialpad(boolean)}, it should never return null.
- */
- private DialpadFragment getDialpadFragment() {
+ @Nullable
+ protected DialpadFragment getDialpadFragment() {
return (DialpadFragment)
mainActivity.getFragmentManager().findFragmentByTag(DIALPAD_FRAGMENT_TAG);
}
@@ -297,6 +311,7 @@ public class MainSearchController implements SearchBarListener {
*/
@Override
public void onSearchBarClicked() {
+ Logger.get(mainActivity).logImpression(DialerImpression.Type.NUI_CLICK_SEARCH_BAR);
openSearch(Optional.absent());
}
@@ -316,14 +331,6 @@ public class MainSearchController implements SearchBarListener {
transaction.show(getSearchFragment());
}
- // Add the dialpad fragment but keep it hidden
- if (getDialpadFragment() == null) {
- DialpadFragment dialpadFragment = new DialpadFragment();
- transaction
- .add(R.id.dialpad_fragment_container, dialpadFragment, DIALPAD_FRAGMENT_TAG)
- .hide(dialpadFragment);
- }
-
transaction.commit();
}
@@ -350,6 +357,7 @@ public class MainSearchController implements SearchBarListener {
@Override
public void onVoiceButtonClicked(VoiceSearchResultCallback voiceSearchResultCallback) {
+ Logger.get(mainActivity).logImpression(DialerImpression.Type.NUI_CLICK_SEARCH_BAR_VOICE_BUTTON);
try {
Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mainActivity.startActivityForResult(voiceIntent, ActivityRequestCodes.DIALTACTS_VOICE_SEARCH);
diff --git a/java/com/android/dialer/main/impl/NewMainActivityPeer.java b/java/com/android/dialer/main/impl/NewMainActivityPeer.java
index 0a85667a1..ed67df936 100644
--- a/java/com/android/dialer/main/impl/NewMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/NewMainActivityPeer.java
@@ -60,6 +60,9 @@ public class NewMainActivityPeer implements MainActivityPeer {
public void onActivityStop() {}
@Override
+ public void onActivityDestroyed() {}
+
+ @Override
public void onNewIntent(Intent intent) {}
@Override
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index c46e61bd0..07c7185ae 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -66,6 +66,8 @@ import com.android.dialer.dialpadview.DialpadFragment.DialpadListener;
import com.android.dialer.dialpadview.DialpadFragment.LastOutgoingCallCallback;
import com.android.dialer.dialpadview.DialpadFragment.OnDialpadQueryChangedListener;
import com.android.dialer.interactions.PhoneNumberInteraction;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
import com.android.dialer.main.MainActivityPeer;
import com.android.dialer.main.impl.bottomnav.BottomNavBar;
import com.android.dialer.main.impl.bottomnav.BottomNavBar.OnBottomNavTabSelectedListener;
@@ -154,6 +156,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onActivityCreate(Bundle savedInstanceState) {
+ LogUtil.enterBlock("OldMainActivityPeer.onActivityCreate");
mainActivity.setContentView(R.layout.main_activity);
initUiListeners();
initLayout(savedInstanceState);
@@ -173,14 +176,19 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
snackbarContainer = mainActivity.findViewById(R.id.coordinator_layout);
FloatingActionButton fab = mainActivity.findViewById(R.id.fab);
- fab.setOnClickListener(v -> searchController.showDialpad(true));
+ fab.setOnClickListener(
+ v -> {
+ Logger.get(mainActivity)
+ .logImpression(DialerImpression.Type.NUI_CLICK_FAB_TO_OPEN_DIALPAD);
+ searchController.showDialpad(true);
+ });
MainToolbar toolbar = mainActivity.findViewById(R.id.toolbar);
mainActivity.setSupportActionBar(mainActivity.findViewById(R.id.toolbar));
bottomNav = mainActivity.findViewById(R.id.bottom_nav_bar);
MainBottomNavBarBottomNavTabListener bottomNavTabListener =
- new MainBottomNavBarBottomNavTabListener(mainActivity.getFragmentManager());
+ new MainBottomNavBarBottomNavTabListener(mainActivity, mainActivity.getFragmentManager());
bottomNav.addOnTabSelectedListener(bottomNavTabListener);
callLogFragmentListener =
@@ -191,7 +199,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
searchController = getNewMainSearchController(bottomNav, fab, toolbar);
toolbar.setSearchBarListener(searchController);
- onDialpadQueryChangedListener = new MainOnDialpadQueryChangedListener(searchController);
+ onDialpadQueryChangedListener = getNewOnDialpadQueryChangedListener(searchController);
dialpadListener =
new MainDialpadListener(mainActivity, searchController, getLastOutgoingCallListener);
searchFragmentListener = new MainSearchFragmentListener(searchController);
@@ -222,6 +230,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onNewIntent(Intent intent) {
+ LogUtil.enterBlock("OldMainActivityPeer.onNewIntent");
showTabOnIntent(intent);
}
@@ -285,6 +294,9 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
mainActivity.getSystemService(KeyguardManager.class).isKeyguardLocked());
}
+ @Override
+ public void onActivityDestroyed() {}
+
private void showPostCallPrompt() {
if (TelecomUtil.isInManagedCall(mainActivity)) {
// No prompt to show if the user is in a call
@@ -309,10 +321,15 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ LogUtil.i(
+ "OldMainActivityPeer.onActivityResult",
+ "requestCode:%d, resultCode:%d",
+ requestCode,
+ resultCode);
if (requestCode == ActivityRequestCodes.DIALTACTS_VOICE_SEARCH) {
searchController.onVoiceResults(resultCode, data);
} else {
- LogUtil.e("MainActivity.onActivityResult", "Unknown request code: " + requestCode);
+ LogUtil.e("OldMainActivityPeer.onActivityResult", "Unknown request code: " + requestCode);
}
}
@@ -350,6 +367,8 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
return (T) onPhoneNumberPickerActionListener;
} else if (callbackInterface.isInstance(oldSpeedDialFragmentHost)) {
return (T) oldSpeedDialFragmentHost;
+ } else if (callbackInterface.isInstance(searchController)) {
+ return (T) searchController;
} else {
return null;
}
@@ -360,6 +379,11 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
return new MainSearchController(mainActivity, bottomNavBar, fab, mainToolbar);
}
+ public MainOnDialpadQueryChangedListener getNewOnDialpadQueryChangedListener(
+ MainSearchController mainSearchController) {
+ return new MainOnDialpadQueryChangedListener(mainSearchController);
+ }
+
/** @see OnContactSelectedListener */
private static final class MainOnContactSelectedListener implements OnContactSelectedListener {
@@ -378,12 +402,12 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
}
/** @see OnDialpadQueryChangedListener */
- private static final class MainOnDialpadQueryChangedListener
+ protected static class MainOnDialpadQueryChangedListener
implements OnDialpadQueryChangedListener {
private final MainSearchController searchController;
- MainOnDialpadQueryChangedListener(MainSearchController searchController) {
+ protected MainOnDialpadQueryChangedListener(MainSearchController searchController) {
this.searchController = searchController;
}
@@ -794,13 +818,20 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
private static final String VOICEMAIL_TAG = "voicemail";
private final FragmentManager fragmentManager;
+ private final Context context;
+ @TabIndex private int selectedTab = -1;
- private MainBottomNavBarBottomNavTabListener(FragmentManager fragmentManager) {
+ private MainBottomNavBarBottomNavTabListener(Context context, FragmentManager fragmentManager) {
this.fragmentManager = fragmentManager;
+ this.context = context;
}
@Override
public void onSpeedDialSelected() {
+ if (selectedTab != TabIndex.SPEED_DIAL) {
+ Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_FAVORITE);
+ selectedTab = TabIndex.SPEED_DIAL;
+ }
hideAllFragments();
Fragment fragment = fragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
if (fragment == null) {
@@ -815,6 +846,10 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onCallLogSelected() {
+ if (selectedTab != TabIndex.CALL_LOG) {
+ Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_CALL_LOG);
+ selectedTab = TabIndex.CALL_LOG;
+ }
hideAllFragments();
CallLogFragment fragment = (CallLogFragment) fragmentManager.findFragmentByTag(CALL_LOG_TAG);
if (fragment == null) {
@@ -829,6 +864,10 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onContactsSelected() {
+ if (selectedTab != TabIndex.CONTACTS) {
+ Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_CONTACTS);
+ selectedTab = TabIndex.CONTACTS;
+ }
hideAllFragments();
ContactsFragment fragment =
(ContactsFragment) fragmentManager.findFragmentByTag(CONTACTS_TAG);
@@ -847,6 +886,10 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onVoicemailSelected() {
+ if (selectedTab != TabIndex.VOICEMAIL) {
+ Logger.get(context).logImpression(DialerImpression.Type.NUI_SWITCH_TAB_TO_VOICEMAIL);
+ selectedTab = TabIndex.VOICEMAIL;
+ }
hideAllFragments();
VisualVoicemailCallLogFragment fragment =
(VisualVoicemailCallLogFragment) fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
diff --git a/java/com/android/dialer/metrics/Metrics.java b/java/com/android/dialer/metrics/Metrics.java
new file mode 100644
index 000000000..3922a8cfa
--- /dev/null
+++ b/java/com/android/dialer/metrics/Metrics.java
@@ -0,0 +1,39 @@
+/*
+ * 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.metrics;
+
+import android.app.Application;
+import android.content.Context;
+
+/** Logs metrics. */
+public interface Metrics {
+
+ /** Start a timer. */
+ void startTimer(Context context, String timerEventName);
+
+ /** Stop a timer. */
+ void stopTimer(String timerEventName);
+
+ /** Record memory. */
+ void recordMemory(String memoryEventName);
+
+ /** Initiazer for metrics. */
+ interface Initializer {
+ /** Initialize metrics for the application . */
+ void initialize(Application application);
+ }
+}
diff --git a/java/com/android/dialer/metrics/MetricsComponent.java b/java/com/android/dialer/metrics/MetricsComponent.java
new file mode 100644
index 000000000..f37129791
--- /dev/null
+++ b/java/com/android/dialer/metrics/MetricsComponent.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.dialer.metrics;
+
+import android.content.Context;
+import com.android.dialer.inject.HasRootComponent;
+import dagger.Subcomponent;
+
+/** Component for metrics. */
+@Subcomponent
+public abstract class MetricsComponent {
+
+ public abstract Metrics metrics();
+
+ public abstract Metrics.Initializer metricsInitializer();
+
+ public static MetricsComponent get(Context context) {
+ return ((MetricsComponent.HasComponent)
+ ((HasRootComponent) context.getApplicationContext()).component())
+ .metricsComponent();
+ }
+
+ /** Used to refer to the root application component. */
+ public interface HasComponent {
+ MetricsComponent metricsComponent();
+ }
+}
diff --git a/java/com/android/dialer/metrics/StubMetrics.java b/java/com/android/dialer/metrics/StubMetrics.java
new file mode 100644
index 000000000..114eb4308
--- /dev/null
+++ b/java/com/android/dialer/metrics/StubMetrics.java
@@ -0,0 +1,36 @@
+/*
+ * 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.metrics;
+
+import android.content.Context;
+import javax.inject.Inject;
+
+/** Stub {@link Metrics}. */
+public final class StubMetrics implements Metrics {
+
+ @Inject
+ StubMetrics() {}
+
+ @Override
+ public void startTimer(Context context, String timerEventName) {}
+
+ @Override
+ public void stopTimer(String timerEventName) {}
+
+ @Override
+ public void recordMemory(String memoryEventName) {}
+}
diff --git a/java/com/android/dialer/metrics/StubMetricsInitializer.java b/java/com/android/dialer/metrics/StubMetricsInitializer.java
new file mode 100644
index 000000000..cea408737
--- /dev/null
+++ b/java/com/android/dialer/metrics/StubMetricsInitializer.java
@@ -0,0 +1,30 @@
+/*
+ * 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.metrics;
+
+import android.app.Application;
+import javax.inject.Inject;
+
+/** Stub for {@link Metrics.Initializer}. */
+public class StubMetricsInitializer implements Metrics.Initializer {
+
+ @Inject
+ StubMetricsInitializer() {}
+
+ @Override
+ public void initialize(Application application) {}
+}
diff --git a/java/com/android/dialer/metrics/StubMetricsModule.java b/java/com/android/dialer/metrics/StubMetricsModule.java
new file mode 100644
index 000000000..a2d9ebfe2
--- /dev/null
+++ b/java/com/android/dialer/metrics/StubMetricsModule.java
@@ -0,0 +1,31 @@
+/*
+ * 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.metrics;
+
+import dagger.Binds;
+import dagger.Module;
+
+/** Binds stub {@link Metrics}. */
+@Module
+public interface StubMetricsModule {
+
+ @Binds
+ Metrics bindMetrics(StubMetrics stub);
+
+ @Binds
+ Metrics.Initializer bindMetricsInitializer(StubMetricsInitializer stub);
+}
diff --git a/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java b/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java
index ce4030d70..9c5411081 100644
--- a/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java
+++ b/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java
@@ -108,6 +108,28 @@ public final class PhoneLookupInfoConsolidator {
/**
* The {@link PhoneLookupInfo} passed to the constructor is associated with a number. This method
+ * returns the photo thumbnail URI associated with that number.
+ *
+ * <p>If no photo thumbnail URI can be obtained from the {@link PhoneLookupInfo}, an empty string
+ * will be returned.
+ */
+ public String getPhotoThumbnailUri() {
+ switch (nameSource) {
+ case NameSource.CP2_LOCAL:
+ return Assert.isNotNull(firstCp2LocalContact).getPhotoThumbnailUri();
+ case NameSource.CP2_REMOTE:
+ return Assert.isNotNull(firstCp2RemoteContact).getPhotoThumbnailUri();
+ case NameSource.PEOPLE_API:
+ case NameSource.NONE:
+ return "";
+ default:
+ throw Assert.createUnsupportedOperationFailException(
+ String.format("Unsupported name source: %s", nameSource));
+ }
+ }
+
+ /**
+ * The {@link PhoneLookupInfo} passed to the constructor is associated with a number. This method
* returns the photo URI associated with that number.
*
* <p>If no photo URI can be obtained from the {@link PhoneLookupInfo}, an empty string will be
diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java b/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java
index e3929990e..5a211eddc 100644
--- a/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java
+++ b/java/com/android/dialer/phonelookup/cp2/Cp2Projections.java
@@ -35,12 +35,13 @@ final class Cp2Projections {
new String[] {
Phone.DISPLAY_NAME_PRIMARY, // 0
Phone.PHOTO_THUMBNAIL_URI, // 1
- Phone.PHOTO_ID, // 2
- Phone.TYPE, // 3
- Phone.LABEL, // 4
- Phone.NORMALIZED_NUMBER, // 5
- Phone.CONTACT_ID, // 6
- Phone.LOOKUP_KEY // 7
+ Phone.PHOTO_URI, // 2
+ Phone.PHOTO_ID, // 3
+ Phone.TYPE, // 4
+ Phone.LABEL, // 5
+ Phone.NORMALIZED_NUMBER, // 6
+ Phone.CONTACT_ID, // 7
+ Phone.LOOKUP_KEY // 8
};
// Projection for performing lookups using the PHONE_LOOKUP table
@@ -48,23 +49,25 @@ final class Cp2Projections {
new String[] {
PhoneLookup.DISPLAY_NAME_PRIMARY, // 0
PhoneLookup.PHOTO_THUMBNAIL_URI, // 1
- PhoneLookup.PHOTO_ID, // 2
- PhoneLookup.TYPE, // 3
- PhoneLookup.LABEL, // 4
- PhoneLookup.NORMALIZED_NUMBER, // 5
- PhoneLookup.CONTACT_ID, // 6
- PhoneLookup.LOOKUP_KEY // 7
+ PhoneLookup.PHOTO_URI, // 2
+ PhoneLookup.PHOTO_ID, // 3
+ PhoneLookup.TYPE, // 4
+ PhoneLookup.LABEL, // 5
+ PhoneLookup.NORMALIZED_NUMBER, // 6
+ PhoneLookup.CONTACT_ID, // 7
+ PhoneLookup.LOOKUP_KEY // 8
};
// The following indexes should match both PHONE_PROJECTION and PHONE_LOOKUP_PROJECTION above.
private static final int CP2_INFO_NAME_INDEX = 0;
- private static final int CP2_INFO_PHOTO_URI_INDEX = 1;
- private static final int CP2_INFO_PHOTO_ID_INDEX = 2;
- private static final int CP2_INFO_TYPE_INDEX = 3;
- private static final int CP2_INFO_LABEL_INDEX = 4;
- private static final int CP2_INFO_NORMALIZED_NUMBER_INDEX = 5;
- private static final int CP2_INFO_CONTACT_ID_INDEX = 6;
- private static final int CP2_INFO_LOOKUP_KEY_INDEX = 7;
+ private static final int CP2_INFO_PHOTO_THUMBNAIL_URI_INDEX = 1;
+ private static final int CP2_INFO_PHOTO_URI_INDEX = 2;
+ private static final int CP2_INFO_PHOTO_ID_INDEX = 3;
+ private static final int CP2_INFO_TYPE_INDEX = 4;
+ private static final int CP2_INFO_LABEL_INDEX = 5;
+ private static final int CP2_INFO_NORMALIZED_NUMBER_INDEX = 6;
+ private static final int CP2_INFO_CONTACT_ID_INDEX = 7;
+ private static final int CP2_INFO_LOOKUP_KEY_INDEX = 8;
private Cp2Projections() {}
@@ -82,6 +85,7 @@ final class Cp2Projections {
*/
static Cp2ContactInfo buildCp2ContactInfoFromCursor(Context appContext, Cursor cursor) {
String displayName = cursor.getString(CP2_INFO_NAME_INDEX);
+ String photoThumbnailUri = cursor.getString(CP2_INFO_PHOTO_THUMBNAIL_URI_INDEX);
String photoUri = cursor.getString(CP2_INFO_PHOTO_URI_INDEX);
int photoId = cursor.getInt(CP2_INFO_PHOTO_ID_INDEX);
int type = cursor.getInt(CP2_INFO_TYPE_INDEX);
@@ -93,6 +97,9 @@ final class Cp2Projections {
if (!TextUtils.isEmpty(displayName)) {
infoBuilder.setName(displayName);
}
+ if (!TextUtils.isEmpty(photoThumbnailUri)) {
+ infoBuilder.setPhotoThumbnailUri(photoThumbnailUri);
+ }
if (!TextUtils.isEmpty(photoUri)) {
infoBuilder.setPhotoUri(photoUri);
}
diff --git a/java/com/android/dialer/phonelookup/phone_lookup_info.proto b/java/com/android/dialer/phonelookup/phone_lookup_info.proto
index e9cb9f8ad..dd6bf664c 100644
--- a/java/com/android/dialer/phonelookup/phone_lookup_info.proto
+++ b/java/com/android/dialer/phonelookup/phone_lookup_info.proto
@@ -19,6 +19,7 @@ message PhoneLookupInfo {
message Cp2Info {
// Information about a single contact, which can be a local contact or a
// remote one.
+ // Next ID: 8
message Cp2ContactInfo {
// For a local contact:
// android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY
@@ -30,13 +31,19 @@ message PhoneLookupInfo {
// android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI
// For a remote contact:
// android.provider.ContactsContract.PhoneLookup.PHOTO_THUMBNAIL_URI
- optional string photo_uri = 2;
+ optional string photo_thumbnail_uri = 2;
+
+ // For a local contact:
+ // android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_URI
+ // For a remote contact:
+ // android.provider.ContactsContract.PhoneLookup.PHOTO_URI
+ optional string photo_uri = 3;
// For a local contact:
// android.provider.ContactsContract.CommonDataKinds.Phone.PHOTO_ID
// For a remote contact:
// android.provider.ContactsContract.PhoneLookup.PHOTO_ID
- optional fixed64 photo_id = 3;
+ optional fixed64 photo_id = 4;
// For a local contact:
// android.provider.ContactsContract.CommonDataKinds.Phone.LABEL
@@ -44,13 +51,13 @@ message PhoneLookupInfo {
// android.provider.ContactsContract.PhoneLookup.LABEL
//
// The value can be "Home", "Mobile", ect.
- optional string label = 4;
+ optional string label = 5;
// For a local contact:
// android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID
// For a remote contact:
// android.provider.ContactsContract.PhoneLookup.CONTACT_ID
- optional fixed64 contact_id = 5;
+ optional fixed64 contact_id = 6;
// For a local contact:
// constructed based on
@@ -58,7 +65,7 @@ message PhoneLookupInfo {
// For a remote contact:
// constructed based on
// android.provider.ContactsContract.PhoneLookup.LOOKUP_KEY
- optional string lookup_uri = 6;
+ optional string lookup_uri = 7;
}
// Repeated because one phone number can be associated with multiple CP2
// contacts.
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index c62d40e59..2d45457d2 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -488,7 +488,9 @@ public final class NewSearchFragment extends Fragment
if (event.getAction() == MotionEvent.ACTION_UP) {
v.performClick();
}
- FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onSearchListTouch();
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onSearchListTouch();
+ }
return false;
}
diff --git a/java/com/android/dialer/simulator/Simulator.java b/java/com/android/dialer/simulator/Simulator.java
index 3c2526be7..11a07d974 100644
--- a/java/com/android/dialer/simulator/Simulator.java
+++ b/java/com/android/dialer/simulator/Simulator.java
@@ -101,6 +101,9 @@ public interface Simulator {
MERGE,
SEPARATE,
SWAP,
+ START_RTT,
+ STOP_RTT,
+ HANDLE_RTT_UPGRADE_RESPONSE,
})
public @interface Type {}
@@ -118,6 +121,9 @@ public interface Simulator {
public static final int MERGE = 11;
public static final int SEPARATE = 12;
public static final int SWAP = 13;
+ public static final int START_RTT = 14;
+ public static final int STOP_RTT = 15;
+ public static final int HANDLE_RTT_UPGRADE_RESPONSE = 16;
@Type public final int type;
/** Holds event specific information. For example, for DTMF this could be the keycode. */
diff --git a/java/com/android/dialer/simulator/impl/RttChatBot.java b/java/com/android/dialer/simulator/impl/RttChatBot.java
new file mode 100644
index 000000000..9c2989a07
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/RttChatBot.java
@@ -0,0 +1,139 @@
+/*
+ * 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.simulator.impl;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.support.annotation.MainThread;
+import android.telecom.Connection.RttTextStream;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.incallui.rtt.protocol.Constants;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/** Chat bot to generate remote RTT chat messages. */
+public class RttChatBot {
+
+ interface Callback {
+ void type(String text);
+ }
+
+ private static final int START_SENDING = 1;
+ private static final int SEND_MESSAGE = 2;
+
+ 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 MessageHandler messageHandler;
+ private final HandlerThread handlerThread;
+
+ RttChatBot(RttTextStream rttTextStream) {
+ handlerThread = new HandlerThread("RttChatBot");
+ handlerThread.start();
+ messageHandler = new MessageHandler(handlerThread.getLooper(), rttTextStream);
+ }
+
+ @MainThread
+ public void start() {
+ Assert.isMainThread();
+ LogUtil.enterBlock("RttChatBot.start");
+ messageHandler.sendEmptyMessage(START_SENDING);
+ }
+
+ @MainThread
+ public void stop() {
+ Assert.isMainThread();
+ LogUtil.enterBlock("RttChatBot.stop");
+ if (handlerThread != null && handlerThread.isAlive()) {
+ handlerThread.quit();
+ }
+ }
+
+ private static class MessageHandler extends Handler {
+ private final RttTextStream rttTextStream;
+ private final Random random = new Random();
+ private final List<String> messageQueue = new ArrayList<>();
+ private int currentTypingPosition = -1;
+ private String currentTypingMessage = null;
+
+ MessageHandler(Looper looper, RttTextStream rttTextStream) {
+ super(looper);
+ this.rttTextStream = rttTextStream;
+ }
+
+ @Override
+ public void handleMessage(android.os.Message msg) {
+ switch (msg.what) {
+ case START_SENDING:
+ sendMessage(obtainMessage(SEND_MESSAGE, nextTyping()));
+ break;
+ case SEND_MESSAGE:
+ String message = (String) msg.obj;
+ LogUtil.w("test", "type: %s, to stream: %s", message, rttTextStream);
+ try {
+ rttTextStream.write(message);
+ } catch (IOException e) {
+ LogUtil.e("RttChatBot.MessageHandler", "write message", e);
+ }
+ if (Constants.BUBBLE_BREAKER.equals(message)) {
+ // Wait 1-11s between two messages.
+ sendMessageDelayed(
+ obtainMessage(SEND_MESSAGE, nextTyping()), 1000 * (1 + random.nextInt(10)));
+ } else {
+ // Wait up to 2s between typing.
+ sendMessageDelayed(obtainMessage(SEND_MESSAGE, nextTyping()), 200 * random.nextInt(10));
+ }
+ break;
+ default: // fall out
+ }
+ }
+
+ private String nextTyping() {
+ if (currentTypingPosition < 0 || currentTypingMessage == null) {
+ if (messageQueue.isEmpty()) {
+ String text = CANDIDATE_MESSAGES[random.nextInt(CANDIDATE_MESSAGES.length)];
+ messageQueue.add(text);
+ }
+ currentTypingMessage = messageQueue.remove(0);
+ currentTypingPosition = 0;
+ }
+ if (currentTypingPosition < currentTypingMessage.length()) {
+ int size = random.nextInt(currentTypingMessage.length() - currentTypingPosition + 1);
+ String messageToType =
+ currentTypingMessage.substring(currentTypingPosition, currentTypingPosition + size);
+ currentTypingPosition = currentTypingPosition + size;
+ return messageToType;
+ } else {
+ currentTypingPosition = -1;
+ currentTypingMessage = null;
+ return Constants.BUBBLE_BREAKER;
+ }
+ }
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java b/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java
index 2bfa98247..81a3d30de 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConferenceCreator.java
@@ -97,7 +97,8 @@ final class SimulatorConferenceCreator
default:
break;
}
- SimulatorSimCallManager.addNewIncomingCall(context, number, false /* isVideo */, extras);
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, number, SimulatorSimCallManager.CALL_TYPE_VOICE, extras);
}
@Override
diff --git a/java/com/android/dialer/simulator/impl/SimulatorConnection.java b/java/com/android/dialer/simulator/impl/SimulatorConnection.java
index d7427dd12..c832a5051 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorConnection.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorConnection.java
@@ -121,6 +121,24 @@ public final class SimulatorConnection extends Connection {
onEvent(new Event(Event.DTMF, Character.toString(c), null));
}
+ @Override
+ public void onStartRtt(@NonNull RttTextStream rttTextStream) {
+ LogUtil.enterBlock("SimulatorConnection.onStartRtt");
+ onEvent(new Event(Event.START_RTT));
+ }
+
+ @Override
+ public void onStopRtt() {
+ LogUtil.enterBlock("SimulatorConnection.onStopRtt");
+ onEvent(new Event(Event.STOP_RTT));
+ }
+
+ @Override
+ public void handleRttUpgradeResponse(RttTextStream rttTextStream) {
+ LogUtil.enterBlock("SimulatorConnection.handleRttUpgradeResponse");
+ onEvent(new Event(Event.HANDLE_RTT_UPGRADE_RESPONSE));
+ }
+
void onEvent(@NonNull Event event) {
events.add(Assert.isNotNull(event));
for (Listener listener : new ArrayList<>(listeners)) {
diff --git a/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java b/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java
index 0bd1c0f22..1bf4b2a00 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorMainMenu.java
@@ -33,7 +33,6 @@ import com.android.dialer.enrichedcall.simulator.EnrichedCallSimulatorActivity;
import com.android.dialer.persistentlog.PersistentLogger;
import com.android.dialer.preferredsim.PreferredSimFallbackContract;
import com.android.dialer.simulator.SimulatorComponent;
-import com.android.incallui.rtt.impl.RttChatActivity;
/** Implements the top level simulator menu. */
final class SimulatorMainMenu {
@@ -42,9 +41,9 @@ final class SimulatorMainMenu {
SimulatorSubMenu simulatorSubMenu = new SimulatorSubMenu(activity.getApplicationContext());
simulatorSubMenu
.addItem("Voice call", SimulatorVoiceCall.getActionProvider(activity))
+ .addItem("Rtt call", SimulatorRttCall.getActionProvider(activity.getApplicationContext()))
.addItem(
"IMS video", SimulatorVideoCall.getActionProvider(activity.getApplicationContext()))
- .addItem("Rtt call mock", () -> simulateRttCallMock(activity.getApplicationContext()))
.addItem(
"Notifications",
SimulatorNotifications.getActionProvider(activity.getApplicationContext()))
@@ -79,10 +78,6 @@ final class SimulatorMainMenu {
return simulatorSubMenu;
}
- 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/dialer/simulator/impl/SimulatorMissedCallCreator.java b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
index 6d4a26278..b8556156b 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorMissedCallCreator.java
@@ -78,7 +78,8 @@ final class SimulatorMissedCallCreator implements SimulatorConnectionService.Lis
extras.putInt(EXTRA_CALL_COUNT, callCount - 1);
extras.putBoolean(EXTRA_IS_MISSED_CALL_CONNECTION, true);
- SimulatorSimCallManager.addNewIncomingCall(context, callerId, false /* isVideo */, extras);
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE, extras);
}
private static boolean isMissedCallConnection(@NonNull Connection connection) {
diff --git a/java/com/android/dialer/simulator/impl/SimulatorRttCall.java b/java/com/android/dialer/simulator/impl/SimulatorRttCall.java
new file mode 100644
index 000000000..7b0066719
--- /dev/null
+++ b/java/com/android/dialer/simulator/impl/SimulatorRttCall.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 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.simulator.impl;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.view.ActionProvider;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.simulator.Simulator;
+import com.android.dialer.simulator.Simulator.Event;
+
+/** Entry point in the simulator to create voice calls. */
+final class SimulatorRttCall
+ implements SimulatorConnectionService.Listener, SimulatorConnection.Listener {
+
+ @NonNull private final Context context;
+ @Nullable private String connectionTag;
+
+ static ActionProvider getActionProvider(@NonNull Context context) {
+ return new SimulatorSubMenu(context)
+ .addItem("Incoming call", () -> new SimulatorRttCall(context).addNewIncomingCall(false))
+ .addItem("Outgoing call", () -> new SimulatorRttCall(context).addNewOutgoingCall())
+ .addItem("Emergency call", () -> new SimulatorRttCall(context).addNewEmergencyCall());
+ }
+
+ private SimulatorRttCall(@NonNull Context context) {
+ this.context = Assert.isNotNull(context);
+ SimulatorConnectionService.addListener(this);
+ SimulatorConnectionService.addListener(
+ new SimulatorConferenceCreator(context, Simulator.CONFERENCE_TYPE_GSM));
+ }
+
+ private void addNewIncomingCall(boolean isSpam) {
+ String callerId =
+ isSpam
+ ? "+1-661-778-3020" /* Blacklisted custom spam number */
+ : "+44 (0) 20 7031 3000" /* Google London office */;
+ connectionTag =
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT);
+ }
+
+ private void addNewOutgoingCall() {
+ String callerId = "+55-31-2128-6800"; // Brazil office.
+ connectionTag =
+ SimulatorSimCallManager.addNewOutgoingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT);
+ }
+
+ private void addNewEmergencyCall() {
+ String callerId = "911";
+ connectionTag =
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_RTT);
+ }
+
+ @Override
+ public void onNewOutgoingConnection(@NonNull SimulatorConnection connection) {
+ if (isMyConnection(connection)) {
+ LogUtil.i("SimulatorRttCall.onNewOutgoingConnection", "connection created");
+ handleNewConnection(connection);
+
+ // Telecom will force the connection to switch to Dialing when we return it. Wait until after
+ // we're returned it before changing call state.
+ ThreadUtil.postOnUiThread(connection::setActive);
+ }
+ }
+
+ @Override
+ public void onNewIncomingConnection(@NonNull SimulatorConnection connection) {
+ if (isMyConnection(connection)) {
+ LogUtil.i("SimulatorRttCall.onNewIncomingConnection", "connection created");
+ handleNewConnection(connection);
+ }
+ }
+
+ @Override
+ public void onConference(
+ @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2) {}
+
+ private void handleNewConnection(@NonNull SimulatorConnection connection) {
+ connection.addListener(this);
+ connection.setConnectionProperties(
+ connection.getConnectionProperties() | Connection.PROPERTY_IS_RTT);
+ }
+
+ private boolean isMyConnection(@NonNull Connection connection) {
+ return connection.getExtras().getBoolean(connectionTag);
+ }
+
+ @Override
+ public void onEvent(@NonNull SimulatorConnection connection, @NonNull Event event) {
+ switch (event.type) {
+ case Event.NONE:
+ throw Assert.createIllegalStateFailException();
+ case Event.ANSWER:
+ connection.setActive();
+ break;
+ case Event.REJECT:
+ connection.setDisconnected(new DisconnectCause(DisconnectCause.REJECTED));
+ break;
+ case Event.HOLD:
+ connection.setOnHold();
+ break;
+ case Event.UNHOLD:
+ connection.setActive();
+ break;
+ case Event.DISCONNECT:
+ connection.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
+ break;
+ case Event.SESSION_MODIFY_REQUEST:
+ ThreadUtil.postDelayedOnUiThread(() -> connection.handleSessionModifyRequest(event), 2000);
+ break;
+ default:
+ LogUtil.i("SimulatorRttCall.onEvent", "unexpected event: " + event.type);
+ break;
+ }
+ }
+}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
index f28393c0c..d51e06816 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorSimCallManager.java
@@ -20,6 +20,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
+import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
@@ -30,6 +31,8 @@ import android.telephony.TelephonyManager;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.strictmode.StrictModeUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
@@ -46,10 +49,20 @@ import java.util.Random;
*/
public class SimulatorSimCallManager {
+ public static final int CALL_TYPE_VOICE = 1;
+ public static final int CALL_TYPE_VIDEO = 2;
+ public static final int CALL_TYPE_RTT = 3;
+
+ /** Call type of a simulator call. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CALL_TYPE_VOICE, CALL_TYPE_VIDEO, CALL_TYPE_RTT})
+ public @interface CallType {}
+
private static final String SIM_CALL_MANAGER_ACCOUNT_ID = "SIMULATOR_ACCOUNT_ID";
private static final String VIDEO_PROVIDER_ACCOUNT_ID = "SIMULATOR_VIDEO_ACCOUNT_ID";
private static final String EXTRA_IS_SIMULATOR_CONNECTION = "is_simulator_connection";
private static final String EXTRA_CONNECTION_TAG = "connection_tag";
+ private static final String EXTRA_CONNECTION_CALL_TYPE = "connection_call_type";
static void register(@NonNull Context context) {
LogUtil.enterBlock("SimulatorSimCallManager.register");
@@ -75,15 +88,15 @@ public class SimulatorSimCallManager {
@NonNull
public static String addNewOutgoingCall(
- @NonNull Context context, @NonNull String phoneNumber, boolean isVideo) {
- return addNewOutgoingCall(context, phoneNumber, isVideo, new Bundle());
+ @NonNull Context context, @NonNull String phoneNumber, @CallType int callType) {
+ return addNewOutgoingCall(context, phoneNumber, callType, new Bundle());
}
@NonNull
public static String addNewOutgoingCall(
@NonNull Context context,
@NonNull String phoneNumber,
- boolean isVideo,
+ @CallType int callType,
@NonNull Bundle extras) {
LogUtil.enterBlock("SimulatorSimCallManager.addNewOutgoingCall");
Assert.isNotNull(context);
@@ -94,13 +107,18 @@ public class SimulatorSimCallManager {
register(context);
extras = new Bundle(extras);
- extras.putAll(createSimulatorConnectionExtras());
+ extras.putAll(createSimulatorConnectionExtras(callType));
Bundle outgoingCallExtras = new Bundle();
outgoingCallExtras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
outgoingCallExtras.putParcelable(
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
- isVideo ? getVideoProviderHandle(context) : getSystemPhoneAccountHandle(context));
+ callType == CALL_TYPE_VIDEO
+ ? getVideoProviderHandle(context)
+ : getSystemPhoneAccountHandle(context));
+ if (callType == CALL_TYPE_RTT) {
+ outgoingCallExtras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true);
+ }
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
try {
@@ -114,13 +132,16 @@ public class SimulatorSimCallManager {
@NonNull
public static String addNewIncomingCall(
- @NonNull Context context, @NonNull String callerId, boolean isVideo) {
- return addNewIncomingCall(context, callerId, isVideo, new Bundle());
+ @NonNull Context context, @NonNull String callerId, @CallType int callType) {
+ return addNewIncomingCall(context, callerId, callType, new Bundle());
}
@NonNull
public static String addNewIncomingCall(
- @NonNull Context context, @NonNull String callerId, boolean isVideo, @NonNull Bundle extras) {
+ @NonNull Context context,
+ @NonNull String callerId,
+ @CallType int callType,
+ @NonNull Bundle extras) {
LogUtil.enterBlock("SimulatorSimCallManager.addNewIncomingCall");
Assert.isNotNull(context);
Assert.isNotNull(callerId);
@@ -130,18 +151,21 @@ public class SimulatorSimCallManager {
extras = new Bundle(extras);
extras.putString(TelephonyManager.EXTRA_INCOMING_NUMBER, callerId);
- extras.putAll(createSimulatorConnectionExtras());
+ extras.putAll(createSimulatorConnectionExtras(callType));
TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
telecomManager.addNewIncomingCall(
- isVideo ? getVideoProviderHandle(context) : getSystemPhoneAccountHandle(context), extras);
+ callType == CALL_TYPE_VIDEO
+ ? getVideoProviderHandle(context)
+ : getSystemPhoneAccountHandle(context),
+ extras);
return extras.getString(EXTRA_CONNECTION_TAG);
}
@NonNull
private static PhoneAccount buildSimCallManagerAccount(Context context) {
return new PhoneAccount.Builder(getSimCallManagerHandle(context), "Simulator SIM call manager")
- .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
+ .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER | PhoneAccount.CAPABILITY_RTT)
.setShortDescription("Simulator SIM call manager")
.setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL))
.build();
@@ -218,12 +242,16 @@ public class SimulatorSimCallManager {
}
@NonNull
- static Bundle createSimulatorConnectionExtras() {
+ static Bundle createSimulatorConnectionExtras(@CallType int callType) {
Bundle extras = new Bundle();
extras.putBoolean(EXTRA_IS_SIMULATOR_CONNECTION, true);
String connectionTag = createUniqueConnectionTag();
extras.putString(EXTRA_CONNECTION_TAG, connectionTag);
extras.putBoolean(connectionTag, true);
+ extras.putInt(EXTRA_CONNECTION_CALL_TYPE, callType);
+ if (callType == CALL_TYPE_RTT) {
+ extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true);
+ }
return extras;
}
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java b/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java
index f7256a11c..0bb56f1f9 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVideoCall.java
@@ -77,7 +77,8 @@ final class SimulatorVideoCall
}
String callerId = "+44 (0) 20 7031 3000"; // Google London office
connectionTag =
- SimulatorSimCallManager.addNewIncomingCall(context, callerId, true /* isVideo */);
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VIDEO);
}
private void addNewOutgoingCall() {
@@ -87,7 +88,8 @@ final class SimulatorVideoCall
}
String phoneNumber = "+44 (0) 20 7031 3000"; // Google London office
connectionTag =
- SimulatorSimCallManager.addNewOutgoingCall(context, phoneNumber, true /* isVideo */);
+ SimulatorSimCallManager.addNewOutgoingCall(
+ context, phoneNumber, SimulatorSimCallManager.CALL_TYPE_VIDEO);
}
@Override
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
index 67a2db804..d4c7ee458 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
@@ -104,7 +104,10 @@ final class SimulatorVoiceCall
extras.putBoolean(Simulator.IS_ENRICHED_CALL, true);
connectionTag =
SimulatorSimCallManager.addNewIncomingCall(
- context, Simulator.ENRICHED_CALL_INCOMING_NUMBER, false, extras);
+ context,
+ Simulator.ENRICHED_CALL_INCOMING_NUMBER,
+ SimulatorSimCallManager.CALL_TYPE_VOICE,
+ extras);
},
DialerExecutorComponent.get(context).uiExecutor());
}
@@ -119,7 +122,10 @@ final class SimulatorVoiceCall
extras.putBoolean(Simulator.IS_ENRICHED_CALL, true);
connectionTag =
SimulatorSimCallManager.addNewOutgoingCall(
- context, Simulator.ENRICHED_CALL_OUTGOING_NUMBER, false, extras);
+ context,
+ Simulator.ENRICHED_CALL_OUTGOING_NUMBER,
+ SimulatorSimCallManager.CALL_TYPE_VOICE,
+ extras);
},
DialerExecutorComponent.get(context).uiExecutor());
}
@@ -127,7 +133,8 @@ final class SimulatorVoiceCall
private void addNewIncomingCall() {
String callerId = "+44 (0) 20 7031 3000" /* Google London office */;
connectionTag =
- SimulatorSimCallManager.addNewIncomingCall(context, callerId, false /* isVideo */);
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE);
}
private void addNewIncomingCall(AppCompatActivity activity) {
@@ -137,7 +144,7 @@ final class SimulatorVoiceCall
extras.putInt(Simulator.PRESENTATION_CHOICE, callerIdPresentation);
connectionTag =
SimulatorSimCallManager.addNewIncomingCall(
- context, callerId, false /* isVideo */, extras);
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE, extras);
})
.show(activity.getSupportFragmentManager(), "SimulatorDialog");
}
@@ -145,7 +152,8 @@ final class SimulatorVoiceCall
private void addNewOutgoingCall() {
String callerId = "+55-31-2128-6800"; // Brazil office.
connectionTag =
- SimulatorSimCallManager.addNewOutgoingCall(context, callerId, false /* isVideo */);
+ SimulatorSimCallManager.addNewOutgoingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE);
}
private void addNewOutgoingCall(AppCompatActivity activity) {
@@ -155,7 +163,7 @@ final class SimulatorVoiceCall
extras.putInt(Simulator.PRESENTATION_CHOICE, callerIdPresentation);
connectionTag =
SimulatorSimCallManager.addNewOutgoingCall(
- context, callerId, false /* isVideo */, extras);
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE, extras);
})
.show(activity.getSupportFragmentManager(), "SimulatorDialog");
}
@@ -163,12 +171,15 @@ final class SimulatorVoiceCall
private void addSpamIncomingCall() {
String callerId = "+1-661-778-3020"; /* Blacklisted custom spam number */
connectionTag =
- SimulatorSimCallManager.addNewIncomingCall(context, callerId, false /* isVideo */);
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE);
}
private void addNewEmergencyCallBack() {
String callerId = "911";
- connectionTag = SimulatorSimCallManager.addNewIncomingCall(context, callerId, false);
+ connectionTag =
+ SimulatorSimCallManager.addNewIncomingCall(
+ context, callerId, SimulatorSimCallManager.CALL_TYPE_VOICE);
}
@Override
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 8769be5d9..67f5cfe4f 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -83,6 +83,10 @@ import com.android.incallui.incall.protocol.InCallScreen;
import com.android.incallui.incall.protocol.InCallScreenDelegate;
import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
import com.android.incallui.incalluilock.InCallUiLock;
+import com.android.incallui.rtt.bindings.RttBindings;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegateFactory;
import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment;
import com.android.incallui.video.bindings.VideoBindings;
import com.android.incallui.video.protocol.VideoCallScreen;
@@ -100,6 +104,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
InCallScreenDelegateFactory,
InCallButtonUiDelegateFactory,
VideoCallScreenDelegateFactory,
+ RttCallScreenDelegateFactory,
PseudoScreenState.StateChangedListener {
@Retention(RetentionPolicy.SOURCE)
@@ -136,6 +141,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
private boolean didShowAnswerScreen;
private boolean didShowInCallScreen;
private boolean didShowVideoCallScreen;
+ private boolean didShowRttCallScreen;
private boolean dismissKeyguard;
private boolean isInShowMainInCallFragment;
private boolean isRecreating; // whether the activity is going to be recreated
@@ -1220,37 +1226,47 @@ public class InCallActivity extends TransactionSafeFragmentActivity
isInShowMainInCallFragment = true;
ShouldShowUiResult shouldShowAnswerUi = getShouldShowAnswerUi();
ShouldShowUiResult shouldShowVideoUi = getShouldShowVideoUi();
+ ShouldShowUiResult shouldShowRttUi = getShouldShowRttUi();
LogUtil.i(
"InCallActivity.showMainInCallFragment",
- "shouldShowAnswerUi: %b, shouldShowVideoUi: %b, "
- + "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowVideoCallScreen: %b",
+ "shouldShowAnswerUi: %b, shouldShowRttUi: %b, shouldShowVideoUi: %b "
+ + "didShowAnswerScreen: %b, didShowInCallScreen: %b, didShowRttCallScreen: %b, "
+ + "didShowVideoCallScreen: %b",
shouldShowAnswerUi.shouldShow,
+ shouldShowRttUi.shouldShow,
shouldShowVideoUi.shouldShow,
didShowAnswerScreen,
didShowInCallScreen,
+ didShowRttCallScreen,
didShowVideoCallScreen);
// Only video call ui allows orientation change.
setAllowOrientationChange(shouldShowVideoUi.shouldShow);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- boolean didChangeInCall;
- boolean didChangeVideo;
- boolean didChangeAnswer;
+ boolean didChange;
if (shouldShowAnswerUi.shouldShow) {
- didChangeInCall = hideInCallScreenFragment(transaction);
- didChangeVideo = hideVideoCallScreenFragment(transaction);
- didChangeAnswer = showAnswerScreenFragment(transaction, shouldShowAnswerUi.call);
+ didChange = hideInCallScreenFragment(transaction);
+ didChange |= hideVideoCallScreenFragment(transaction);
+ didChange |= hideRttCallScreenFragment(transaction);
+ didChange |= showAnswerScreenFragment(transaction, shouldShowAnswerUi.call);
} else if (shouldShowVideoUi.shouldShow) {
- didChangeInCall = hideInCallScreenFragment(transaction);
- didChangeVideo = showVideoCallScreenFragment(transaction, shouldShowVideoUi.call);
- didChangeAnswer = hideAnswerScreenFragment(transaction);
+ didChange = hideInCallScreenFragment(transaction);
+ didChange |= showVideoCallScreenFragment(transaction, shouldShowVideoUi.call);
+ didChange |= hideRttCallScreenFragment(transaction);
+ didChange |= hideAnswerScreenFragment(transaction);
+ } else if (shouldShowRttUi.shouldShow) {
+ didChange = hideInCallScreenFragment(transaction);
+ didChange |= hideVideoCallScreenFragment(transaction);
+ didChange |= hideAnswerScreenFragment(transaction);
+ didChange |= showRttCallScreenFragment(transaction, shouldShowRttUi.call);
} else {
- didChangeInCall = showInCallScreenFragment(transaction);
- didChangeVideo = hideVideoCallScreenFragment(transaction);
- didChangeAnswer = hideAnswerScreenFragment(transaction);
+ didChange = showInCallScreenFragment(transaction);
+ didChange |= hideVideoCallScreenFragment(transaction);
+ didChange |= hideRttCallScreenFragment(transaction);
+ didChange |= hideAnswerScreenFragment(transaction);
}
- if (didChangeInCall || didChangeVideo || didChangeAnswer) {
+ if (didChange) {
Trace.beginSection("InCallActivity.commitTransaction");
transaction.commitNow();
Trace.endSection();
@@ -1308,6 +1324,26 @@ public class InCallActivity extends TransactionSafeFragmentActivity
return new ShouldShowUiResult(false, null);
}
+ private static ShouldShowUiResult getShouldShowRttUi() {
+ DialerCall call = CallList.getInstance().getFirstCall();
+ if (call == null) {
+ LogUtil.i("InCallActivity.getShouldShowRttUi", "null call");
+ return new ShouldShowUiResult(false, null);
+ }
+
+ if (call.isRttCall()) {
+ LogUtil.i("InCallActivity.getShouldShowRttUi", "found rtt call");
+ return new ShouldShowUiResult(true, call);
+ }
+
+ if (call.hasSentRttUpgradeRequest()) {
+ LogUtil.i("InCallActivity.getShouldShowRttUi", "upgrading to rtt");
+ return new ShouldShowUiResult(true, call);
+ }
+
+ return new ShouldShowUiResult(false, null);
+ }
+
private boolean showAnswerScreenFragment(FragmentTransaction transaction, DialerCall call) {
// When rejecting a call the active call can become null in which case we should continue
// showing the answer screen.
@@ -1347,6 +1383,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
AnswerScreen answerScreen =
AnswerBindings.createAnswerScreen(
call.getId(),
+ call.isRttCall(),
call.isVideoCall(),
isVideoUpgradeRequest,
call.getVideoTech().isSelfManagedCamera(),
@@ -1418,6 +1455,33 @@ public class InCallActivity extends TransactionSafeFragmentActivity
return true;
}
+ private boolean showRttCallScreenFragment(FragmentTransaction transaction, DialerCall call) {
+ if (didShowRttCallScreen) {
+ // This shouldn't happen since only one RTT call is allow at same time.
+ if (!getRttCallScreen().getCallId().equals(call.getId())) {
+ LogUtil.e("InCallActivity.showRttCallScreenFragment", "RTT call id doesn't match");
+ }
+ return false;
+ }
+ RttCallScreen rttCallScreen = RttBindings.createRttCallScreen(call.getId());
+ transaction.add(R.id.main, rttCallScreen.getRttCallScreenFragment(), Tags.RTT_CALL_SCREEN);
+ Logger.get(this).logScreenView(ScreenEvent.Type.INCALL, this);
+ didShowRttCallScreen = true;
+ return true;
+ }
+
+ private boolean hideRttCallScreenFragment(FragmentTransaction transaction) {
+ if (!didShowRttCallScreen) {
+ return false;
+ }
+ RttCallScreen rttCallScreen = getRttCallScreen();
+ if (rttCallScreen != null) {
+ transaction.remove(rttCallScreen.getRttCallScreenFragment());
+ }
+ didShowRttCallScreen = false;
+ return true;
+ }
+
private boolean showVideoCallScreenFragment(FragmentTransaction transaction, DialerCall call) {
if (didShowVideoCallScreen) {
VideoCallScreen videoCallScreen = getVideoCallScreen();
@@ -1467,6 +1531,10 @@ public class InCallActivity extends TransactionSafeFragmentActivity
return (VideoCallScreen) getSupportFragmentManager().findFragmentByTag(Tags.VIDEO_CALL_SCREEN);
}
+ private RttCallScreen getRttCallScreen() {
+ return (RttCallScreen) getSupportFragmentManager().findFragmentByTag(Tags.RTT_CALL_SCREEN);
+ }
+
@Override
public void onPseudoScreenStateChanged(boolean isOn) {
LogUtil.i("InCallActivity.onPseudoScreenStateChanged", "isOn: " + isOn);
@@ -1499,6 +1567,11 @@ public class InCallActivity extends TransactionSafeFragmentActivity
return super.dispatchTouchEvent(event);
}
+ @Override
+ public RttCallScreenDelegate newRttCallScreenDelegate(RttCallScreen videoCallScreen) {
+ return new RttCallPresenter();
+ }
+
private static class ShouldShowUiResult {
public final boolean shouldShow;
public final DialerCall call;
@@ -1536,6 +1609,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
static final String INTERNATIONAL_CALL_ON_WIFI = "tag_international_call_on_wifi";
static final String SELECT_ACCOUNT_FRAGMENT = "tag_select_account_fragment";
static final String VIDEO_CALL_SCREEN = "tag_video_call_screen";
+ static final String RTT_CALL_SCREEN = "tag_rtt_call_screen";
static final String POST_CHAR_DIALOG_FRAGMENT = "tag_post_char_dialog_fragment";
}
diff --git a/java/com/android/incallui/ProximitySensor.java b/java/com/android/incallui/ProximitySensor.java
index f82b75d06..4b033441d 100644
--- a/java/com/android/incallui/ProximitySensor.java
+++ b/java/com/android/incallui/ProximitySensor.java
@@ -55,6 +55,7 @@ public class ProximitySensor
private boolean dialpadVisible;
private boolean isAttemptingVideoCall;
private boolean isVideoCall;
+ private boolean isRttCall;
public ProximitySensor(
@NonNull Context context,
@@ -112,10 +113,14 @@ public class ProximitySensor
DialerCall activeCall = callList.getActiveCall();
boolean isVideoCall = activeCall != null && activeCall.isVideoCall();
+ boolean isRttCall = activeCall != null && activeCall.isRttCall();
- if (isOffhook != isPhoneOffhook || this.isVideoCall != isVideoCall) {
+ if (isOffhook != isPhoneOffhook
+ || this.isVideoCall != isVideoCall
+ || this.isRttCall != isRttCall) {
isPhoneOffhook = isOffhook;
this.isVideoCall = isVideoCall;
+ this.isRttCall = isRttCall;
orientation = AccelerometerListener.ORIENTATION_UNKNOWN;
accelerometerListener.enable(isPhoneOffhook);
@@ -217,7 +222,8 @@ public class ProximitySensor
|| CallAudioState.ROUTE_SPEAKER == audioRoute
|| CallAudioState.ROUTE_BLUETOOTH == audioRoute
|| isAttemptingVideoCall
- || isVideoCall);
+ || isVideoCall
+ || isRttCall);
// We do not keep the screen off when the user is outside in-call screen and we are
// horizontal, but we do not force it on when we become horizontal until the
diff --git a/java/com/android/incallui/RttCallPresenter.java b/java/com/android/incallui/RttCallPresenter.java
new file mode 100644
index 000000000..b90d56b36
--- /dev/null
+++ b/java/com/android/incallui/RttCallPresenter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.incallui;
+
+import android.content.Context;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+
+/**
+ * Logic related to the {@link RttCallScreen} and for managing changes to the RTT calling surfaces
+ * based on other user interface events and incoming events.
+ */
+public class RttCallPresenter implements RttCallScreenDelegate {
+
+ private Context appContext;
+ private RttCallScreen rttCallScreen;
+
+ @Override
+ public void initRttCallScreenDelegate(Context context, RttCallScreen rttCallScreen) {
+ this.appContext = context.getApplicationContext();
+ this.rttCallScreen = rttCallScreen;
+ }
+
+ @Override
+ public void onRttCallScreenUiReady() {}
+
+ @Override
+ public void onRttCallScreenUiUnready() {}
+}
diff --git a/java/com/android/incallui/answer/bindings/AnswerBindings.java b/java/com/android/incallui/answer/bindings/AnswerBindings.java
index 0b546db63..9f4199b7b 100644
--- a/java/com/android/incallui/answer/bindings/AnswerBindings.java
+++ b/java/com/android/incallui/answer/bindings/AnswerBindings.java
@@ -24,6 +24,7 @@ public class AnswerBindings {
public static AnswerScreen createAnswerScreen(
String callId,
+ boolean isRttCall,
boolean isVideoCall,
boolean isVideoUpgradeRequest,
boolean isSelfManagedCamera,
@@ -31,6 +32,7 @@ public class AnswerBindings {
boolean hasCallOnHold) {
return AnswerFragment.newInstance(
callId,
+ isRttCall,
isVideoCall,
isVideoUpgradeRequest,
isSelfManagedCamera,
diff --git a/java/com/android/incallui/answer/impl/AnswerFragment.java b/java/com/android/incallui/answer/impl/AnswerFragment.java
index d687b6e01..8626e6d0e 100644
--- a/java/com/android/incallui/answer/impl/AnswerFragment.java
+++ b/java/com/android/incallui/answer/impl/AnswerFragment.java
@@ -103,6 +103,8 @@ public class AnswerFragment extends Fragment
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String ARG_CALL_ID = "call_id";
+ static final String ARG_IS_RTT_CALL = "is_rtt_call";
+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String ARG_IS_VIDEO_CALL = "is_video_call";
@@ -344,6 +346,7 @@ public class AnswerFragment extends Fragment
public static AnswerFragment newInstance(
String callId,
+ boolean isRttCall,
boolean isVideoCall,
boolean isVideoUpgradeRequest,
boolean isSelfManagedCamera,
@@ -351,6 +354,7 @@ public class AnswerFragment extends Fragment
boolean hasCallOnHold) {
Bundle bundle = new Bundle();
bundle.putString(ARG_CALL_ID, Assert.isNotNull(callId));
+ bundle.putBoolean(ARG_IS_RTT_CALL, isRttCall);
bundle.putBoolean(ARG_IS_VIDEO_CALL, isVideoCall);
bundle.putBoolean(ARG_IS_VIDEO_UPGRADE_REQUEST, isVideoUpgradeRequest);
bundle.putBoolean(ARG_IS_SELF_MANAGED_CAMERA, isSelfManagedCamera);
@@ -663,6 +667,7 @@ public class AnswerFragment extends Fragment
Trace.beginSection("AnswerFragment.onCreateView");
Bundle arguments = getArguments();
Assert.checkState(arguments.containsKey(ARG_CALL_ID));
+ Assert.checkState(arguments.containsKey(ARG_IS_RTT_CALL));
Assert.checkState(arguments.containsKey(ARG_IS_VIDEO_CALL));
Assert.checkState(arguments.containsKey(ARG_IS_VIDEO_UPGRADE_REQUEST));
@@ -836,6 +841,11 @@ public class AnswerFragment extends Fragment
}
@Override
+ public boolean isRttCall() {
+ return getArguments().getBoolean(ARG_IS_RTT_CALL);
+ }
+
+ @Override
public boolean isVideoCall() {
return getArguments().getBoolean(ARG_IS_VIDEO_CALL);
}
diff --git a/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java b/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java
index afa194f2e..0f1455c74 100644
--- a/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java
+++ b/java/com/android/incallui/answer/impl/answermethod/AnswerMethodHolder.java
@@ -46,4 +46,6 @@ public interface AnswerMethodHolder {
boolean isVideoCall();
boolean isVideoUpgradeRequest();
+
+ boolean isRttCall();
}
diff --git a/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java b/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java
index fe6bbbca5..b5dbc0c20 100644
--- a/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java
+++ b/java/com/android/incallui/answer/impl/answermethod/FlingUpDownMethod.java
@@ -335,6 +335,8 @@ public class FlingUpDownMethod extends AnswerMethod implements OnProgressChanged
}
if (getParent().isVideoCall() || getParent().isVideoUpgradeRequest()) {
contactPuckIcon.setImageResource(R.drawable.quantum_ic_videocam_white_24);
+ } else if (getParent().isRttCall()) {
+ contactPuckIcon.setImageResource(R.drawable.quantum_ic_call_white_24);
} else {
contactPuckIcon.setImageResource(R.drawable.quantum_ic_call_white_24);
}
diff --git a/java/com/android/incallui/answer/protocol/AnswerScreen.java b/java/com/android/incallui/answer/protocol/AnswerScreen.java
index 5ad500200..f030ce984 100644
--- a/java/com/android/incallui/answer/protocol/AnswerScreen.java
+++ b/java/com/android/incallui/answer/protocol/AnswerScreen.java
@@ -24,6 +24,8 @@ public interface AnswerScreen {
String getCallId();
+ boolean isRttCall();
+
boolean isVideoCall();
boolean isVideoUpgradeRequest();
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index 1785eceb4..cbe7c57a6 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -32,6 +32,7 @@ import android.support.annotation.VisibleForTesting;
import android.support.v4.os.BuildCompat;
import android.telecom.Call;
import android.telecom.Call.Details;
+import android.telecom.Call.RttCall;
import android.telecom.CallAudioState;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
@@ -263,6 +264,28 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
}
@Override
+ public void onRttModeChanged(Call call, int mode) {
+ LogUtil.v("TelecomCallCallback.onRttModeChanged", "mode=%d", mode);
+ }
+
+ @Override
+ public void onRttRequest(Call call, int id) {
+ LogUtil.v("TelecomCallCallback.onRttRequest", "id=%d", id);
+ }
+
+ @Override
+ public void onRttInitiationFailure(Call call, int reason) {
+ LogUtil.v("TelecomCallCallback.onRttInitiationFailure", "reason=%d", reason);
+ update();
+ }
+
+ @Override
+ public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {
+ LogUtil.v("TelecomCallCallback.onRttStatusChanged", "enabled=%b", enabled);
+ update();
+ }
+
+ @Override
public void onConnectionEvent(android.telecom.Call call, String event, Bundle extras) {
LogUtil.v(
"TelecomCallCallback.onConnectionEvent",
@@ -906,6 +929,14 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
return getVideoTech().isTransmittingOrReceiving() || VideoProfile.isVideo(getVideoState());
}
+ public boolean isRttCall() {
+ if (BuildCompat.isAtLeastP()) {
+ return getTelecomCall().isRttActive();
+ } else {
+ return false;
+ }
+ }
+
public boolean hasReceivedVideoUpgradeRequest() {
return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState());
}
@@ -914,6 +945,11 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
return VideoUtils.hasSentVideoUpgradeRequest(getVideoTech().getSessionModificationState());
}
+ public boolean hasSentRttUpgradeRequest() {
+ // TODO(wangqi): Implement this.
+ return false;
+ }
+
/**
* Determines if the call handle is an emergency number or not and caches the result to avoid
* repeated calls to isEmergencyNumber.
diff --git a/java/com/android/incallui/rtt/bindings/RttBindings.java b/java/com/android/incallui/rtt/bindings/RttBindings.java
new file mode 100644
index 000000000..8f9a1437e
--- /dev/null
+++ b/java/com/android/incallui/rtt/bindings/RttBindings.java
@@ -0,0 +1,28 @@
+/*
+ * 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.bindings;
+
+import com.android.incallui.rtt.impl.RttChatFragment;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+
+/** Bindings for RTT module. */
+public class RttBindings {
+
+ public static RttCallScreen createRttCallScreen(String callId) {
+ return RttChatFragment.newInstance(callId);
+ }
+}
diff --git a/java/com/android/incallui/rtt/impl/AndroidManifest.xml b/java/com/android/incallui/rtt/impl/AndroidManifest.xml
index fc0705d7e..7f58f71e5 100644
--- a/java/com/android/incallui/rtt/impl/AndroidManifest.xml
+++ b/java/com/android/incallui/rtt/impl/AndroidManifest.xml
@@ -13,14 +13,5 @@
~ 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 package="com.android.incallui.rtt.impl">
</manifest>
diff --git a/java/com/android/incallui/rtt/impl/RttChatActivity.java b/java/com/android/incallui/rtt/impl/RttChatActivity.java
deleted file mode 100644
index 96056f746..000000000
--- a/java/com/android/incallui/rtt/impl/RttChatActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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
index 1db4c6bad..1ea7f31b1 100644
--- a/java/com/android/incallui/rtt/impl/RttChatAdapter.java
+++ b/java/com/android/incallui/rtt/impl/RttChatAdapter.java
@@ -17,19 +17,15 @@
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> {
@@ -42,13 +38,11 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde
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
@@ -133,7 +127,6 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde
rttMessages.get(lastIndexOfLocalMessage).finish();
notifyItemChanged(lastIndexOfLocalMessage);
lastIndexOfLocalMessage = -1;
- startChatBot();
}
void addRemoteMessage(String message) {
@@ -146,73 +139,4 @@ public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolde
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
index 0b0ad2a8e..c7ee2ff67 100644
--- a/java/com/android/incallui/rtt/impl/RttChatFragment.java
+++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java
@@ -16,21 +16,25 @@
package com.android.incallui.rtt.impl;
+import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
+import android.support.annotation.NonNull;
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.telecom.CallAudioState;
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.Window;
+import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Chronometer;
@@ -38,15 +42,34 @@ import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.FragmentUtils;
+import com.android.dialer.common.LogUtil;
+import com.android.incallui.call.DialerCall.State;
+import com.android.incallui.incall.protocol.InCallButtonUi;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
+import com.android.incallui.incall.protocol.InCallScreen;
+import com.android.incallui.incall.protocol.InCallScreenDelegate;
+import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
+import com.android.incallui.incall.protocol.PrimaryCallState;
+import com.android.incallui.incall.protocol.PrimaryInfo;
+import com.android.incallui.incall.protocol.SecondaryInfo;
import com.android.incallui.rtt.impl.RttChatAdapter.MessageListener;
+import com.android.incallui.rtt.protocol.RttCallScreen;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
+import com.android.incallui.rtt.protocol.RttCallScreenDelegateFactory;
/** RTT chat fragment to show chat bubbles. */
public class RttChatFragment extends Fragment
- implements OnClickListener, OnEditorActionListener, TextWatcher, MessageListener {
+ implements OnEditorActionListener,
+ TextWatcher,
+ MessageListener,
+ RttCallScreen,
+ InCallScreen,
+ InCallButtonUi {
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;
@@ -63,27 +86,59 @@ public class RttChatFragment extends Fragment
}
}
};
+ private InCallScreenDelegate inCallScreenDelegate;
+ private RttCallScreenDelegate rttCallScreenDelegate;
+ private InCallButtonUiDelegate inCallButtonUiDelegate;
+ private View endCallButton;
+ private TextView nameTextView;
+ private Chronometer chronometer;
+ private boolean isTimerStarted;
/**
* 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) {
+ public static RttChatFragment newInstance(String callId) {
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;
}
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LogUtil.i("RttChatFragment.onCreate", null);
+ inCallButtonUiDelegate =
+ FragmentUtils.getParent(this, InCallButtonUiDelegateFactory.class)
+ .newInCallButtonUiDelegate();
+ if (savedInstanceState != null) {
+ inCallButtonUiDelegate.onRestoreInstanceState(savedInstanceState);
+ }
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) {
+ super.onViewCreated(view, bundle);
+ LogUtil.i("RttChatFragment.onViewCreated", null);
+
+ inCallScreenDelegate =
+ FragmentUtils.getParentUnsafe(this, InCallScreenDelegateFactory.class)
+ .newInCallScreenDelegate();
+ rttCallScreenDelegate =
+ FragmentUtils.getParentUnsafe(this, RttCallScreenDelegateFactory.class)
+ .newRttCallScreenDelegate(this);
+
+ rttCallScreenDelegate.initRttCallScreenDelegate(getContext(), this);
+
+ inCallScreenDelegate.onInCallScreenDelegateInit(this);
+ inCallScreenDelegate.onInCallScreenReady();
+ inCallButtonUiDelegate.onInCallButtonUiReady(this);
+ }
+
@Nullable
@Override
public View onCreateView(
@@ -101,38 +156,27 @@ public class RttChatFragment extends Fragment
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(onScrollListener);
submitButton = view.findViewById(R.id.rtt_chat_submit_button);
- submitButton.setOnClickListener(this);
+ submitButton.setOnClickListener(
+ v -> {
+ adapter.submitLocalMessage();
+ isClearingInput = true;
+ editText.setText("");
+ isClearingInput = false;
+ });
submitButton.setEnabled(false);
+ endCallButton = view.findViewById(R.id.rtt_end_call_button);
+ endCallButton.setOnClickListener(
+ v -> {
+ LogUtil.i("RttChatFragment.onClick", "end call button clicked");
+ inCallButtonUiDelegate.onEndCallClicked();
+ });
- 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();
+ nameTextView = view.findViewById(R.id.rtt_name_or_number);
+ chronometer = view.findViewById(R.id.rtt_timer);
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();
@@ -166,6 +210,20 @@ public class RttChatFragment extends Fragment
recyclerView.smoothScrollToPosition(adapter.getItemCount());
}
+ @Override
+ public void onStart() {
+ LogUtil.enterBlock("RttChatFragment.onStart");
+ super.onStart();
+ onRttScreenStart();
+ }
+
+ @Override
+ public void onStop() {
+ LogUtil.enterBlock("RttChatFragment.onStop");
+ super.onStop();
+ onRttScreenStop();
+ }
+
private void hideKeyboard() {
InputMethodManager inputMethodManager = getContext().getSystemService(InputMethodManager.class);
if (inputMethodManager.isAcceptingText()) {
@@ -173,4 +231,129 @@ public class RttChatFragment extends Fragment
getActivity().getCurrentFocus().getWindowToken(), 0);
}
}
+
+ @Override
+ public void onRttScreenStart() {
+ rttCallScreenDelegate.onRttCallScreenUiReady();
+ Activity activity = getActivity();
+ Window window = getActivity().getWindow();
+ window.setStatusBarColor(activity.getColor(R.color.rtt_status_bar_color));
+ window.setNavigationBarColor(activity.getColor(R.color.rtt_navigation_bar_color));
+ window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ }
+
+ @Override
+ public void onRttScreenStop() {
+ rttCallScreenDelegate.onRttCallScreenUiUnready();
+ }
+
+ @Override
+ public Fragment getRttCallScreenFragment() {
+ return this;
+ }
+
+ @Override
+ public String getCallId() {
+ return Assert.isNotNull(getArguments().getString(ARG_CALL_ID));
+ }
+
+ @Override
+ public void setPrimary(@NonNull PrimaryInfo primaryInfo) {
+ LogUtil.i("RttChatFragment.setPrimary", primaryInfo.toString());
+ nameTextView.setText(primaryInfo.name);
+ }
+
+ @Override
+ public void setSecondary(@NonNull SecondaryInfo secondaryInfo) {}
+
+ @Override
+ public void setCallState(@NonNull PrimaryCallState primaryCallState) {
+ LogUtil.i("RttChatFragment.setCallState", primaryCallState.toString());
+ if (!isTimerStarted && primaryCallState.state == State.ACTIVE) {
+ LogUtil.i(
+ "RttChatFragment.setCallState", "starting timer with base: %d", chronometer.getBase());
+ chronometer.setBase(
+ primaryCallState.connectTimeMillis
+ - System.currentTimeMillis()
+ + SystemClock.elapsedRealtime());
+ chronometer.start();
+ isTimerStarted = true;
+ }
+ }
+
+ @Override
+ public void setEndCallButtonEnabled(boolean enabled, boolean animate) {}
+
+ @Override
+ public void showManageConferenceCallButton(boolean visible) {}
+
+ @Override
+ public boolean isManageConferenceVisible() {
+ return false;
+ }
+
+ @Override
+ public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {}
+
+ @Override
+ public void showNoteSentToast() {}
+
+ @Override
+ public void updateInCallScreenColors() {}
+
+ @Override
+ public void onInCallScreenDialpadVisibilityChange(boolean isShowing) {}
+
+ @Override
+ public int getAnswerAndDialpadContainerResourceId() {
+ return 0;
+ }
+
+ @Override
+ public void showLocationUi(Fragment locationUi) {}
+
+ @Override
+ public boolean isShowingLocationUi() {
+ return false;
+ }
+
+ @Override
+ public Fragment getInCallScreenFragment() {
+ return this;
+ }
+
+ @Override
+ public void showButton(int buttonId, boolean show) {}
+
+ @Override
+ public void enableButton(int buttonId, boolean enable) {}
+
+ @Override
+ public void setEnabled(boolean on) {}
+
+ @Override
+ public void setHold(boolean on) {}
+
+ @Override
+ public void setCameraSwitched(boolean isBackFacingCamera) {}
+
+ @Override
+ public void setVideoPaused(boolean isPaused) {}
+
+ @Override
+ public void setAudioState(CallAudioState audioState) {}
+
+ @Override
+ public void updateButtonStates() {}
+
+ @Override
+ public void updateInCallButtonUiColors(int color) {}
+
+ @Override
+ public Fragment getInCallButtonUiFragment() {
+ return this;
+ }
+
+ @Override
+ public void showAudioRouteSelector() {}
}
diff --git a/java/com/android/incallui/rtt/impl/RttChatMessage.java b/java/com/android/incallui/rtt/impl/RttChatMessage.java
index 85b045183..b36da77cc 100644
--- a/java/com/android/incallui/rtt/impl/RttChatMessage.java
+++ b/java/com/android/incallui/rtt/impl/RttChatMessage.java
@@ -19,6 +19,7 @@ package com.android.incallui.rtt.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextWatcher;
+import com.android.incallui.rtt.protocol.Constants;
import com.google.common.base.Splitter;
import java.util.ArrayList;
import java.util.Iterator;
@@ -27,8 +28,7 @@ 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);
+ private static final Splitter SPLITTER = Splitter.on(Constants.BUBBLE_BREAKER);
boolean isRemote;
public boolean hasAvatar;
@@ -108,7 +108,7 @@ final class RttChatMessage {
firstMessage.isRemote = true;
}
firstMessage.append(firstMessageContent);
- if (splitText.hasNext() || text.endsWith(BUBBLE_BREAKER)) {
+ if (splitText.hasNext() || text.endsWith(Constants.BUBBLE_BREAKER)) {
firstMessage.finish();
}
messageList.add(firstMessage);
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
index 7ba6a09e3..5ba9f4ee8 100644
--- 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
@@ -17,7 +17,8 @@
<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">
+ android:background="@color/dialer_theme_color"
+ android:fitsSystemWindows="true">
<include layout="@layout/rtt_banner"/>
@@ -52,6 +53,8 @@
android:inputType="textMultiLine|text"
android:maxLines="4"
android:minHeight="53dp"
+ android:textColor="#DD000000"
+ android:textColorHint="#757575"
android:textSize="16sp"/>
<ImageButton
android:id="@+id/rtt_chat_submit_button"
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
index 4ce94f9fb..f1938056f 100644
--- a/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml
+++ b/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml
@@ -17,79 +17,61 @@
<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:layout_height="?attr/actionBarSize"
+ android:background="#F305228F"
android:elevation="3dp">
<ImageButton
- android:id="@+id/rtt_back"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:id="@+id/rtt_end_call_button"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
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_arrow_back_vd_theme_24"
- android:tint="#DF000000"/>
+ android:contentDescription="@string/incall_content_description_end_call"
+ android:scaleType="fitXY"
+ android:src="@drawable/quantum_ic_call_end_vd_theme_24"
+ android:tint="#FFDF0000"/>
<LinearLayout
- android:layout_width="wrap_content"
+ android:layout_width="260dp"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginStart="32dp"
- android:layout_toEndOf="@id/rtt_back"
+ android:layout_toEndOf="@id/rtt_end_call_button"
android:orientation="vertical">
<TextView
android:id="@+id/rtt_name_or_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
android:fontFamily="sans-serif-medium"
android:includeFontPadding="false"
- android:textColor="#DD000000"
+ android:textColor="#FFFFFF"
android:textSize="20sp"
tools:text="Bruce Graham"/>
<Chronometer
android:id="@+id/rtt_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
android:fontFamily="sans-serif-medium"
android:includeFontPadding="false"
- android:textColor="#DD000000"
+ android:textColor="#FFFFFF"
android:textSize="14sp"
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:id="@+id/rtt_overflow_button"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_marginEnd="12dp"
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"/>
+ android:contentDescription="@string/content_description_overflow"
+ android:scaleType="fitXY"
+ android:src="@drawable/quantum_ic_more_vert_vd_theme_24"
+ android:tint="#FFFFFF"/>
</RelativeLayout> \ 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
index 402cac4a0..c25ad21f2 100644
--- a/java/com/android/incallui/rtt/impl/res/values/colors.xml
+++ b/java/com/android/incallui/rtt/impl/res/values/colors.xml
@@ -15,5 +15,6 @@
~ limitations under the License
-->
<resources>
- <color name="rtt_status_bar_color">#E0E0E0</color>
+ <color name="rtt_status_bar_color">#03165C</color>
+ <color name="rtt_navigation_bar_color">#FAFAFA</color>
</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
index 523abdcbc..0b9eb71f4 100644
--- a/java/com/android/incallui/rtt/impl/res/values/strings.xml
+++ b/java/com/android/incallui/rtt/impl/res/values/strings.xml
@@ -18,9 +18,6 @@
<!-- Content description for submit chat input button. [CHAR LIMIT=NONE] -->
<string name="content_description_rtt_check_button">Go ahead</string>
- <!-- Content description for navigate back button on RTT chat window. [CHAR LIMIT=NONE] -->
- <string name="content_description_rtt_back_button">Back</string>
-
<!-- Hint text for input box. [CHAR LIMIT=NONE] -->
<string name="rtt_input_hint">Type a message</string>
diff --git a/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml b/java/com/android/incallui/rtt/protocol/AndroidManifest.xml
index b48e8d43f..52514a501 100644
--- a/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml
+++ b/java/com/android/incallui/rtt/protocol/AndroidManifest.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 The Android Open Source Project
~
@@ -14,13 +13,10 @@
~ 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
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.incallui.rtt.protocol">
+ <uses-sdk
+ android:minSdkVersion="23"
+ android:targetSdkVersion="26"/>
+</manifest> \ No newline at end of file
diff --git a/java/com/android/incallui/rtt/protocol/Constants.java b/java/com/android/incallui/rtt/protocol/Constants.java
new file mode 100644
index 000000000..5806bbada
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/Constants.java
@@ -0,0 +1,24 @@
+/*
+ * 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.protocol;
+
+/** Constants for RTT call. */
+public interface Constants {
+
+ /** String used to break bubble, which means one RTT message is complete. */
+ String BUBBLE_BREAKER = "\n\n";
+}
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreen.java b/java/com/android/incallui/rtt/protocol/RttCallScreen.java
new file mode 100644
index 000000000..afacbae48
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreen.java
@@ -0,0 +1,31 @@
+/*
+ * 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.protocol;
+
+import android.support.v4.app.Fragment;
+
+/** Interface for call RTT call module. */
+public interface RttCallScreen {
+
+ void onRttScreenStart();
+
+ void onRttScreenStop();
+
+ Fragment getRttCallScreenFragment();
+
+ String getCallId();
+}
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
new file mode 100644
index 000000000..e29c43d70
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegate.java
@@ -0,0 +1,29 @@
+/*
+ * 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.protocol;
+
+import android.content.Context;
+
+/** Callbacks from the module out to the container. */
+public interface RttCallScreenDelegate {
+
+ void initRttCallScreenDelegate(Context context, RttCallScreen rttCallScreen);
+
+ void onRttCallScreenUiReady();
+
+ void onRttCallScreenUiUnready();
+}
diff --git a/java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java
new file mode 100644
index 000000000..0dbcc9135
--- /dev/null
+++ b/java/com/android/incallui/rtt/protocol/RttCallScreenDelegateFactory.java
@@ -0,0 +1,23 @@
+/*
+ * 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.protocol;
+
+/** Callbacks from the module out to the container. */
+public interface RttCallScreenDelegateFactory {
+
+ RttCallScreenDelegate newRttCallScreenDelegate(RttCallScreen rttCallScreen);
+}