diff options
author | linyuh <linyuh@google.com> | 2018-05-31 20:59:05 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-06-01 18:19:51 -0700 |
commit | f85644637b808d6a88886e462c1f8fd5f53a6f2f (patch) | |
tree | 6ed1c44ef3a167b27693831b00037db65b8f056c | |
parent | f0d515573aa65c265ccb104ca982a5ccfbd0fa24 (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
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" |