summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlinyuh <linyuh@google.com>2018-05-31 20:59:05 -0700
committerCopybara-Service <copybara-piper@google.com>2018-06-01 18:19:51 -0700
commitf85644637b808d6a88886e462c1f8fd5f53a6f2f (patch)
tree6ed1c44ef3a167b27693831b00037db65b8f056c
parentf0d515573aa65c265ccb104ca982a5ccfbd0fa24 (diff)
Solve BiDi problem when phone number is concatenated with RTL-string
Solves BiDi problem that might cause phone number to be displayed incorrectly in the dialer. Issue might occur when a phone number is concatenated with a custom number label containing an RTL-string. Solved by changing affected labels from TextView to BidiTextView. Removed function spanDisplayNumber in BottomRow which are now obsolete. Updates the DialerBidiFormatter to prevent whitespace to be misplaced within a BidiTextView. BUG=78464687 TEST=Manual Public-Origin-Change-Id: I789a6f76a5ca805c03a437813ce627eef7a0bf2e Signed-off-by: Linyu He <linyuh@google.com> Author: Torbjorn Eklund <torbjorn.eklund@sony.com> Bug: 78464687 Test: Manual PiperOrigin-RevId: 198823629 Change-Id: Id35c3ebf514609b4a1fe10a7ae5a297bde7c7456
-rw-r--r--java/com/android/dialer/callcomposer/CallComposerActivity.java3
-rw-r--r--java/com/android/dialer/callcomposer/res/layout/call_composer_activity.xml2
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java2
-rwxr-xr-x[-rw-r--r--]java/com/android/dialer/calldetails/res/layout/contact_container.xml2
-rw-r--r--java/com/android/dialer/i18n/DialerBidiFormatter.java44
-rw-r--r--java/com/android/dialer/widget/DialerToolbar.java4
-rwxr-xr-x[-rw-r--r--]java/com/android/dialer/widget/res/layout/dialer_toolbar.xml2
-rw-r--r--java/com/android/incallui/contactgrid/BottomRow.java13
-rw-r--r--java/com/android/incallui/contactgrid/ContactGridManager.java3
-rw-r--r--java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_bottom_row.xml2
10 files changed, 52 insertions, 25 deletions
diff --git a/java/com/android/dialer/callcomposer/CallComposerActivity.java b/java/com/android/dialer/callcomposer/CallComposerActivity.java
index 49bc29c34..921bbbaea 100644
--- a/java/com/android/dialer/callcomposer/CallComposerActivity.java
+++ b/java/com/android/dialer/callcomposer/CallComposerActivity.java
@@ -78,6 +78,7 @@ import com.android.dialer.storage.StorageComponent;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.util.UriUtils;
import com.android.dialer.util.ViewUtil;
+import com.android.dialer.widget.BidiTextView;
import com.android.dialer.widget.DialerToolbar;
import com.android.dialer.widget.LockableViewPager;
import com.android.incallui.callpending.CallPendingActivity;
@@ -135,7 +136,7 @@ public class CallComposerActivity extends AppCompatActivity
private Long sessionId = Session.NO_SESSION_ID;
private TextView nameView;
- private TextView numberView;
+ private BidiTextView numberView;
private QuickContactBadge contactPhoto;
private RelativeLayout contactContainer;
private DialerToolbar toolbar;
diff --git a/java/com/android/dialer/callcomposer/res/layout/call_composer_activity.xml b/java/com/android/dialer/callcomposer/res/layout/call_composer_activity.xml
index 49d278f30..8b982b9dc 100644
--- a/java/com/android/dialer/callcomposer/res/layout/call_composer_activity.xml
+++ b/java/com/android/dialer/callcomposer/res/layout/call_composer_activity.xml
@@ -57,7 +57,7 @@
android:textColor="?android:attr/textColorPrimaryInverse"
android:textSize="@dimen/call_composer_name_text_size"/>
- <TextView
+ <com.android.dialer.widget.BidiTextView
android:id="@+id/phone_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java
index 4da7fa0dc..84a60c16e 100644
--- a/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java
@@ -54,7 +54,7 @@ public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
private final CallDetailsHeaderListener callDetailsHeaderListener;
private final ImageView callbackButton;
private final BidiTextView nameView;
- private final TextView numberView;
+ private final BidiTextView numberView;
private final TextView networkView;
private final QuickContactBadge contactPhoto;
private final Context context;
diff --git a/java/com/android/dialer/calldetails/res/layout/contact_container.xml b/java/com/android/dialer/calldetails/res/layout/contact_container.xml
index e918feb69..4df81f152 100644..100755
--- a/java/com/android/dialer/calldetails/res/layout/contact_container.xml
+++ b/java/com/android/dialer/calldetails/res/layout/contact_container.xml
@@ -51,7 +51,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/photo_text_margin"/>
- <TextView
+ <com.android.dialer.widget.BidiTextView
android:id="@+id/phone_number"
style="@style/Dialer.TextAppearance.Secondary.Ellipsize"
android:layout_width="wrap_content"
diff --git a/java/com/android/dialer/i18n/DialerBidiFormatter.java b/java/com/android/dialer/i18n/DialerBidiFormatter.java
index 4ebaa666c..e882e06c4 100644
--- a/java/com/android/dialer/i18n/DialerBidiFormatter.java
+++ b/java/com/android/dialer/i18n/DialerBidiFormatter.java
@@ -26,6 +26,7 @@ import com.google.auto.value.AutoValue;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* An enhanced version of {@link BidiFormatter} that can recognize a formatted phone number
@@ -40,6 +41,9 @@ public final class DialerBidiFormatter {
private DialerBidiFormatter() {}
+ // Regular expression that matches a single space in the beginning or end of a string.
+ private static final String REGEXP_SURROUNDING_SPACE = "^[ ]|[ ]$";
+
/**
* Divides the given text into segments, applies {@link BidiFormatter#unicodeWrap(CharSequence)}
* to each segment, and then reassembles the text.
@@ -65,19 +69,49 @@ public final class DialerBidiFormatter {
}
/**
- * Segments the given text using {@link Patterns#PHONE}.
+ * Segments the given text into a sequence of substrings using the following procedure.
+ *
+ * <ol>
+ * <li>Separate text matching {@link Patterns#PHONE} from others.
+ * <p>For example: "Mobile, +1 650-253-0000, 20 seconds" will be segmented into<br>
+ * {"Mobile, ", "+1 650-253-0000", ", 20 seconds"}
+ * <li>For each substring produced by the previous step, separate a single whitespace at the
+ * start/end of it from the rest of the substring.
+ * <p>For example, the first substring "Mobile, " will be segmented into {"Mobile,", " "}.
+ * </ol>
+ *
+ * <p>The final result of segmenting "Mobile, +1 650-253-0000, 20 seconds" is<br>
+ * {"Mobile,", " ", "+1 650-253-0000", ", 20 seconds"}.
*
- * <p>For example, "Mobile, +1 650-253-0000, 20 seconds" will be segmented into {"Mobile, ", "+1
- * 650-253-0000", ", 20 seconds"}.
+ * <p>The reason for singling out the whitespace at the start/end of a substring is to prevent it
+ * from being misplaced in RTL context.
*/
@VisibleForTesting
static List<CharSequence> segmentText(CharSequence text) {
Assert.checkArgument(!TextUtils.isEmpty(text));
+ // Separate text matching the phone number pattern from others.
+ List<CharSequence> segmentsSeparatingPhoneNumbers = segmentText(text, Patterns.PHONE);
+
+ // For each substring, separate a single whitespace at the start/end of it from the rest of the
+ // substring.
+ List<CharSequence> finalSegments = new ArrayList<>();
+ Pattern patternSurroundingSpace = Pattern.compile(REGEXP_SURROUNDING_SPACE);
+ for (CharSequence segment : segmentsSeparatingPhoneNumbers) {
+ finalSegments.addAll(segmentText(segment, patternSurroundingSpace));
+ }
+
+ return finalSegments;
+ }
+
+ /** Segments the given text into a sequence of substrings using the provided pattern. */
+ private static List<CharSequence> segmentText(CharSequence text, Pattern pattern) {
+ Assert.checkArgument(!TextUtils.isEmpty(text));
+
List<CharSequence> segments = new ArrayList<>();
- // Find the start index and the end index of each segment matching the phone number pattern.
- Matcher matcher = Patterns.PHONE.matcher(text.toString());
+ // Find the start index and the end index of each segment matching the pattern.
+ Matcher matcher = pattern.matcher(text.toString());
List<Range> segmentRanges = new ArrayList<>();
while (matcher.find()) {
segmentRanges.add(Range.newBuilder().setStart(matcher.start()).setEnd(matcher.end()).build());
diff --git a/java/com/android/dialer/widget/DialerToolbar.java b/java/com/android/dialer/widget/DialerToolbar.java
index 02ec8c02c..40dabe8bc 100644
--- a/java/com/android/dialer/widget/DialerToolbar.java
+++ b/java/com/android/dialer/widget/DialerToolbar.java
@@ -29,13 +29,13 @@ import com.android.dialer.theme.base.ThemeComponent;
public class DialerToolbar extends Toolbar {
private final TextView title;
- private final TextView subtitle;
+ private final BidiTextView subtitle;
public DialerToolbar(Context context, @Nullable AttributeSet attributeSet) {
super(context, attributeSet);
inflate(context, R.layout.dialer_toolbar, this);
title = (TextView) findViewById(R.id.title);
- subtitle = (TextView) findViewById(R.id.subtitle);
+ subtitle = (BidiTextView) findViewById(R.id.subtitle);
setElevation(getResources().getDimensionPixelSize(R.dimen.toolbar_elevation));
setBackgroundColor(ThemeComponent.get(context).theme().getColorPrimary());
diff --git a/java/com/android/dialer/widget/res/layout/dialer_toolbar.xml b/java/com/android/dialer/widget/res/layout/dialer_toolbar.xml
index a75176a22..3b4d1367e 100644..100755
--- a/java/com/android/dialer/widget/res/layout/dialer_toolbar.xml
+++ b/java/com/android/dialer/widget/res/layout/dialer_toolbar.xml
@@ -31,7 +31,7 @@
android:textColor="?android:attr/textColorPrimaryInverse"
style="@style/Dialer.TextAppearance.Header2"/>
- <TextView
+ <com.android.dialer.widget.BidiTextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/java/com/android/incallui/contactgrid/BottomRow.java b/java/com/android/incallui/contactgrid/BottomRow.java
index 7388c50a8..767d66668 100644
--- a/java/com/android/incallui/contactgrid/BottomRow.java
+++ b/java/com/android/incallui/contactgrid/BottomRow.java
@@ -18,9 +18,6 @@ package com.android.incallui.contactgrid;
import android.content.Context;
import android.support.annotation.Nullable;
-import android.telephony.PhoneNumberUtils;
-import android.text.BidiFormatter;
-import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import com.android.incallui.call.state.DialerCallState;
import com.android.incallui.incall.protocol.PrimaryCallState;
@@ -118,21 +115,15 @@ public class BottomRow {
return primaryInfo.location();
}
if (!primaryInfo.nameIsNumber() && !TextUtils.isEmpty(primaryInfo.number())) {
- CharSequence spannedNumber = spanDisplayNumber(primaryInfo.number());
if (primaryInfo.label() == null) {
- return spannedNumber;
+ return primaryInfo.number();
} else {
- return TextUtils.concat(primaryInfo.label(), " ", spannedNumber);
+ return TextUtils.concat(primaryInfo.label(), " ", primaryInfo.number());
}
}
return null;
}
- private static CharSequence spanDisplayNumber(String displayNumber) {
- return PhoneNumberUtils.createTtsSpannable(
- BidiFormatter.getInstance().unicodeWrap(displayNumber, TextDirectionHeuristics.LTR));
- }
-
private static boolean isIncoming(PrimaryCallState state) {
return state.state() == DialerCallState.INCOMING
|| state.state() == DialerCallState.CALL_WAITING;
diff --git a/java/com/android/incallui/contactgrid/ContactGridManager.java b/java/com/android/incallui/contactgrid/ContactGridManager.java
index 86d71141c..e375bd574 100644
--- a/java/com/android/incallui/contactgrid/ContactGridManager.java
+++ b/java/com/android/incallui/contactgrid/ContactGridManager.java
@@ -40,6 +40,7 @@ import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent;
import com.android.dialer.glidephotomanager.PhotoInfo;
import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.util.DrawableConverter;
+import com.android.dialer.widget.BidiTextView;
import com.android.incallui.incall.protocol.ContactPhotoType;
import com.android.incallui.incall.protocol.PrimaryCallState;
import com.android.incallui.incall.protocol.PrimaryInfo;
@@ -77,7 +78,7 @@ public class ContactGridManager {
private final TextView forwardedNumberView;
private final ImageView spamIconImageView;
private final ViewAnimator bottomTextSwitcher;
- private final TextView bottomTextView;
+ private final BidiTextView bottomTextView;
private final Chronometer bottomTimerView;
private final Space topRowSpace;
private int avatarSize;
diff --git a/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_bottom_row.xml b/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_bottom_row.xml
index ce355ea2d..73db41314 100644
--- a/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_bottom_row.xml
+++ b/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_bottom_row.xml
@@ -53,7 +53,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:measureAllChildren="false">
- <TextView
+ <com.android.dialer.widget.BidiTextView
android:id="@+id/contactgrid_bottom_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"