TextViewTest.java revision 6beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9
1fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su/*
2fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Copyright (C) 2008 The Android Open Source Project
3fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *
4fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Licensed under the Apache License, Version 2.0 (the "License");
5fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * you may not use this file except in compliance with the License.
6fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * You may obtain a copy of the License at
7fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *
8fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *      http://www.apache.org/licenses/LICENSE-2.0
9fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su *
10fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Unless required by applicable law or agreed to in writing, software
11fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * distributed under the License is distributed on an "AS IS" BASIS,
12fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * See the License for the specific language governing permissions and
14fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * limitations under the License.
15fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su */
16fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
17fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Supackage android.widget.cts;
18fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
19fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.app.Activity;
20fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.app.Instrumentation;
21fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.app.Instrumentation.ActivityMonitor;
22354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.content.Context;
23fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.content.Intent;
242751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonakaimport android.content.pm.PackageManager;
25fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.content.res.ColorStateList;
26938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport android.content.res.Resources;
27fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.content.res.Resources.NotFoundException;
285bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinirimport android.cts.util.KeyEventUtil;
290162547f44173f0604d8a80143c128d9892460a1Kristian Monsenimport android.cts.util.PollingCheck;
30d82745ff4a8b174f7be1258fd329dedc52ce58bbChenjie Luoimport android.cts.util.WidgetTestUtils;
31fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Color;
32fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Paint;
33afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.graphics.Path;
34fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukaiimport android.graphics.PorterDuff;
35fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Rect;
36afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.graphics.RectF;
37fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.Typeface;
38fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.drawable.BitmapDrawable;
39ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.graphics.drawable.ColorDrawable;
40fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.graphics.drawable.Drawable;
41fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.net.Uri;
42fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.os.Bundle;
43354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.os.Handler;
44265b3d21959154e9a6ce0fdd888249f3699b7bddYohei Yukawaimport android.os.LocaleList;
45354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.os.Looper;
465b51f77b99861d48fec1c327252416f726b3b01aJames Cookimport android.os.Parcelable;
47354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.os.ResultReceiver;
4857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.os.SystemClock;
49fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.test.ActivityInstrumentationTestCase2;
5072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.test.TouchUtils;
51fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.test.UiThreadTest;
5298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinirimport android.test.suitebuilder.annotation.MediumTest;
53ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.test.suitebuilder.annotation.SmallTest;
54fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Editable;
55fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.InputFilter;
56fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.InputType;
57fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Layout;
58fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Selection;
59fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.Spannable;
60fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.SpannableString;
61ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.text.Spanned;
62fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.TextPaint;
63fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.TextUtils;
64fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.TextUtils.TruncateAt;
65afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.text.TextWatcher;
66fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.ArrowKeyMovementMethod;
67fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DateKeyListener;
68fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DateTimeKeyListener;
69fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DialerKeyListener;
70fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.DigitsKeyListener;
71fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.KeyListener;
72fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.LinkMovementMethod;
73fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.MovementMethod;
74fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.PasswordTransformationMethod;
75fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.QwertyKeyListener;
76fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.SingleLineTransformationMethod;
77fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.TextKeyListener;
78afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.text.method.TextKeyListener.Capitalize;
79fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.TimeKeyListener;
80fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.method.TransformationMethod;
8157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.text.style.ClickableSpan;
8298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinirimport android.text.style.ImageSpan;
83fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.style.URLSpan;
84ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagiimport android.text.style.UnderlineSpan;
85fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.text.util.Linkify;
86fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.util.DisplayMetrics;
87fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.util.TypedValue;
88ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport android.view.ActionMode;
89fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.ContextMenu;
90afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.view.ContextMenu.ContextMenuInfo;
91fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.Gravity;
9257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.view.InputDevice;
93fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.KeyEvent;
9432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagiimport android.view.Menu;
9557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.view.MotionEvent;
9657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarriimport android.view.PointerIcon;
97fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.view.View;
98afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsuimport android.view.ViewGroup;
9932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagiimport android.view.accessibility.AccessibilityNodeInfo;
10072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.BaseInputConnection;
10171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagiimport android.view.inputmethod.CorrectionInfo;
10272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.EditorInfo;
10372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.ExtractedText;
10472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubachimport android.view.inputmethod.ExtractedTextRequest;
105c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cookimport android.view.inputmethod.InputConnection;
106354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.view.inputmethod.InputMethodManager;
107c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunneimport android.widget.EditText;
108bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsuimport android.widget.FrameLayout;
10962808562ee0218f6ea3c07d333f7a65fc57c122fBrian Muramatsuimport android.widget.LinearLayout;
110354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikovimport android.widget.ScrollView;
111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.widget.Scroller;
112fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.widget.TextView;
113fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport android.widget.TextView.BufferType;
114938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport android.widget.cts.util.TestUtils;
11541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikovimport android.widget.cts.util.ViewTestUtils;
116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
117938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport org.mockito.invocation.InvocationOnMock;
118ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levienimport org.xmlpull.v1.XmlPullParserException;
119ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
120fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Suimport java.io.IOException;
121b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonakaimport java.util.Locale;
122fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
123938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport static org.mockito.Matchers.any;
124938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikovimport static org.mockito.Mockito.*;
125938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
126fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su/**
127fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su * Test {@link TextView}.
128fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su */
1294ca04c0729a0e810b5af16edcd52bb8cb59bf55eChenjie Luopublic class TextViewTest extends ActivityInstrumentationTestCase2<TextViewCtsActivity> {
130fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
131fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private TextView mTextView;
132fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private Activity mActivity;
133fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private Instrumentation mInstrumentation;
134fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static final String LONG_TEXT = "This is a really long string which exceeds "
1357375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "the width of the view. New devices have a much larger screen which "
1367375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "actually enables long strings to be displayed with no fading. "
1377375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "I have made this string longer to fix this case. If you are correcting "
1387375565c2caf62392b32049cafb7df0730373794Gilles Debunne            + "this text, I would love to see the kind of devices you guys now use!";
139fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static final long TIMEOUT = 5000;
14022d40a1fcc078329a7e5a34ff5eeadeca9c70d49Kenny Root    private CharSequence mTransformedText;
1415bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir    private KeyEventUtil mKeyEventUtil;
142354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    private Handler mHandler = new Handler(Looper.getMainLooper());
143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
144fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public TextViewTest() {
145a3e5fa456a01c74b91a5d66981433db598bcc9a7Agatha Man        super("android.widget.cts", TextViewCtsActivity.class);
146fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
147fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
148fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @Override
149fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    protected void setUp() throws Exception {
150fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        super.setUp();
151fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity = getActivity();
152938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation = getInstrumentation();
1545bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil = new KeyEventUtil(mInstrumentation);
155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
156fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
15728715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    /**
1586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * Promotes the TextView to editable and places focus in it to allow simulated typing. Used in
1596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * test methods annotated with {@link android.test.UiThreadTest}.
16028715a6877392e4e63cb2b0170c1592fb50079dcJames Cook     */
16128715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    private void initTextViewForTyping() {
1626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView = findTextView(R.id.textview_text);
1636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
1646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("", BufferType.EDITABLE);
1656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.requestFocus();
1666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    }
1676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
1686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    /**
1696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * Used in test methods that can not entirely be run on the UiThread (e.g: tests that need to
1706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     * emulate touches and/or key presses).
1716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu     */
1726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    private void initTextViewForTypingOnUiThread() {
1736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(this::initTextViewForTyping);
17428715a6877392e4e63cb2b0170c1592fb50079dcJames Cook        mInstrumentation.waitForIdleSync();
17528715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
17628715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
177fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testConstructor() {
178fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        new TextView(mActivity);
179fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
180fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        new TextView(mActivity, null);
181fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
182938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        new TextView(mActivity, null, android.R.attr.textViewStyle);
183938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
184f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_TextView);
185f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov
186f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_TextView);
187f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov
188f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_Material_TextView);
189f0b8eb2d36b704834dd594c9eebe7f7134a94b40Kirill Grouchnikov
190938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        new TextView(mActivity, null, 0, android.R.style.Widget_Material_Light_TextView);
191fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
192fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
193fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
194fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessText() {
195fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
196fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
197fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String expected = mActivity.getResources().getString(R.string.text_view_hello);
198fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(expected);
199fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, tv.getText().toString());
200fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
201fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(null);
202fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
203fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
204fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
205fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetLineHeight() {
206fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
207fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineHeight() > 0);
208fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
209fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLineSpacing(1.2f, 1.5f);
210fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineHeight() > 0);
211fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
212fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
213fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetLayout() {
2146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
2156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
2166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.CENTER);
217fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
218fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
219fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView.getLayout());
220fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
221fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TestLayoutRunnable runnable = new TestLayoutRunnable(mTextView) {
222fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            public void run() {
223fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                // change the text of TextView.
224fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.setText("Hello, Android!");
225fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveLayout();
226fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            }
227fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        };
228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.runOnUiThread(runnable);
229fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(runnable.getLayout());
231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView.getLayout());
232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessKeyListener() {
2356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView = findTextView(R.id.textview_text));
236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getKeyListener());
239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
240fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final KeyListener digitsKeyListener = DigitsKeyListener.getInstance();
241fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setKeyListener(digitsKeyListener));
243fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(digitsKeyListener, mTextView.getKeyListener());
245fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
246fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final QwertyKeyListener qwertyKeyListener
247fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                = QwertyKeyListener.getInstance(false, Capitalize.NONE);
2486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setKeyListener(qwertyKeyListener));
249fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
250fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(qwertyKeyListener, mTextView.getKeyListener());
251fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
252fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
253fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessMovementMethod() {
254fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence LONG_TEXT = "Scrolls the specified widget to the specified "
255fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + "coordinates, except constrains the X scrolling position to the horizontal "
256fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + "regions of the text that will be visible after scrolling to "
257fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + "the specified Y position.";
258fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int selectionStart = 10;
259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int selectionEnd = LONG_TEXT.length();
260fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final MovementMethod movementMethod = ArrowKeyMovementMethod.getInstance();
2616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
2626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
2636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setMovementMethod(movementMethod);
2646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(LONG_TEXT, BufferType.EDITABLE);
2656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Editable) mTextView.getText(),
2666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    selectionStart, selectionEnd);
2676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
269fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
270fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
271fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(movementMethod, mTextView.getMovementMethod());
272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
273fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
27403818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
275fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                KeyEvent.KEYCODE_DPAD_UP);
276fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the selection has been removed.
277fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
278fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionEnd(mTextView.getText()));
279fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
2816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setMovementMethod(null);
2826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Editable) mTextView.getText(),
2836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    selectionStart, selectionEnd);
2846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
285fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
288fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getMovementMethod());
289fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
290fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
29103818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
292fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                KeyEvent.KEYCODE_DPAD_UP);
293fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the selection will not be changed.
294fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
295fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
296fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
297fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
298fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testLength() {
300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
302fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String content = "This is content";
303fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(content);
304fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(content.length(), mTextView.length());
305fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
306fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("");
307fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.length());
308fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(null);
310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.length());
311fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
313fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
314fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessGravity() {
315fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_gravity);
316fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_default);
3184bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.TOP | Gravity.START, mTextView.getGravity());
319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_bottom);
3214bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.BOTTOM | Gravity.START, mTextView.getGravity());
322fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
323fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_right);
324fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.TOP | Gravity.RIGHT, mTextView.getGravity());
325fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_center);
327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.CENTER, mTextView.getGravity());
328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
329fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_fill);
330fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.FILL, mTextView.getGravity());
331fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
332fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.gravity_center_vertical_right);
333fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.CENTER_VERTICAL | Gravity.RIGHT, mTextView.getGravity());
334fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
336fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, mTextView.getGravity());
337fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.FILL);
338fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.FILL, mTextView.getGravity());
339fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.CENTER);
340fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.CENTER, mTextView.getGravity());
341fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
342fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.NO_GRAVITY);
3434bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.TOP | Gravity.START, mTextView.getGravity());
344fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
345fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.RIGHT);
346fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Gravity.TOP | Gravity.RIGHT, mTextView.getGravity());
347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.FILL_VERTICAL);
3494bb7d555a927c5f7a8747fdd85f7c94e1c0d2f19Fabrice Di Meglio        assertEquals(Gravity.FILL_VERTICAL | Gravity.START, mTextView.getGravity());
350fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //test negative input value.
352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(-1);
353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getGravity());
354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessAutoLinkMask() {
357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
358fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text1 =
359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new SpannableString("URL: http://www.google.com. mailto: account@gmail.com");
3606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
3616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setAutoLinkMask(Linkify.ALL);
3626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text1, BufferType.EDITABLE);
363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.ALL, mTextView.getAutoLinkMask());
366fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
367fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Spannable spanString = (Spannable) mTextView.getText();
368fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        URLSpan[] spans = spanString.getSpans(0, spanString.length(), URLSpan.class);
369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(spans);
370fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, spans.length);
371fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("http://www.google.com", spans[0].getURL());
372fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("mailto:account@gmail.com", spans[1].getURL());
373fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text2 =
375fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            new SpannableString("name: Jack. tel: +41 44 800 8999");
3766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
3776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setAutoLinkMask(Linkify.PHONE_NUMBERS);
3786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text2, BufferType.EDITABLE);
379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
380fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
381fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.PHONE_NUMBERS, mTextView.getAutoLinkMask());
382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
383fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spanString = (Spannable) mTextView.getText();
384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = spanString.getSpans(0, spanString.length(), URLSpan.class);
385fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(spans);
386fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, spans.length);
387fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("tel:+41448008999", spans[0].getURL());
388fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
389fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(R.layout.textview_autolink);
390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 1 for web, 2 for email, 4 for phone, 7 for all(web|email|phone)
391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, getAutoLinkMask(R.id.autolink_default));
392fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.WEB_URLS, getAutoLinkMask(R.id.autolink_web));
393fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.EMAIL_ADDRESSES, getAutoLinkMask(R.id.autolink_email));
394fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.PHONE_NUMBERS, getAutoLinkMask(R.id.autolink_phone));
395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.ALL, getAutoLinkMask(R.id.autolink_all));
396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES,
397fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound1));
398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.WEB_URLS | Linkify.PHONE_NUMBERS,
399fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound2));
400fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS,
401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound3));
402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Linkify.PHONE_NUMBERS | Linkify.ALL,
403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                getAutoLinkMask(R.id.autolink_compound4));
404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
405fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
406fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessTextSize() {
407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 20f);
411fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 20f, metrics),
412fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
413fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
414fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20f);
415fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20f, metrics),
416fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
417fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
418fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f);
419fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, metrics),
420fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
421fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
422fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // setTextSize by default unit "sp"
423fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(20f);
424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, metrics),
425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
426fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
427fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextSize(200f);
428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 200f, metrics),
429fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTextSize(), 0.01f);
430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
431fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessTextColor() {
433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
434fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(Color.GREEN);
436fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.GREEN, mTextView.getCurrentTextColor());
437fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.GREEN), mTextView.getTextColors());
438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
439fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(Color.BLACK);
440fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getCurrentTextColor());
441fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.BLACK), mTextView.getTextColors());
442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
443fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(Color.RED);
444fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.RED, mTextView.getCurrentTextColor());
445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.RED), mTextView.getTextColors());
446fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
447fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using ColorStateList
448fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
449fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ColorStateList colors = new ColorStateList(new int[][] {
450fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { android.R.attr.state_focused}, new int[0] },
451fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { Color.rgb(0, 255, 0), Color.BLACK });
452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextColor(colors);
453fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(colors, mTextView.getTextColors());
454fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getCurrentTextColor());
455fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
456fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // exceptional
457fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
458fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setTextColor(null);
459fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should thrown exception if the colors is null");
460fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e){
461fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
463fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
464325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette    public void testGetTextColor() {
465325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        // TODO: How to get a suitable TypedArray to test this method.
466325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette
467325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        try {
468325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette            TextView.getTextColor(mActivity, null, -1);
469325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette            fail("There should be a NullPointerException thrown out.");
470325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        } catch (NullPointerException e) {
471325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette        }
472325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette    }
473325d45563875cb6915e40070f3f687a3d92566f2Alan Viverette
474354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    public void testAccessHighlightColor() {
475354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
476354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
477354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> {
478354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            textView.setTextIsSelectable(true);
479354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            textView.setText("abcd", BufferType.EDITABLE);
480354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            textView.setHighlightColor(Color.BLUE);
481354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        });
482354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
483354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
484354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(textView.isTextSelectable());
485354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(Color.BLUE, textView.getHighlightColor());
486354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
487354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Long click on the text selects all text and shows selection handlers. The view has an
488354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // attribute layout_width="wrap_content", so clicked location (the center of the view)
489354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // should be on the text.
490354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        TouchUtils.longClickView(this, textView);
491fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
492354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // At this point the entire content of our TextView should be selected and highlighted
493354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // with blue. Now change the highlight to red while the selection is still on.
494354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setHighlightColor(Color.RED));
495354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
496354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
497354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(Color.RED, textView.getHighlightColor());
498354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.equals("abcd", textView.getText()));
499354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
500354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Remove the selection
501354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> Selection.removeSelection((Spannable) textView.getText()));
502354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
503354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
504354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // And switch highlight to green after the selection has been removed
505354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setHighlightColor(Color.GREEN));
506354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
507354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
508354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(Color.GREEN, textView.getHighlightColor());
509354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.equals("abcd", textView.getText()));
510fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
511fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
513fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetShadowLayer() {
5146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test values
5156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final MockTextView mockTextView = new MockTextView(mActivity);
5166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
5176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(1.0f, 0.3f, 0.4f, Color.CYAN);
5186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(Color.CYAN, mockTextView.getShadowColor());
5196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0.3f, mockTextView.getShadowDx());
5206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0.4f, mockTextView.getShadowDy());
5216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(1.0f, mockTextView.getShadowRadius());
522fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
523fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // shadow is placed to the left and below the text
5246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(1.0f, 0.3f, 0.3f, Color.CYAN);
5256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(mockTextView.isPaddingOffsetRequired());
5266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getLeftPaddingOffset());
5276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getTopPaddingOffset());
5286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(1, mockTextView.getRightPaddingOffset());
5296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(1, mockTextView.getBottomPaddingOffset());
530fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
531fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // shadow is placed to the right and above the text
5326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(1.0f, -0.8f, -0.8f, Color.CYAN);
5336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(mockTextView.isPaddingOffsetRequired());
5346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mockTextView.getLeftPaddingOffset());
5356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mockTextView.getTopPaddingOffset());
5366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getRightPaddingOffset());
5376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getBottomPaddingOffset());
538fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
539fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // no shadow
5406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.setShadowLayer(0.0f, 0.0f, 0.0f, Color.CYAN);
5416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(mockTextView.isPaddingOffsetRequired());
5426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getLeftPaddingOffset());
5436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getTopPaddingOffset());
5446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getRightPaddingOffset());
5456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, mockTextView.getBottomPaddingOffset());
546fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
547fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
548fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
549fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetSelectAllOnFocus() {
550fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_selectallonfocus);
551fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String content = "This is the content";
552fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String blank = "";
553fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.selectAllOnFocus_default);
554fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(blank, BufferType.SPANNABLE);
555fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
556fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
557fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
558fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
559fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
560fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
561fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
562fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
563fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
564fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(content, BufferType.SPANNABLE);
565fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(true);
566fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
567fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
568fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
569fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
570fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
571fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
572fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
573fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(content.length(), mTextView.getSelectionEnd());
574fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
575fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 0);
576fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(false);
577fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
578fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
579fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
580fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
581fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
582fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
583fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
584fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionEnd());
585fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
586fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(blank, BufferType.SPANNABLE);
587fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(true);
588fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
589fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
590fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
591fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
592fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
593fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
594fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
595fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(blank.length(), mTextView.getSelectionEnd());
596fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
597fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 0);
598fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setSelectAllOnFocus(false);
599fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change the focus
600fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        findTextView(R.id.selectAllOnFocus_dummy).requestFocus();
601fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.isFocused());
602fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestFocus();
603fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.isFocused());
604fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
605fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
606fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionEnd());
607fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
608fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
609fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetPaint() {
610fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
611fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextPaint tp = mTextView.getPaint();
612fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(tp);
613fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
614fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaintFlags(), tp.getFlags());
615fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
616fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
617fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
618fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessLinksClickable() {
619fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_hint_linksclickable_freezestext);
620fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
621fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_linksClickable_freezesText_default);
622fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLinksClickable());
623fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
624fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.linksClickable_true);
625fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLinksClickable());
626fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
627fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.linksClickable_false);
628fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getLinksClickable());
629fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
630fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinksClickable(false);
631fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getLinksClickable());
632fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
633fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinksClickable(true);
634fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLinksClickable());
635fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
636fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getMovementMethod());
637fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
638fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text = new SpannableString("name: Jack. tel: +41 44 800 8999");
639fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
640fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setAutoLinkMask(Linkify.PHONE_NUMBERS);
641fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
642fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
643fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Movement method will be automatically set to LinkMovementMethod
644fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getMovementMethod() instanceof LinkMovementMethod);
645fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
646fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
647fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessHintTextColor() {
648fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
649fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using int values
650fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
651fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(Color.GREEN);
652fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.GREEN, mTextView.getCurrentHintTextColor());
653fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.GREEN), mTextView.getHintTextColors());
654fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
655fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(Color.BLUE);
656fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.BLUE), mTextView.getHintTextColors());
657fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLUE, mTextView.getCurrentHintTextColor());
658fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
659fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(Color.RED);
660fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.RED), mTextView.getHintTextColors());
661fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.RED, mTextView.getCurrentHintTextColor());
662fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
663fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using ColorStateList
664fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
665fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ColorStateList colors = new ColorStateList(new int[][] {
666fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { android.R.attr.state_focused}, new int[0] },
667fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { Color.rgb(0, 255, 0), Color.BLACK });
668fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(colors);
669fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(colors, mTextView.getHintTextColors());
670fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getCurrentHintTextColor());
671fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
672fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // exceptional
673fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHintTextColor(null);
674fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getHintTextColors());
675fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCurrentTextColor(), mTextView.getCurrentHintTextColor());
676fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
677fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
678fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessLinkTextColor() {
679fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
680fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
681fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(Color.GRAY);
682fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.GRAY), mTextView.getLinkTextColors());
683fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.GRAY, mTextView.getPaint().linkColor);
684fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
685fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(Color.YELLOW);
686fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.YELLOW), mTextView.getLinkTextColors());
687fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.YELLOW, mTextView.getPaint().linkColor);
688fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
689fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(Color.WHITE);
690fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(ColorStateList.valueOf(Color.WHITE), mTextView.getLinkTextColors());
691fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.WHITE, mTextView.getPaint().linkColor);
692fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
693fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ColorStateList colors = new ColorStateList(new int[][] {
694fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { android.R.attr.state_expanded}, new int[0] },
695fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new int[] { Color.rgb(0, 255, 0), Color.BLACK });
696fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(colors);
697fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(colors, mTextView.getLinkTextColors());
698fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getPaint().linkColor);
699fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
700fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLinkTextColor(null);
701fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getLinkTextColors());
702fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Color.BLACK, mTextView.getPaint().linkColor);
703fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
704fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
705fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessPaintFlags() {
706fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
70753959f211c113aa7b2a2ebaf80e10b79ddcccef1Victoria Lease        assertEquals(Paint.DEV_KERN_TEXT_FLAG | Paint.EMBEDDED_BITMAP_TEXT_FLAG
70853959f211c113aa7b2a2ebaf80e10b79ddcccef1Victoria Lease                | Paint.ANTI_ALIAS_FLAG, mTextView.getPaintFlags());
709fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
710fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);
711fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Paint.UNDERLINE_TEXT_FLAG | Paint.FAKE_BOLD_TEXT_FLAG,
712fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getPaintFlags());
713fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
714fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.LINEAR_TEXT_FLAG);
715fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Paint.STRIKE_THRU_TEXT_FLAG | Paint.LINEAR_TEXT_FLAG,
716fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getPaintFlags());
717fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
718fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
7206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testHeight() {
721fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
7226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalHeight = mTextView.getHeight();
723fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test setMaxHeight
7256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        int newHeight = originalHeight + 1;
7266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
727fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
7286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
729fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight - 1;
7316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
7326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
7336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
734fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = -1;
7366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
737fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getHeight());
7386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
739fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = Integer.MAX_VALUE;
7416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxHeight(newHeight);
742fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
7436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
744fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test setMinHeight
7466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight + 1;
7476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinHeight(newHeight);
7486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
7496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
750fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight - 1;
7526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinHeight(newHeight);
753fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
7546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
755fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = -1;
7576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinHeight(newHeight);
758fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
7596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
760fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // reset min and max height
762fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinHeight(0);
763fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxHeight(Integer.MAX_VALUE);
764fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // test setHeight
7666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight + 1;
7676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setHeight(newHeight);
7686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
7696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
7706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
7716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
7726a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = originalHeight - 1;
7736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setHeight(newHeight);
7746a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getHeight());
7756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
7766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
7776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
7786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newHeight = -1;
7796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setHeight(newHeight);
780fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getHeight());
7816a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMaxHeight());
7826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newHeight, mTextView.getMinHeight());
783fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
784fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setHeight(originalHeight);
785fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalHeight, mTextView.getHeight());
7866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(originalHeight, mTextView.getMaxHeight());
7876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(originalHeight, mTextView.getMinHeight());
788fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
7896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // setting max/min lines should cause getMaxHeight/getMinHeight to return -1
7906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxLines(2);
7916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting maxLines should return -1 fir maxHeight",
7926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                -1, mTextView.getMaxHeight());
7936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
7946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinLines(1);
7956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting minLines should return -1 for minHeight",
7966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                -1, mTextView.getMinHeight());
7976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
7986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
7996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
8006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testWidth() {
8016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = findTextView(R.id.textview_text);
8026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        int originalWidth = mTextView.getWidth();
8036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        int newWidth = mTextView.getWidth() / 8;
8056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setWidth(newWidth);
8066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMaxWidth());
8086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
809fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
810fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Min Width
8116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth + 1;
8126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinWidth(newWidth);
813fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
816fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth - 1;
818fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinWidth(originalWidth - 1);
8199c3b459233e30a88d24e7178cc7514731fa56f55Brian Muramatsu        assertEquals(2, mTextView.getLineCount());
8206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
822fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
823fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Width
8246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth + 1;
8256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setWidth(newWidth);
826fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMaxWidth());
8296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
830fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        newWidth = originalWidth - 1;
8326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setWidth(newWidth);
8339c3b459233e30a88d24e7178cc7514731fa56f55Brian Muramatsu        assertEquals(2, mTextView.getLineCount());
8346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getWidth());
8356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMaxWidth());
8366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(newWidth, mTextView.getMinWidth());
8376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // setting ems should cause getMaxWidth/getMinWidth to return -1
8396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setEms(1);
8406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMaxWidth());
8416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMinWidth());
842fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
843fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
845fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetMinEms() {
846fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
847fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8489c3b459233e30a88d24e7178cc7514731fa56f55Brian Muramatsu
8496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalWidth = mTextView.getWidth();
8506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalEms = originalWidth / mTextView.getLineHeight();
851fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
852fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinEms(originalEms + 1);
853fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
85498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
85598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMinEms());
856fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
857fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinEms(originalEms - 1);
858fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalWidth, mTextView.getWidth());
85998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
86098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMinEms());
8616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMinWidth(1);
8636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mTextView.getMinEms());
864fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
865fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
867fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetMaxEms() {
868fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
869fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalWidth = mTextView.getWidth();
8726a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalEms = originalWidth / mTextView.getLineHeight();
873fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
874fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxEms(originalEms + 1);
875fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
876fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(originalWidth, mTextView.getWidth());
87798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
87898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMaxEms());
879fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
880fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxEms(originalEms - 1);
881fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(1 < mTextView.getLineCount());
8826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
88398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
88498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMaxEms());
8856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
8866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        setMaxWidth(originalWidth);
8876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(-1, mTextView.getMaxEms());
888fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
889fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
8906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
891fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetEms() {
892fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
893fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("check height", 1, mTextView.getLineCount());
8946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalWidth = mTextView.getWidth();
8956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int originalEms = originalWidth / mTextView.getLineHeight();
896fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
897fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setEms(originalEms + 1);
898fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
8996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
90098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
90198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
90298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMinEms());
90398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms + 1, mTextView.getMaxEms());
904fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
905fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setEms(originalEms - 1);
906fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((1 < mTextView.getLineCount()));
9076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
90898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinWidth());
90998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxWidth());
91098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMinEms());
91198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalEms - 1, mTextView.getMaxEms());
912fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
913fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
914fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetLineSpacing() {
915fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
916fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int originalLineHeight = mTextView.getLineHeight();
917fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
918fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // normal
919fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        float add = 1.2f;
920fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        float mult = 1.4f;
921fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
92292e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
923fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = 0.0f;
924fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = 1.4f;
925fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
92692e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
927fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
928fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // abnormal
929fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = -1.2f;
930fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = 1.4f;
931fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
93292e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
933fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = -1.2f;
934fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = -1.4f;
935fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
93692e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
937fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = 1.2f;
938fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = 0.0f;
939fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
94092e24e51c89759b176c38a0ceaa94ae7b23c1930Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
941fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
942fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // edge
943fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = Float.MIN_VALUE;
944fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = Float.MIN_VALUE;
945fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
946ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        assertEquals(Math.round(originalLineHeight * mult + add), mTextView.getLineHeight());
947ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette
948ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        // edge case where the behavior of Math.round() deviates from
949ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        // FastMath.round(), requiring us to use an explicit 0 value
950fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        add = Float.MAX_VALUE;
951fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mult = Float.MAX_VALUE;
952fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLineSpacing(add, mult);
953ae663de2120beb9de33d57e2c0ebfa6662e1d9f8Alan Viverette        assertEquals(0, mTextView.getLineHeight());
954fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
955fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
956ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien    public void testSetElegantLineHeight() {
957ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mTextView = findTextView(R.id.textview_text);
958ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertFalse(mTextView.getPaint().isElegantTextHeight());
9596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
9606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setWidth(mTextView.getWidth() / 3);
9616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
9626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
963ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        });
964ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mInstrumentation.waitForIdleSync();
965ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
966ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        int oldHeight = mTextView.getHeight();
9676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setElegantTextHeight(true));
968ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mInstrumentation.waitForIdleSync();
969ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
970ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getPaint().isElegantTextHeight());
971ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getHeight() > oldHeight);
972ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
9736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setElegantTextHeight(false));
974ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        mInstrumentation.waitForIdleSync();
975ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertFalse(mTextView.getPaint().isElegantTextHeight());
976ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getHeight() == oldHeight);
977ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien    }
978ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien
979fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testInstanceState() {
980fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
981fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
982fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
983fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessFreezesText() throws Throwable {
984fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(R.layout.textview_hint_linksclickable_freezestext);
985fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
986fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_linksClickable_freezesText_default);
987fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getFreezesText());
988fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
989fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_true);
990fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getFreezesText());
991fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
992fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_false);
993fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getFreezesText());
994fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
995fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setFreezesText(false);
996fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getFreezesText());
997fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
998fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final CharSequence text = "Hello, TextView.";
9996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setText(text));
1000fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
1001fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1002fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final URLSpan urlSpan = new URLSpan("ctstest://TextView/test");
100372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // TODO: How to simulate the TextView in frozen icicles.
1004fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Instrumentation instrumentation = getInstrumentation();
1005fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        ActivityMonitor am = instrumentation.addMonitor(MockURLSpanTestActivity.class.getName(),
1006fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                null, false);
1007fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
10086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
10096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Uri uri = Uri.parse(urlSpan.getURL());
10106beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
10116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.startActivity(intent);
1012fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
1013fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1014fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Activity newActivity = am.waitForActivityWithTimeout(TIMEOUT);
1015fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(newActivity);
1016fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        newActivity.finish();
101772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        instrumentation.removeMonitor(am);
1018fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text of TextView is removed.
1019fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_false);
102072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
102172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(text.toString(), mTextView.getText().toString());
1022fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1023fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setFreezesText(true);
1024fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getFreezesText());
1025fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
10266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setText(text));
1027fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
102872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // TODO: How to simulate the TextView in frozen icicles.
1029fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        am = instrumentation.addMonitor(MockURLSpanTestActivity.class.getName(),
1030fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                null, false);
1031fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
10326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
10336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Uri uri = Uri.parse(urlSpan.getURL());
10346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
10356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.startActivity(intent);
1036fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
1037fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
103807b9d3406e116f2f6b92932925783eed79503de0Mist Liao        Activity oldActivity = newActivity;
103907b9d3406e116f2f6b92932925783eed79503de0Mist Liao        while (true) {
104007b9d3406e116f2f6b92932925783eed79503de0Mist Liao            newActivity = am.waitForActivityWithTimeout(TIMEOUT);
104107b9d3406e116f2f6b92932925783eed79503de0Mist Liao            assertNotNull(newActivity);
104207b9d3406e116f2f6b92932925783eed79503de0Mist Liao            if (newActivity != oldActivity) {
104307b9d3406e116f2f6b92932925783eed79503de0Mist Liao                break;
104407b9d3406e116f2f6b92932925783eed79503de0Mist Liao            }
104507b9d3406e116f2f6b92932925783eed79503de0Mist Liao        }
1046fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        newActivity.finish();
104772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        instrumentation.removeMonitor(am);
1048fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text of TextView is still there.
1049fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.freezesText_false);
1050fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text.toString(), mTextView.getText().toString());
1051fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1052fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1053fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetEditableFactory() {
1054fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1055fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "sample";
1056fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
105798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final Editable.Factory mockEditableFactory = spy(new Editable.Factory());
105898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        doCallRealMethod().when(mockEditableFactory).newEditable(any(CharSequence.class));
105998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setEditableFactory(mockEditableFactory);
106098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov
1061fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text);
106298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
1063fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
106498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1065fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.SPANNABLE);
106698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
1067fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
106898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1069fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.NORMAL);
107098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
1071fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
107298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1073fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
107498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, times(1)).newEditable(text);
1075fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1076fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setKeyListener(DigitsKeyListener.getInstance());
107798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockEditableFactory);
1078fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
107998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockEditableFactory, times(1)).newEditable(text);
1080fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1081fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1082fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setEditableFactory(null);
1083fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("The factory can not set to null!");
1084fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
1085fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1086fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1087fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1088fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetSpannableFactory() {
1089fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1090fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "sample";
1091fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
109298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final Spannable.Factory mockSpannableFactory = spy(new Spannable.Factory());
109398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        doCallRealMethod().when(mockSpannableFactory).newSpannable(any(CharSequence.class));
109498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setSpannableFactory(mockSpannableFactory);
109598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov
1096fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text);
109798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
1098fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
109998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1100fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.EDITABLE);
110198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
1102fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
110398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1104fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.NORMAL);
110598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
1106fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
110798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1108fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.SPANNABLE);
110998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, times(1)).newSpannable(text);
1110fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setMovementMethod(LinkMovementMethod.getInstance());
111298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockSpannableFactory);
1113fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.NORMAL);
111498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockSpannableFactory, times(1)).newSpannable(text);
1115fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1117fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setSpannableFactory(null);
1118fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("The factory can not set to null!");
1119fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
1120fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1121fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1122fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1123fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testTextChangedListener() {
1124fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1125fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextWatcher watcher0 = new MockTextWatcher();
1126fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextWatcher watcher1 = new MockTextWatcher();
1127fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1128fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.addTextChangedListener(watcher0);
1129fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.addTextChangedListener(watcher1);
1130fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1131fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1132fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1133fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("Changed");
1134fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1135fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1136fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1137fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledBeforeTextChanged());
1138fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledOnTextChanged());
1139fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledAfterTextChanged());
1140fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1141fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1142fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // BeforeTextChanged and OnTextChanged are called though the strings are same
1144fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("Changed");
1145fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1146fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1147fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1148fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledBeforeTextChanged());
1149fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledOnTextChanged());
1150fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledAfterTextChanged());
1151fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1152fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1154fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // BeforeTextChanged and OnTextChanged are called twice (The text is not
1155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Editable, so in Append() it calls setText() first)
1156fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("and appended");
1157fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1158fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1159fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1160fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledBeforeTextChanged());
1161fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledOnTextChanged());
1162fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher1.hasCalledAfterTextChanged());
1163fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1164fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1165fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1166fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Methods are not called if the string does not change
1167fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("");
1168fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher0.hasCalledBeforeTextChanged());
1169fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher0.hasCalledOnTextChanged());
1170fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher0.hasCalledAfterTextChanged());
1171fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledBeforeTextChanged());
1172fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledOnTextChanged());
1173fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledAfterTextChanged());
1174fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1175fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher0.reset();
1176fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        watcher1.reset();
1177fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.removeTextChangedListener(watcher1);
1178fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(null);
1179fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledBeforeTextChanged());
1180fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledOnTextChanged());
1181fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(watcher0.hasCalledAfterTextChanged());
1182fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledBeforeTextChanged());
1183fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledOnTextChanged());
1184fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(watcher1.hasCalledAfterTextChanged());
1185fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1186fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1187fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetTextKeepState1() {
1188fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
1189fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1190fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String longString = "very long content";
1191fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String shortString = "short";
1192fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1193fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is inside the short string
1194fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString, BufferType.SPANNABLE);
1195fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 3);
1196fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1197fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1198fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionStart());
1199fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionEnd());
1200fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1201fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is outside the short string
1202fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1203fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), shortString.length() + 1);
1204fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1205fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1206fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1207fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1208fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1209fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is inside the short string
1210fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1211fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 1, 4);
1212fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1213fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1214fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getSelectionStart());
1215fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(4, mTextView.getSelectionEnd());
1216fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1217fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which ends outside the short string
1218fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1219fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 2, shortString.length() + 1);
1220fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1221fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1222fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, mTextView.getSelectionStart());
1223fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1224fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1225fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is outside the short string
1226fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1227fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(),
1228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                shortString.length() + 1, shortString.length() + 3);
1229fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString);
1230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1235fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetEditableText() {
1237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
1238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "Hello";
1240fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(text, BufferType.EDITABLE);
1241fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text, tv.getText().toString());
1242fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Editable);
1243fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text, tv.getEditableText().toString());
1244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1245fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(text, BufferType.SPANNABLE);
1246fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text, tv.getText().toString());
1247fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Spannable);
1248fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(tv.getEditableText());
1249fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1250fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(null, BufferType.EDITABLE);
1251fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
1252fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Editable);
1253fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getEditableText().toString());
1254fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1255fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(null, BufferType.SPANNABLE);
1256fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
1257fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Spannable);
1258fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(tv.getEditableText());
1259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1260fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1261fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1262fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText2() {
1263fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String string = "This is a test for setting text content by char array";
1264fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        char[] input = string.toCharArray();
1265fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
1266fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1267fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(input, 0, input.length);
1268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(string, tv.getText().toString());
1269fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1270fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(input, 0, 5);
1271fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(string.substring(0, 5), tv.getText().toString());
1272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1273fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1274fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(input, -1, input.length);
1275fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if the start position is negative!");
1276fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IndexOutOfBoundsException exception) {
1277fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1278fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1279fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1280fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(input, 0, -1);
1281fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if the length is negative!");
1282fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IndexOutOfBoundsException exception) {
1283fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1284fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1285fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(input, 1, input.length);
1287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if the end position is out of index!");
1288fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IndexOutOfBoundsException exception) {
1289fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1290fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1291fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(input, 1, 0);
1292fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", tv.getText().toString());
1293fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1294fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1295fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1296fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText1() {
1297fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
1298fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String longString = "very long content";
1300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String shortString = "short";
1301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1302fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is inside the short string
1303fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString, BufferType.SPANNABLE);
1304fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 3);
1305fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1306fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1307fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1308fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionStart());
1310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(3, mTextView.getSelectionEnd());
1311fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1313fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1314fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1315fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1316fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // selection is at the exact place which is outside the short string
1321fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1322fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), longString.length());
1323fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1324fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1325fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1329fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1330fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1331fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1332fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1333fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1334fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1336fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1337fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1338fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is inside the short string
1339fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1340fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 1, shortString.length() - 1);
1341fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1342fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1343fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1344fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1345fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getSelectionStart());
1346fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length() - 1, mTextView.getSelectionEnd());
1347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1350fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which ends outside the short string
1357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1358fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), 2, longString.length());
1359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1360fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1361fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1362fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, mTextView.getSelectionStart());
1364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1366fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1367fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1368fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1370fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1371fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1372fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1373fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // select the sub string which is outside the short string
1375fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(longString);
1376fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(),
1377fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                shortString.length() + 1, shortString.length() + 3);
1378fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextKeepState(shortString, BufferType.EDITABLE);
1379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1380fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1381fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionStart());
1383fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString.length(), mTextView.getSelectionEnd());
1384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1385fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(shortString, BufferType.EDITABLE);
1386fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
1387fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getText().toString());
1388fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(shortString, mTextView.getEditableText().toString());
1389fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no selection.
1390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionStart());
1391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getSelectionEnd());
1392fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1393fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1394fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
1395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText3() {
1396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
1397fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int resId = R.string.text_view_hint;
1399fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String result = mActivity.getResources().getString(resId);
1400fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(resId);
1402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(result, tv.getText().toString());
1403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
1404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
1405fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(-1);
1406fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception with illegal id");
1407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NotFoundException e) {
1408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
1409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
1410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
141198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir    @MediumTest
141298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir    public void testSetText_updatesHeightAfterRemovingImageSpan() {
141398d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // Height calculation had problems when TextView had width: match_parent
141498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int textViewWidth = ViewGroup.LayoutParams.MATCH_PARENT;
141598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final Spannable text = new SpannableString("some text");
141698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int spanHeight = 100;
141798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
141898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // prepare TextView, width: MATCH_PARENT
141998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        TextView textView = new TextView(getActivity());
142098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        textView.setSingleLine(true);
142198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 2);
142298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        textView.setPadding(0, 0, 0, 0);
142398d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        textView.setIncludeFontPadding(false);
142498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        textView.setText(text);
142598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
142698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(textViewWidth,
142798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
142898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        layout.addView(textView, layoutParams);
142998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        layout.setLayoutParams(layoutParams);
14306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> getActivity().setContentView(layout));
143198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        getInstrumentation().waitForIdleSync();
143298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
143398d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // measure height of text with no span
143498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int heightWithoutSpan = textView.getHeight();
143598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        assertTrue("Text height should be smaller than span height",
143698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                heightWithoutSpan < spanHeight);
143798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
143898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // add ImageSpan to text
143998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        Drawable drawable = mInstrumentation.getContext().getDrawable(R.drawable.scenery);
144098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        drawable.setBounds(0, 0, spanHeight, spanHeight);
144198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        ImageSpan span = new ImageSpan(drawable);
144298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        text.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
14436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> textView.setText(text));
144498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        mInstrumentation.waitForIdleSync();
144598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
144698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // measure height with span
144798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int heightWithSpan = textView.getHeight();
144898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        assertTrue("Text height should be greater or equal than span height",
144998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                heightWithSpan >= spanHeight);
145098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
145198d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        // remove the span
145298d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        text.removeSpan(span);
14536beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> textView.setText(text));
145498d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        mInstrumentation.waitForIdleSync();
145598d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
145698d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        final int heightAfterRemoveSpan = textView.getHeight();
145798d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir        assertEquals("Text height should be same after removing the span",
145898d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir                heightWithoutSpan, heightAfterRemoveSpan);
145998d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir    }
146098d94f2d9f2354dc151fe0ad12646c39b7cf49b8Siyamed Sinir
1461af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi    public void testRemoveSelectionWithSelectionHandles() {
14626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1463af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1464354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertFalse(mTextView.isTextSelectable());
1465354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> {
1466354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mTextView.setTextIsSelectable(true);
1467354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mTextView.setText("abcd", BufferType.EDITABLE);
1468af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        });
1469af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        mInstrumentation.waitForIdleSync();
1470354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mTextView.isTextSelectable());
1471af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1472af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        // Long click on the text selects all text and shows selection handlers. The view has an
1473af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        // attribute layout_width="wrap_content", so clicked location (the center of the view)
1474af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        // should be on the text.
1475af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        TouchUtils.longClickView(this, mTextView);
1476af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1477354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> Selection.removeSelection((Spannable) mTextView.getText()));
1478af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi        mInstrumentation.waitForIdleSync();
1479354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
1480354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.equals("abcd", mTextView.getText()));
1481af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi    }
1482af32bc382e1eae93a12b5c2aa91c2acf8a999adfYoshiki Iguchi
1483c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_insert() {
14846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
14855b51f77b99861d48fec1c327252416f726b3b01aJames Cook
14865b51f77b99861d48fec1c327252416f726b3b01aJames Cook        // Type some text.
14875bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
14886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
14896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Precondition: The cursor is at the end of the text.
14906beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
14916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
14926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo removes the typed string in one step.
14936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
14946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
14956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
14966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
14976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Redo restores the text and cursor position.
14986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.redo);
14996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
15006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
15016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undoing the redo clears the text again.
15036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15046beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15066beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo when the undo stack is empty does nothing.
15076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15095b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
15105b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
151128715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
15125b51f77b99861d48fec1c327252416f726b3b01aJames Cook
1513c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_delete() {
15146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
15155b51f77b99861d48fec1c327252416f726b3b01aJames Cook
151628715a6877392e4e63cb2b0170c1592fb50079dcJames Cook        // Simulate deleting text and undoing it.
15175bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "xyz");
15185bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL,
15195bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir                KeyEvent.KEYCODE_DEL);
15206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
15216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Precondition: The text was actually deleted.
15226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
15246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo restores the typed string and cursor position in one step.
15266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("xyz", mTextView.getText().toString());
15286beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
15296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Redo removes the text in one step.
15316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.redo);
15326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
15346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undoing the redo restores the text again.
15366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("xyz", mTextView.getText().toString());
15386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(3, mTextView.getSelectionStart());
15396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
15406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undoing again undoes the original typing.
15416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
15426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
15436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals(0, mTextView.getSelectionStart());
15445b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
15455b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
154628715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
15475b51f77b99861d48fec1c327252416f726b3b01aJames Cook
1548c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    // Initialize the text view for simulated IME typing. Must be called on UI thread.
1549c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    private InputConnection initTextViewForSimulatedIme() {
1550c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView = findTextView(R.id.textview_text);
1551c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
1552c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.setText("", BufferType.EDITABLE);
1553c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        return mTextView.onCreateInputConnection(new EditorInfo());
1554c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1555c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1556c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    // Simulates IME composing text behavior.
1557c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    private void setComposingTextInBatch(InputConnection input, CharSequence text) {
1558c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1559c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.setComposingText(text, 1);  // Leave cursor at end.
1560c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1561c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1562c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1563c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1564c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeInsertLatin() {
1565c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1566c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1567c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Simulate IME text entry behavior. The Latin IME enters text by replacing partial words,
1568c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // such as "c" -> "ca" -> "cat" -> "cat ".
1569c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "c");
1570c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "ca");
1571c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1572c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The completion and space are added in the same batch.
1573c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1574c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.commitText("cat", 1);
1575c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.commitText(" ", 1);
1576c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1577c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1578c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The repeated replacements undo in a single step.
1579c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
1580c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("", mTextView.getText().toString());
1581c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1582c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1583c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1584c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeInsertJapanese() {
1585c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1586c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1587c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The Japanese IME does repeated replacements of Latin characters to hiragana to kanji.
1588c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        final String HA = "\u306F";  // HIRAGANA LETTER HA
1589c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        final String NA = "\u306A";  // HIRAGANA LETTER NA
1590c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "h");
1591c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA);
1592c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA + "n");
1593c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA + NA);
1594c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1595c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The result may be a surrogate pair. The composition ends in the same batch.
1596c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1597c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.commitText("\uD83C\uDF37", 1);  // U+1F337 TULIP
1598c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.setComposingText("", 1);
1599c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1600c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1601c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // The repeated replacements are a single undo step.
1602c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
1603c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("", mTextView.getText().toString());
1604c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1605c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1606c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
160771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    public void testUndo_imeInsertAndDeleteLatin() {
160871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        InputConnection input = initTextViewForSimulatedIme();
160971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
161071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "t");
161171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "te");
161271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "tes");
161371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "test");
161471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "tes");
161571e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "te");
161671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "t");
161771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
161871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.beginBatchEdit();
161971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.setComposingText("", 1);
162071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.finishComposingText();
162171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.endBatchEdit();
162271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
162371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        mTextView.onTextContextMenuItem(android.R.id.undo);
162471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("test", mTextView.getText().toString());
162571e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        mTextView.onTextContextMenuItem(android.R.id.undo);
162671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("", mTextView.getText().toString());
162771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    }
162871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
162971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    @UiThreadTest
163071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    public void testUndo_imeAutoCorrection() {
163171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        InputConnection input = initTextViewForSimulatedIme();
163271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
163371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        // Start typing a composition.
163471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "t");
163571e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "te");
163671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        setComposingTextInBatch(input, "teh");
163771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
163871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.beginBatchEdit();
163971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        // Auto correct "teh" to "the".
164071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.commitCorrection(new CorrectionInfo(0, "teh", "the"));
164171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.commitText("the", 1);
164271e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        input.endBatchEdit();
164371e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
164471e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("the", mTextView.getText().toString());
164571e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        mTextView.onTextContextMenuItem(android.R.id.undo);
164671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("teh", mTextView.getText().toString());
164771e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        mTextView.onTextContextMenuItem(android.R.id.undo);
164871e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals("", mTextView.getText().toString());
164971e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    }
165071e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi
165171e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi    @UiThreadTest
1652c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeCancel() {
1653c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1654c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.setText("flower");
1655c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1656c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Start typing a composition.
1657c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        final String HA = "\u306F";  // HIRAGANA LETTER HA
1658c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "h");
1659c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA);
1660c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, HA + "n");
1661c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1662c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Cancel the composition.
1663c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        setComposingTextInBatch(input, "");
1664c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1665c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
166671e696fcc640126a0360d30e8b1d9a5552f6dd1dKeisuke Kuroyanagi        assertEquals(HA + "n" + "flower", mTextView.getText().toString());
1667c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.redo);
1668c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("flower", mTextView.getText().toString());
1669c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1670c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1671c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    @UiThreadTest
1672c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_imeEmptyBatch() {
1673c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        InputConnection input = initTextViewForSimulatedIme();
1674c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.setText("flower");
1675c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1676c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Send an empty batch edit. This happens if the IME is hidden and shown.
1677c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.beginBatchEdit();
1678c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        input.endBatchEdit();
1679c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1680c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Undo and redo do nothing.
1681c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.undo);
1682c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("flower", mTextView.getText().toString());
1683c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        mTextView.onTextContextMenuItem(android.R.id.redo);
1684c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        assertEquals("flower", mTextView.getText().toString());
1685c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    }
1686c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook
1687c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_setText() {
16886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
168928715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1690c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook        // Create two undo operations, an insert and a delete.
16915bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "xyz");
16925bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL,
16935bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir                KeyEvent.KEYCODE_DEL);
16946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
16956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Calling setText() clears both undo operations, so undo doesn't happen.
16966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("Hello", BufferType.EDITABLE);
16976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
16986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("Hello", mTextView.getText().toString());
16996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
17006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Clearing text programmatically does not undo either.
17016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
17026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
17036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1704277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1705277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1706277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
170728715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1708c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testRedo_setText() {
17096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1710277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1711277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text. This creates an undo entry.
17125bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
17136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
17146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo the typing to create a redo entry.
17156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
1716277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
17176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Calling setText() clears the redo stack, so redo doesn't happen.
17186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("Hello", BufferType.EDITABLE);
17196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.redo);
17206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("Hello", mTextView.getText().toString());
1721277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1722277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1723277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
1724277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1725c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_directAppend() {
17266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
172728715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1728277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text.
17295bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
17306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
17316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Programmatically append some text.
17326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.append("def");
17336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abcdef", mTextView.getText().toString());
1734277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
17356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo removes the append as a separate step.
17366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
17376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
1738277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
17396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Another undo removes the original typing.
17406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
17416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1742277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1743277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1744277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
1745277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1746c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_directInsert() {
17476beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1748277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1749277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text.
17505bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
17516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
17526beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Directly modify the underlying Editable to insert some text.
17536beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // NOTE: This is a violation of the API of getText() which specifies that the
17546beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // returned object should not be modified. However, some apps do this anyway and
17556beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // the framework needs to handle it.
17566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Editable text = (Editable) mTextView.getText();
17576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            text.insert(0, "def");
17586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("defabc", mTextView.getText().toString());
17596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
17606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo removes the insert as a separate step.
17616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
17626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
17636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
17646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Another undo removes the original typing.
17656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
17666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1767277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1768277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1769277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
1770277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
17716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
1772c530472a02205f0b7d87f9f06140c56ca0849816James Cook    public void testUndo_noCursor() {
1773c530472a02205f0b7d87f9f06140c56ca0849816James Cook        initTextViewForTyping();
1774c530472a02205f0b7d87f9f06140c56ca0849816James Cook
17756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Append some text to create an undo operation. There is no cursor present.
17766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.append("cat");
1777c530472a02205f0b7d87f9f06140c56ca0849816James Cook
17786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Place the cursor at the end of the text so the undo will have to change it.
17796beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 3);
1780c530472a02205f0b7d87f9f06140c56ca0849816James Cook
17816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Undo the append. This should not crash, despite not having a valid cursor
17826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // position in the undo operation.
17836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.undo);
1784c530472a02205f0b7d87f9f06140c56ca0849816James Cook    }
1785c530472a02205f0b7d87f9f06140c56ca0849816James Cook
1786c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_textWatcher() {
17876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
1788277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1789277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Add a TextWatcher that converts the text to spaces on each change.
1790277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mTextView.addTextChangedListener(new ConvertToSpacesTextWatcher());
1791277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
1792277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        // Type some text.
17935bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
17946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
17956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // TextWatcher altered the text.
17966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("   ", mTextView.getText().toString());
1797277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
17986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo reverses both changes in one step.
17996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
1801277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        });
1802277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        mInstrumentation.waitForIdleSync();
1803c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook    }
1804c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
18056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
1806c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook    public void testUndo_textWatcherDirectAppend() {
1807c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook        initTextViewForTyping();
1808c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
1809c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook        // Add a TextWatcher that converts the text to spaces on each change.
1810c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook        mTextView.addTextChangedListener(new ConvertToSpacesTextWatcher());
1811c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
18126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Programmatically append some text. The TextWatcher changes it to spaces.
18136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.append("abc");
18146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("   ", mTextView.getText().toString());
1815c4dca4185874f3a78380439d678f1a8fa86f7a66James Cook
18166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Undo reverses both changes in one step.
18176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.undo);
18186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("", mTextView.getText().toString());
181928715a6877392e4e63cb2b0170c1592fb50079dcJames Cook    }
182028715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
1821c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_shortcuts() {
18226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
182328715a6877392e4e63cb2b0170c1592fb50079dcJames Cook
182428715a6877392e4e63cb2b0170c1592fb50079dcJames Cook        // Type some text.
18255bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
18266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
18276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Pressing Control-Z triggers undo.
18286beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent control = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_Z, 0,
18296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_CTRL_LEFT_ON);
18306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertTrue(mTextView.onKeyShortcut(KeyEvent.KEYCODE_Z, control));
18316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
18326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
18336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Pressing Control-Shift-Z triggers redo.
18346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent controlShift = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_Z,
18356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    0, KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_SHIFT_LEFT_ON);
18366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertTrue(mTextView.onKeyShortcut(KeyEvent.KEYCODE_Z, controlShift));
18376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
18385b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
18395b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
18405b51f77b99861d48fec1c327252416f726b3b01aJames Cook    }
18415b51f77b99861d48fec1c327252416f726b3b01aJames Cook
1842c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_saveInstanceState() {
18436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
18445b51f77b99861d48fec1c327252416f726b3b01aJames Cook
18455b51f77b99861d48fec1c327252416f726b3b01aJames Cook        // Type some text to create an undo operation.
18465bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
18476beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
18486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Parcel and unparcel the TextView.
18496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Parcelable state = mTextView.onSaveInstanceState();
18506beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onRestoreInstanceState(state);
18515b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
18525b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
18535b51f77b99861d48fec1c327252416f726b3b01aJames Cook
18545b51f77b99861d48fec1c327252416f726b3b01aJames Cook        // Delete a character to create a new undo operation.
18555bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
18566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
18576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("ab", mTextView.getText().toString());
18585b51f77b99861d48fec1c327252416f726b3b01aJames Cook
18596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo the delete.
18606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("abc", mTextView.getText().toString());
18625b51f77b99861d48fec1c327252416f726b3b01aJames Cook
18636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Undo the typing, which verifies that the original undo operation was parceled
18646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // correctly.
18656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
18675f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
18686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Parcel and unparcel the undo stack (which is empty but has been used and may
18696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // contain other state).
18706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Parcelable state = mTextView.onSaveInstanceState();
18716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onRestoreInstanceState(state);
18725f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        });
18735f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        mInstrumentation.waitForIdleSync();
18745f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook    }
18755f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
1876c1198c0aa7c7e9b52a32d9e2c0d663c69ee131c6James Cook    public void testUndo_saveInstanceStateEmpty() {
18776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
18785f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
18795f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        // Type and delete to create two new undo operations.
18805bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "a");
18815bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
18826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
18836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Empty the undo stack then parcel and unparcel the TextView. While the undo
18846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // stack contains no operations it may contain other state.
18856beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18866beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Parcelable state = mTextView.onSaveInstanceState();
18886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onRestoreInstanceState(state);
18895f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        });
18905f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        mInstrumentation.waitForIdleSync();
18915f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook
18925f31960d0d0e9aac4b48e895ee8fd144791a5109James Cook        // Create two more undo operations.
18935bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "b");
18945bd6955fa69a7f5e07d669ea677840099c4e1dbcSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
18956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
18966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Verify undo still works.
18976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
18986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("b", mTextView.getText().toString());
18996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.undo);
19006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("", mTextView.getText().toString());
19015b51f77b99861d48fec1c327252416f726b3b01aJames Cook        });
19025b51f77b99861d48fec1c327252416f726b3b01aJames Cook        mInstrumentation.waitForIdleSync();
19035b51f77b99861d48fec1c327252416f726b3b01aJames Cook    }
19045b51f77b99861d48fec1c327252416f726b3b01aJames Cook
19056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
1906b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    public void testCopyAndPaste() {
1907b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        initTextViewForTyping();
19086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("abcd", BufferType.EDITABLE);
19106beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setSelected(true);
19116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Copy "bc".
19136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
19146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.copy);
19156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste "bc" between "b" and "c".
19176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 2, 2);
19186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
19196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("abbccd", mTextView.getText().toString());
19206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Select entire text and paste "bc".
19226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
19236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
19246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("bc", mTextView.getText().toString());
1925b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
1926b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
192749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi    public void testCopyAndPaste_byKey() {
19286beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
192949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
193049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Type "abc".
193103818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
19326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
19336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Select "bc"
19346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
193549279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
193649279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
193749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Copy "bc"
193803818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_COPY);
193949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
19406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
19416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Set cursor between 'b' and 'c'.
19426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 2, 2);
194349279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
194449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
194549279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Paste "bc"
194603818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PASTE);
194749279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        assertEquals("abbcc", mTextView.getText().toString());
194849279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
19496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
19506beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
19516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
19526beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.KEYCODE_COPY, 0, KeyEvent.META_SHIFT_LEFT_ON);
19536beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Shift + copy doesn't perform copy.
19546beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
19556beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
19566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.paste);
19576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bcabbcc", mTextView.getText().toString());
19586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
19606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_COPY, 0,
19616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_CTRL_LEFT_ON);
19626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + copy doesn't perform copy.
19636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
19646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
19656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.paste);
19666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bcbcabbcc", mTextView.getText().toString());
19676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
19696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            copyWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_COPY, 0,
19706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_CTRL_LEFT_ON);
19716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + Shift + copy doesn't perform copy.
19726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_COPY, copyWithMeta);
19736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
19746beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.paste);
19756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bcbcbcabbcc", mTextView.getText().toString());
197649279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
19778e9fc4a5b2274a1279261f1a36c5396b9884042dKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
197849279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi    }
197949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
19806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
1981b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    public void testCutAndPaste() {
1982b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        initTextViewForTyping();
19836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("abcd", BufferType.EDITABLE);
19856beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setSelected(true);
19866beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19876beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Cut "bc".
19886beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
19896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.cut);
19906beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("ad", mTextView.getText().toString());
19916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Cut "ad".
19936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.setSelection((Spannable) mTextView.getText(), 0, 2);
19946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.cut);
19956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("", mTextView.getText().toString());
19966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
19976beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste "ad".
19986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
19996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("ad", mTextView.getText().toString());
2000b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2001b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
200249279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi    public void testCutAndPaste_byKey() {
20036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
200449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
200549279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Type "abc".
200603818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "abc");
20076beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
20086beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Select "bc"
20096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 1, 3);
201049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
201149279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
201249279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Cut "bc"
201303818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_CUT);
201449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
20156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
20166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("a", mTextView.getText().toString());
20176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Move cursor to the head
20186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection((Spannable) mTextView.getText(), 0, 0);
201949279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
202049279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
202149279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        // Paste "bc"
202203818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PASTE);
202349279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        assertEquals("bca", mTextView.getText().toString());
202449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
20256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
20266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.selectAll((Spannable) mTextView.getText());
20276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            KeyEvent cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
20286beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.KEYCODE_CUT, 0, KeyEvent.META_SHIFT_LEFT_ON);
20296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Shift + cut doesn't perform cut.
20306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
20316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bca", mTextView.getText().toString());
20326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CUT, 0,
20346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_CTRL_LEFT_ON);
20356beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + cut doesn't perform cut.
20366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
20376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bca", mTextView.getText().toString());
20386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20396beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            cutWithMeta = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_CUT, 0,
20406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_CTRL_LEFT_ON);
20416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Control + Shift + cut doesn't perform cut.
20426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onKeyDown(KeyEvent.KEYCODE_CUT, cutWithMeta);
20436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertEquals("bca", mTextView.getText().toString());
204449279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi        });
204549279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi    }
204649279f3ccd432c3d9611ee3c357ebb407b84c5c5Keisuke Kuroyanagi
2047b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    private static boolean hasSpansAtMiddleOfText(final TextView textView, final Class<?> type) {
2048b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        final Spannable spannable = (Spannable)textView.getText();
2049b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        final int at = spannable.length() / 2;
2050b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        return spannable.getSpans(at, at, type).length > 0;
2051b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2052b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
20536beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
2054b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    public void testCutAndPaste_withAndWithoutStyle() {
2055b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi        initTextViewForTyping();
20566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20576beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setText("example", BufferType.EDITABLE);
20586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.setSelected(true);
20596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Set URLSpan.
20616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        final Spannable spannable = (Spannable) mTextView.getText();
20626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        spannable.setSpan(new URLSpan("http://example.com"), 0, spannable.length(), 0);
20636beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertTrue(hasSpansAtMiddleOfText(mTextView, URLSpan.class));
20646beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Cut entire text.
20666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
20676beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.cut);
20686beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("", mTextView.getText().toString());
20696beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste without style.
20716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.pasteAsPlainText);
20726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("example", mTextView.getText().toString());
20736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Check that the text doesn't have URLSpan.
20746beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertFalse(hasSpansAtMiddleOfText(mTextView, URLSpan.class));
20756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu
20766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Paste with style.
20776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        Selection.selectAll((Spannable) mTextView.getText());
20786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mTextView.onTextContextMenuItem(android.R.id.paste);
20796beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertEquals("example", mTextView.getText().toString());
20806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // Check that the text has URLSpan.
20816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        assertTrue(hasSpansAtMiddleOfText(mTextView, URLSpan.class));
2082b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi    }
2083b07a600d96f12f712b7914822fea7db15b881a5dKeisuke Kuroyanagi
2084fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
20854ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    public void testSaveInstanceState() {
2086baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // should save text when freezesText=true
20874ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        TextView originalTextView = new TextView(mActivity);
20884ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        final String text = "This is a string";
20894ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        originalTextView.setText(text);
20904ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        originalTextView.setFreezesText(true);  // needed to actually save state
20914ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        Parcelable state = originalTextView.onSaveInstanceState();
20924ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
20934ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        TextView restoredTextView = new TextView(mActivity);
20944ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        restoredTextView.onRestoreInstanceState(state);
20954ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        assertEquals(text, restoredTextView.getText().toString());
20964ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    }
20974ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
20984ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    @UiThreadTest
2099baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_whenFreezesTextIsFalse() {
21004ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien        final String text = "This is a string";
2101baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        { // should not save text when freezesText=false
2102baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for before saveInstanceState
2103baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView1 = new TextView(mActivity);
2104baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setFreezesText(false);
2105baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setText(text);
21064ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
2107baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for after saveInstanceState
2108baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView2 = new TextView(mActivity);
2109baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.setFreezesText(false);
2110baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2111baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2112baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2113baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            assertEquals("", textView2.getText().toString());
2114baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        }
2115baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2116baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        { // should not save text even when textIsSelectable=true
2117baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for before saveInstanceState
2118baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView1 = new TextView(mActivity);
2119baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setFreezesText(false);
2120baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setTextIsSelectable(true);
2121baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView1.setText(text);
2122baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2123baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            // prepare TextView for after saveInstanceState
2124baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            TextView textView2 = new TextView(mActivity);
2125baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.setFreezesText(false);
2126baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.setTextIsSelectable(true);
2127baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2128baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2129baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2130baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir            assertEquals("", textView2.getText().toString());
2131baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        }
2132baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    }
2133baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2134baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @UiThreadTest
2135baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @SmallTest
2136baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_doesNotSaveSelectionWhenDoesNotExist() {
2137baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for before saveInstanceState
2138baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        final String text = "This is a string";
2139baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView1 = new TextView(mActivity);
2140baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setFreezesText(true);
2141baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setText(text);
2142baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2143baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for after saveInstanceState
2144baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView2 = new TextView(mActivity);
2145baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setFreezesText(true);
2146baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2147baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2148baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2149baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(-1, textView2.getSelectionStart());
2150baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(-1, textView2.getSelectionEnd());
2151baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    }
2152baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2153baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @UiThreadTest
2154baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @SmallTest
2155baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_doesNotRestoreSelectionWhenTextIsAbsent() {
2156baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for before saveInstanceState
2157baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        final String text = "This is a string";
2158baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView1 = new TextView(mActivity);
2159baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setFreezesText(false);
2160baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setTextIsSelectable(true);
2161baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setText(text);
2162baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        Selection.setSelection((Spannable) textView1.getText(), 2, text.length() - 2);
2163baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2164baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for after saveInstanceState
2165baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView2 = new TextView(mActivity);
2166baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setFreezesText(false);
2167baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setTextIsSelectable(true);
2168baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2169baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2170baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2171baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals("", textView2.getText().toString());
2172baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        //when textIsSelectable, selection start and end are initialized to 0
2173baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(0, textView2.getSelectionStart());
2174baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(0, textView2.getSelectionEnd());
2175baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    }
2176baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2177baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @UiThreadTest
2178baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    @SmallTest
2179baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir    public void testOnSaveInstanceState_savesSelectionWhenExists() {
2180baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        final String text = "This is a string";
2181baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for before saveInstanceState
2182baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView1 = new TextView(mActivity);
2183baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setFreezesText(true);
2184baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setTextIsSelectable(true);
2185baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView1.setText(text);
2186baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        Selection.setSelection((Spannable) textView1.getText(), 2, text.length() - 2);
2187baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2188baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        // prepare TextView for after saveInstanceState
2189baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        TextView textView2 = new TextView(mActivity);
2190baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setFreezesText(true);
2191baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.setTextIsSelectable(true);
2192baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2193baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        textView2.onRestoreInstanceState(textView1.onSaveInstanceState());
2194baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir
2195baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(textView1.getSelectionStart(), textView2.getSelectionStart());
2196baeafb8c1c7feacfa0fd684d38646ac24d642e34Siyamed Sinir        assertEquals(textView1.getSelectionEnd(), textView2.getSelectionEnd());
21974ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    }
21984ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien
21994ed3b6c02b917394dfc68c4d421c4b935a3325c8Raph Levien    @UiThreadTest
2200fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetText() {
2201fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView tv = findTextView(R.id.textview_text);
2202fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2203fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int resId = R.string.text_view_hint;
2204fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String result = mActivity.getResources().getString(resId);
2205fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2206fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(resId, BufferType.EDITABLE);
2207fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(result, tv.getText().toString());
2208fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Editable);
2209fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2210fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        tv.setText(resId, BufferType.SPANNABLE);
2211fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(result, tv.getText().toString());
2212fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(tv.getText() instanceof Spannable);
2213fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2214fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2215fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            tv.setText(-1, BufferType.EDITABLE);
2216fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception with illegal id");
2217fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NotFoundException e) {
2218fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2219fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2220fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2221fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2222fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessHint() {
2223fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_hint_linksclickable_freezestext);
2224fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2225fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_linksClickable_freezesText_default);
2226fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getHint());
2227fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_blank);
2229fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", mTextView.getHint());
2230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_string);
2232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getString(R.string.text_view_simple_hint),
2233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHint());
2234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2235fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.hint_resid);
2236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getString(R.string.text_view_hint),
2237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHint());
2238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHint("This is hint");
2240fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("This is hint", mTextView.getHint().toString());
2241fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2242fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setHint(R.string.text_view_hello);
2243fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
2244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHint().toString());
2245fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2246fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Non-exist resid
2247fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2248fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setHint(-1);
2249fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw exception if id is illegal");
2250fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NotFoundException e) {
2251fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2252fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2253fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2254fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessError() {
2255fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2256fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2257fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
225853b55f734fb3cf52df49a79cf76d410a77fbe8f5Craig Mautner        final String errorText = "Oops! There is an error";
2259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
22606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setError(null));
2261fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2262fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2263fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2264a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable icon = TestUtils.getDrawable(mActivity, R.drawable.failed);
22656beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setError(errorText, icon));
2266fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2267fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(errorText, mTextView.getError().toString());
2268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // can not check whether the drawable is set correctly
2269fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
22706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setError(null, null));
2271fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2273fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
22746beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
22756beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(DigitsKeyListener.getInstance(""));
22766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
22776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setError(errorText);
22786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
2279fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2280fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2281fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2282fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(errorText, mTextView.getError().toString());
2283fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
228403818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "a");
2285fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // a key event that will not change the TextView's text
2286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("", mTextView.getText().toString());
2287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // The icon and error message will not be reset to null
228853b55f734fb3cf52df49a79cf76d410a77fbe8f5Craig Mautner        assertEquals(errorText, mTextView.getError().toString());
2289fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
22906beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
22916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(DigitsKeyListener.getInstance());
22926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
22936beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setError(errorText);
22946beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
2295300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        });
2296300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu        mInstrumentation.waitForIdleSync();
2297300d755fcaa7274f1570f53d34c7a657bc420ab6Brian Muramatsu
229803818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "1");
2299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // a key event cause changes to the TextView's text
2300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("1", mTextView.getText().toString());
2301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the error message and icon will be cleared.
2302fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getError());
2303fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2304fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2305fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessFilters() {
2306fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final InputFilter[] expected = { new InputFilter.AllCaps(),
2307fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                new InputFilter.LengthFilter(2) };
2308fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final QwertyKeyListener qwertyKeyListener
2310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                = QwertyKeyListener.getInstance(false, Capitalize.NONE);
23116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
23126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
23136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(qwertyKeyListener);
23146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("", BufferType.EDITABLE);
23156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setFilters(expected);
23166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
2317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(expected, mTextView.getFilters());
2321fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
232203818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "a");
2323fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text is capitalized by InputFilter.AllCaps
2324fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("A", mTextView.getText().toString());
232503818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "b");
2326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the text is capitalized by InputFilter.AllCaps
2327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("AB", mTextView.getText().toString());
232803818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "c");
2329fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 'C' could not be accepted, because there is a length filter.
2330fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("AB", mTextView.getText().toString());
2331fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2332fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2333fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.setFilters(null);
2334fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw IllegalArgumentException!");
2335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (IllegalArgumentException e) {
2336fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2337fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2338fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2339fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetFocusedRect() {
2340fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Rect rc = new Rect();
2341fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2342fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        // Basic
2343fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2344fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getFocusedRect(rc);
2345fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX(), rc.left);
2346fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX() + mTextView.getWidth(), rc.right);
2347fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY(), rc.top);
2348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY() + mTextView.getHeight(), rc.bottom);
2349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2350fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        // Single line
2351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getFocusedRect(rc);
2353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX(), rc.left);
2354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollX() + mTextView.getWidth(), rc.right);
2355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY(), rc.top);
2356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getScrollY() + mTextView.getHeight(), rc.bottom);
2357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
23586beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
23596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
23606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
23616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 3, 13);
23626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getFocusedRect(rc);
2366fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView.getLayout());
2367fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        /* Cursor coordinates from getPrimaryHorizontal() may have a fractional
2368fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * component, while the result of getFocusedRect is in int coordinates.
2369fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * It's not practical for these to match exactly, so we compare that the
2370fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * integer components match - there can be a fractional pixel
2371fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien         * discrepancy, which should be okay for all practical applications. */
2372fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(3), rc.left);
2373fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(13), rc.right);
2374fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2375fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(0), rc.bottom);
2376fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
23776beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
23786beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
23796beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
23806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 13, 3);
23816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2382fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        });
2383fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mInstrumentation.waitForIdleSync();
2384fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2385fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertNotNull(mTextView.getLayout());
2386fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(3) - 2, rc.left);
2387fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(3) + 2, rc.right);
2388fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2389fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(0), rc.bottom);
2390fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
2391fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        // Multi lines
2392fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView = findTextView(R.id.textview_text_two_lines);
2393fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2394fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollX(), rc.left);
2395fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollX() + mTextView.getWidth(), rc.right);
2396fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollY(), rc.top);
2397fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getScrollY() + mTextView.getHeight(), rc.bottom);
2398fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
23996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
24006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
24016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
24026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 2, 4);
24036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2404fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        });
2405fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mInstrumentation.waitForIdleSync();
2406fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2407fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertNotNull(mTextView.getLayout());
2408fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(2), rc.left);
2409fe2fb182b7998f5384f78a6956962966b10b5699Raph Levien        assertEquals((int) mTextView.getLayout().getPrimaryHorizontal(4), rc.right);
2410fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2411fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(0), rc.bottom);
2412fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio
24136beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
24146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
24156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            SpannableString text = new SpannableString(mTextView.getText());
24166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            Selection.setSelection(text, 2, 10); // cross the "\n" and two lines
24176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text);
2418fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        });
2419fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mInstrumentation.waitForIdleSync();
2420fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getFocusedRect(rc);
2421fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        Path path = new Path();
2422fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        mTextView.getLayout().getSelectionPath(2, 10, path);
2423fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        RectF rcf = new RectF();
2424fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        path.computeBounds(rcf, true);
2425fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertNotNull(mTextView.getLayout());
2426fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(rcf.left - 1, (float) rc.left);
2427fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(rcf.right + 1, (float) rc.right);
2428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getLayout().getLineTop(0), rc.top);
2429fb0961aa68799b42121f3d8cac094b341c2f9084Fabrice Di Meglio        assertEquals(mTextView.getLayout().getLineBottom(1), rc.bottom);
2430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2431fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Exception
2432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.getFocusedRect(null);
2434fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw NullPointerException!");
2435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
2436fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2437fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2439fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetLineCount() {
2440fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2441fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // this is an one line text with default setting.
2442fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
2443fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2444fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make it multi-lines
2445fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxWidth(mTextView.getWidth() / 3);
2446fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(1 < mTextView.getLineCount());
2447fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2448fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make it to an one line
2449fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMaxWidth(Integer.MAX_VALUE);
2450fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
2451fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2452fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set min lines don't effect the lines count for actual text.
2453fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinLines(12);
2454fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
2455fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2456fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2457fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // the internal Layout has not been built.
2458fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getLayout());
2459fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getLineCount());
2460fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2461fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2462fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetLineBounds() {
2463fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Rect rc = new Rect();
2464fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2465fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getLineBounds(0, null));
2466fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2467fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getLineBounds(0, rc));
2468fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.left);
2469fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.right);
2470fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.top);
2471fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.bottom);
2472fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2473fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2474fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getBaseline(), mTextView.getLineBounds(0, null));
2475fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2476fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getBaseline(), mTextView.getLineBounds(0, rc));
2477fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.left);
2478fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getWidth(), rc.right);
2479fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, rc.top);
2480fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getHeight(), rc.bottom);
2481fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
24826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
24836beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
24846beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
2485fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2486fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2487fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getBaseline(), mTextView.getLineBounds(0, rc));
2488fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getTotalPaddingLeft(), rc.left);
2489fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getWidth() - mTextView.getTotalPaddingRight(), rc.right);
2490fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getTotalPaddingTop(), rc.top);
2491fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getHeight() - mTextView.getTotalPaddingBottom(), rc.bottom);
2492fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2493fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2494fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetBaseLine() {
2495fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2496fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(-1, mTextView.getBaseline());
2497fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2498fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2499fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getLayout().getLineBaseline(0), mTextView.getBaseline());
2500fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
25016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
25026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
25036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
2504fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2505fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2506fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int expected = mTextView.getTotalPaddingTop() + mTextView.getLayout().getLineBaseline(0);
2507fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, mTextView.getBaseline());
2508fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2509fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2510fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testPressKey() {
25116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        initTextViewForTypingOnUiThread();
2512fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
251303818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "a");
2514fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("a", mTextView.getText().toString());
251503818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendString(mTextView, "b");
2516fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("ab", mTextView.getText().toString());
251703818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
2518fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("a", mTextView.getText().toString());
2519fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2520fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2521fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetIncludeFontPadding() {
2522fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2523ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertTrue(mTextView.getIncludeFontPadding());
25246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
25256beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setWidth(mTextView.getWidth() / 3);
25266beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setPadding(1, 2, 3, 4);
25276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
2528fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
2529fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2530fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2531fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int oldHeight = mTextView.getHeight();
25326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setIncludeFontPadding(false));
2533fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
2534fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2535fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getHeight() < oldHeight);
2536ac8bc1679adcd60c7d0b1580d468ae1f58894d4fRaph Levien        assertFalse(mTextView.getIncludeFontPadding());
2537fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2538fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2539fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testScroll() {
2540fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2541fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2542fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollX());
2543fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollY());
2544fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2545fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //don't set the Scroller, nothing changed.
2546fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.computeScroll();
2547fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollX());
2548fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getScrollY());
2549fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2550fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //set the Scroller
2551fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Scroller s = new Scroller(mActivity);
2552fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(s);
2553fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        s.startScroll(0, 0, 320, 480, 0);
2554fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        s.abortAnimation();
2555fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        s.forceFinished(false);
2556fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setScroller(s);
2557fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2558fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.computeScroll();
2559fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(320, mTextView.getScrollX());
2560fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(480, mTextView.getScrollY());
2561fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2562fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2563fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testDebug() {
2564fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2565fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.debug(0);
2566fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2567fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("Hello!");
2568fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(mTextView);
2569fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.debug(1);
2570fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2571fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2572fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSelection() {
2573fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2574fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String text = "This is the content";
2575fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(text, BufferType.SPANNABLE);
2576fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.hasSelection());
2577fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2578fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.selectAll((Spannable) mTextView.getText());
2579fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getSelectionStart());
2580fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(text.length(), mTextView.getSelectionEnd());
2581fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.hasSelection());
2582fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2583fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int selectionStart = 5;
2584fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int selectionEnd = 7;
2585fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), selectionStart);
2586fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, mTextView.getSelectionStart());
2587fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, mTextView.getSelectionEnd());
2588fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.hasSelection());
2589fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2590fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Selection.setSelection((Spannable) mTextView.getText(), selectionStart, selectionEnd);
2591fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionStart, mTextView.getSelectionStart());
2592fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(selectionEnd, mTextView.getSelectionEnd());
2593fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.hasSelection());
2594fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2595fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
25966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
25976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testOnSelectionChanged_isTriggeredWhenSelectionChanges() {
2598b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        final MockTextView textView = spy(new MockTextView(mActivity));
25996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final String text = "any text";
26006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText(text, BufferType.SPANNABLE);
26016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
26026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // assert that there is currently no selection
26036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.hasSelection());
26046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
26056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // select all
26066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        Selection.selectAll((Spannable) textView.getText());
2607b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // After selectAll OnSelectionChanged should have been called
2608b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(textView, times(1)).onSelectionChanged(0, text.length());
26096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
2610b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        reset(textView);
26116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // change selection
26126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        Selection.setSelection((Spannable) textView.getText(), 1, 5);
2613b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(textView, times(1)).onSelectionChanged(1, 5);
26146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
2615b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        reset(textView);
26166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // clear selection
26176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        Selection.removeSelection((Spannable) textView.getText());
2618b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(textView, times(1)).onSelectionChanged(-1, -1);
26196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
26206a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
2621fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2622fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessEllipsize() {
2623fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.setContentView(R.layout.textview_ellipsize);
2624fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2625fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_default);
2626fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getEllipsize());
2627fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2628fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_none);
2629fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getEllipsize());
2630fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2631fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_start);
2632fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TruncateAt.START, mTextView.getEllipsize());
2633fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2634fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_middle);
2635fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TruncateAt.MIDDLE, mTextView.getEllipsize());
2636fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2637fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.ellipsize_end);
2638fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TruncateAt.END, mTextView.getEllipsize());
2639fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2640fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.START);
2641fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.START, mTextView.getEllipsize());
2642fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2643fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
2644fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.MIDDLE, mTextView.getEllipsize());
2645fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2646fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.END);
2647fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.END, mTextView.getEllipsize());
2648fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2649fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(null);
2650fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getEllipsize());
2651fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2652fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(10);
2653fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setEllipsize(TextUtils.TruncateAt.START);
2654fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("ThisIsAVeryLongVeryLongVeryLongVeryLongVeryLongWord");
2655fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.invalidate();
2656fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2657fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(TextUtils.TruncateAt.START, mTextView.getEllipsize());
2658fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no method to check if '...yLongVeryLongWord' is painted in the screen.
2659fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2660fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
26612deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir    public void testEllipsizeEndAndNoEllipsizeHasSameBaselineForSingleLine() {
26622deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        int textWidth = calculateTextWidth(LONG_TEXT);
26632deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26642deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        TextView tvEllipsizeEnd = new TextView(getActivity());
26652deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setEllipsize(TruncateAt.END);
26662deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setMaxLines(1);
26672deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setWidth(textWidth >> 2);
26682deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setText(LONG_TEXT);
26692deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26702deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        TextView tvEllipsizeNone = new TextView(getActivity());
26712deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeNone.setWidth(textWidth >> 2);
26722deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeNone.setText("a");
26732deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26742deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
26752deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
26762deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
26772deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT);
26782deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        layout.addView(tvEllipsizeEnd, layoutParams);
26792deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        layout.addView(tvEllipsizeNone, layoutParams);
26802deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        layout.setLayoutParams(layoutParams);
26812deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> getActivity().setContentView(layout));
26832deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        getInstrumentation().waitForIdleSync();
26842deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26852deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        assertEquals("Ellipsized and non ellipsized single line texts should have the same " +
26862deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                        "baseline",
26872deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                tvEllipsizeEnd.getLayout().getLineBaseline(0),
26882deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                tvEllipsizeNone.getLayout().getLineBaseline(0));
26892deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir    }
26902deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26912deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir    public void testEllipsizeEndAndNoEllipsizeHasSameBaselineForMultiLine() {
26922deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        int textWidth = calculateTextWidth(LONG_TEXT);
26932deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
26942deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        TextView tvEllipsizeEnd = new TextView(getActivity());
26952deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setEllipsize(TruncateAt.END);
26962deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setMaxLines(2);
26972deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setWidth(textWidth >> 2);
26982deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeEnd.setText(LONG_TEXT);
26992deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
27002deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        TextView tvEllipsizeNone = new TextView(getActivity());
27012deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeNone.setMaxLines(2);
27022deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeNone.setWidth(textWidth >> 2);
27032deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        tvEllipsizeNone.setText(LONG_TEXT);
27042deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
27052deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
27062deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
27072deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
27082deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT);
27092deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
27102deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        layout.addView(tvEllipsizeEnd, layoutParams);
27112deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        layout.addView(tvEllipsizeNone, layoutParams);
27122deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        layout.setLayoutParams(layoutParams);
27132deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
27146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> getActivity().setContentView(layout));
27152deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        getInstrumentation().waitForIdleSync();
27162deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
27172deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        for (int i = 0; i < tvEllipsizeEnd.getLineCount(); i++) {
27182deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir            assertEquals("Ellipsized and non ellipsized multi line texts should have the same " +
27192deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                            "baseline for line " + i,
27202deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                    tvEllipsizeEnd.getLayout().getLineBaseline(i),
27212deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir                    tvEllipsizeNone.getLayout().getLineBaseline(i));
27222deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir        }
27232deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir    }
27242deef38f19cb26869b600cd0d075753a9f97d5daSiyamed Sinir
2725672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir    public void testTextViewInWeigthenedLayoutChangesWidthAfterSetText() {
2726672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        final TextView textView = new TextView(getActivity());
2727672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        textView.setEllipsize(TruncateAt.END);
2728672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        textView.setSingleLine(true);
2729672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        textView.setText("a");
2730672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2731672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        TextView otherTextView = new TextView(getActivity());
2732672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        otherTextView.setSingleLine(true);
2733672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        otherTextView.setText("any");
2734672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2735672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        final LinearLayout layout = new LinearLayout(mActivity);
2736672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        layout.setOrientation(LinearLayout.HORIZONTAL);
2737672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2738672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        // TextView under test has weight 1, and width 0
2739672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        layout.addView(textView, new LinearLayout.LayoutParams(0,
2740672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
2741672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2742672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        // other TextView has default weight
2743672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        layout.addView(otherTextView, new LinearLayout.LayoutParams(
2744672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
2745672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT));
2746672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2747672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        // main layout params
2748672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        layout.setLayoutParams(new ViewGroup.LayoutParams(
2749672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
2750672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
27516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> getActivity().setContentView(layout));
2752672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        getInstrumentation().waitForIdleSync();
2753672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2754672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        int oldWidth = textView.getWidth();
2755672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
27566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> textView.setText("aaa"));
2757672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        getInstrumentation().waitForIdleSync();
2758672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2759672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir        assertTrue("TextView should have larger width after a longer text is set",
2760672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir                textView.getWidth() > oldWidth);
2761672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir    }
2762672de87741b35d488adeabd3a4b9f8440dbc8beeSiyamed Sinir
2763354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    public void testAccessCursorVisible() {
2764fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2765fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2766fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCursorVisible(true);
2767354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mTextView.isCursorVisible());
2768fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCursorVisible(false);
2769354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertFalse(mTextView.isCursorVisible());
2770fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2771fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2772fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnWindowFocusChanged() {
2773fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
2774fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2775fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2776fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnTouchEvent() {
2777fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
2778fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2779fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2780fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnTrackballEvent() {
2781fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
2782fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2783fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2784fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTextColors() {
2785fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // TODO: How to get a suitable TypedArray to test this method.
2786fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2787fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2788fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnKeyShortcut() {
2789fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
2790fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2791fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2792fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2793fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testPerformLongClick() {
2794fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
2795fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText("This is content");
2796938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
2797938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        View.OnLongClickListener mockOnLongClickListener = mock(View.OnLongClickListener.class);
2798938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.TRUE);
2799938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
2800938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        View.OnCreateContextMenuListener mockOnCreateContextMenuListener =
2801938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                mock(View.OnCreateContextMenuListener.class);
28024e47d86641f4cbf8269723cca1a2ca1250f9aa02Kirill Grouchnikov        doAnswer((InvocationOnMock invocation) -> {
28034e47d86641f4cbf8269723cca1a2ca1250f9aa02Kirill Grouchnikov            ((ContextMenu) invocation.getArguments() [0]).add("menu item");
28044e47d86641f4cbf8269723cca1a2ca1250f9aa02Kirill Grouchnikov            return null;
2805938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        }).when(mockOnCreateContextMenuListener).onCreateContextMenu(
2806938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
2807938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
2808938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        mTextView.setOnLongClickListener(mockOnLongClickListener);
2809938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        mTextView.setOnCreateContextMenuListener(mockOnCreateContextMenuListener);
2810fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.performLongClick());
2811938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
2812938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verifyZeroInteractions(mockOnCreateContextMenuListener);
2813fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2814938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        reset(mockOnLongClickListener);
2815938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.FALSE);
2816fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.performLongClick());
2817938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
2818938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
2819938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
2820fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2821938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        reset(mockOnCreateContextMenuListener);
2822fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setOnLongClickListener(null);
2823938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        doNothing().when(mockOnCreateContextMenuListener).onCreateContextMenu(
2824938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
2825fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.performLongClick());
2826938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verifyNoMoreInteractions(mockOnLongClickListener);
2827938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
2828938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
2829fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2830fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2831fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2832fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testTextAttr() {
2833fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_textAttr);
2834fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getText
2835fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getString(R.string.text_view_hello), mTextView.getText().toString());
2836fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2837fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getCurrentTextColor
2838fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.black),
2839fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentTextColor());
2840fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.red),
2841fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentHintTextColor());
2842fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.red),
2843fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getHintTextColors().getDefaultColor());
2844fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
2845fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getLinkTextColors().getDefaultColor());
2846fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2847fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getTextScaleX
2848fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1.2f, mTextView.getTextScaleX(), 0.01f);
2849fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2850fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // setTextScaleX
2851fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextScaleX(2.4f);
2852fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2.4f, mTextView.getTextScaleX(), 0.01f);
2853fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2854fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextScaleX(0f);
2855fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0f, mTextView.getTextScaleX(), 0.01f);
2856fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2857fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextScaleX(- 2.4f);
2858fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(- 2.4f, mTextView.getTextScaleX(), 0.01f);
2859fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2860fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getTextSize
2861fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(20f, mTextView.getTextSize(), 0.01f);
2862fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2863fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // getTypeface
2864119351956fc53fdd61bfbfb0d1ab43857cf7a6d7Peter Eliasson        // getTypeface will be null if android:typeface is set to normal,
2865c02a9f453c5c1255d668bbd8970f4585ab5ff494Alan Viverette        // and android:style is not set or is set to normal, and
2866c02a9f453c5c1255d668bbd8970f4585ab5ff494Alan Viverette        // android:fontFamily is not set
2867fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getTypeface());
2868fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2869fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(Typeface.DEFAULT);
2870fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(Typeface.DEFAULT, mTextView.getTypeface());
2871fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // null type face
2872fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(null);
2873fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getTypeface());
2874fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2875fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // default type face, bold style, note: the type face will be changed
2876fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // after call set method
2877fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
2878fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(Typeface.BOLD, mTextView.getTypeface().getStyle());
2879fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2880fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // null type face, BOLD style
2881fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(null, Typeface.BOLD);
2882fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(Typeface.BOLD, mTextView.getTypeface().getStyle());
2883fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2884fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // old type face, null style
2885fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTypeface(Typeface.DEFAULT, 0);
2886fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Typeface.NORMAL, mTextView.getTypeface().getStyle());
2887fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2888fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2889fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
2890fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAppend() {
2891fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
2892fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2893fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 1: check the original length, should be blank as initialised.
2894fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getText().length());
2895fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2896fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 2: append a string use append(CharSquence) into the original blank
2897fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // buffer, check the content. And upgrading it to BufferType.EDITABLE if it was
2898fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // not already editable.
2899fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(mTextView.getText() instanceof Editable);
2900fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("Append.");
2901fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("Append.", mTextView.getText().toString());
2902fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
2903fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2904fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 3: append a string from 0~3.
2905fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("Append", 0, 3);
2906fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("Append.App", mTextView.getText().toString());
2907fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
2908fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2909fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 4: append a string from 0~0, nothing will be append as expected.
2910fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.append("Append", 0, 0);
2911fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals("Append.App", mTextView.getText().toString());
2912fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getText() instanceof Editable);
2913fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2914fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 5: append a string from -3~3. check the wrong left edge.
2915fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2916fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.append("Append", -3, 3);
2917fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw StringIndexOutOfBoundsException");
2918fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (StringIndexOutOfBoundsException e) {
2919fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2920fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2921fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 6: append a string from 3~10. check the wrong right edge.
2922fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2923fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.append("Append", 3, 10);
2924fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw StringIndexOutOfBoundsException");
2925fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (StringIndexOutOfBoundsException e) {
2926fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2927fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2928fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // 7: append a null string.
2929fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
2930fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView.append(null);
2931fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw NullPointerException");
2932fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
2933fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
2934fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
2935fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
2936f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
2937f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_doesNotAddLinksWhenAppendedTextDoesNotContainLinks() {
2938f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
2939f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
2940f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without URL");
2941f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2942f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" another text without URL");
2943f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2944f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
2945f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
2946f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be zero", 0, urlSpans.length);
2947f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text without URL another text without URL", text.toString());
2948f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
2949f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2950f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
2951f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_doesNotAddLinksWhenAutoLinkIsNotEnabled() {
2952f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
2953f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without URL");
2954f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2955f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with URL http://android.com");
2956f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2957f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
2958f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
2959f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be zero", 0, urlSpans.length);
2960f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text without URL text with URL http://android.com", text.toString());
2961f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
2962f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2963f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
2964f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinksWhenAutoLinkIsEnabled() {
2965f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
2966f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
2967f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without URL");
2968f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2969f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with URL http://android.com");
2970f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2971f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
2972f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
2973f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be one after appending a URL", 1, urlSpans.length);
2974f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
2975f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com");
2976f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text without URL text with URL http://android.com", text.toString());
2977f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
2978f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2979f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
2980f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinksEvenWhenThereAreUrlsSetBefore() {
2981f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
2982f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
2983f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text with URL http://android.com/before");
2984f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2985f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with URL http://android.com");
2986f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2987f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
2988f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
2989f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be two after appending another URL", 2, urlSpans.length);
2990f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("First URLSpan URL should be same",
2991f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com/before");
2992f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
2993f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[1].getURL(), "http://android.com");
2994f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("text with URL http://android.com/before text with URL http://android.com",
2995f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                text.toString());
2996f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
2997f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
2998f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
2999f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_setsMovementMethodWhenTextContainsUrlAndAutoLinkIsEnabled() {
3000f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3001f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3002f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without a URL");
3003f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3004f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(" text with a url: http://android.com");
3005f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3006f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertNotNull("MovementMethod should not be null when text contains url",
3007f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                mTextView.getMovementMethod());
3008f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertTrue("MovementMethod should be instance of LinkMovementMethod when text contains url",
3009f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                mTextView.getMovementMethod() instanceof LinkMovementMethod);
3010f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3011f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3012f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3013f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinksWhenTextIsSpannableAndContainsUrlAndAutoLinkIsEnabled() {
3014f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3015f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3016f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text without a URL");
3017f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3018f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append(new SpannableString(" text with a url: http://android.com"));
3019f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3020f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3021f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3022f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be one after appending a URL", 1, urlSpans.length);
3023f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
3024f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com");
3025f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3026f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3027f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3028f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinkIfAppendedTextCompletesPartialUrlAtTheEndOfExistingText() {
3029f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3030f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3031f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text with a partial url android.");
3032f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3033f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append("com");
3034f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3035f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3036f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3037f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should be one after appending to partial URL",
3038f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                1, urlSpans.length);
3039f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the appended URL",
3040f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com");
3041f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3042f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3043f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    @UiThreadTest
3044f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    public void testAppend_addsLinkIfAppendedTextUpdatesUrlAtTheEndOfExistingText() {
3045f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView = new TextView(mActivity);
3046f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setAutoLinkMask(Linkify.ALL);
3047f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.setText("text with a url http://android.com");
3048f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3049f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        mTextView.append("/textview");
3050f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3051f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        Spannable text = (Spannable) mTextView.getText();
3052f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
3053f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan count should still be one after extending a URL", 1, urlSpans.length);
3054f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir        assertEquals("URLSpan URL should be same as the new URL",
3055f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir                urlSpans[0].getURL(), "http://android.com/textview");
3056f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir    }
3057f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
30586a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
30596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetLetterSpacing_returnsValueThatWasSet() {
30606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = new TextView(mActivity);
30616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setLetterSpacing(2f);
30626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("getLetterSpacing should return the value that was set",
30636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                2f, mTextView.getLetterSpacing());
30646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
30656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
30676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testSetLetterSpacing_changesTextWidth() {
30686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(mActivity);
30696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText("aa");
30706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setLetterSpacing(0f);
30716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextSize(8f);
30726a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
30746a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
30756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT,
30766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT);
30776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.addView(textView, layoutParams);
30786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
30796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30806beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> getActivity().setContentView(layout));
30816a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        getInstrumentation().waitForIdleSync();
30826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // measure text with zero letter spacing
30846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final float zeroSpacing = textView.getLayout().getLineWidth(0);
30856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30866beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        getActivity().runOnUiThread(() -> textView.setLetterSpacing(1f));
30876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        getInstrumentation().waitForIdleSync();
30886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // measure text with single letter spacing
30906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final float singleSpacing = textView.getLayout().getLineWidth(0);
30916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30926beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        getActivity().runOnUiThread(() -> textView.setLetterSpacing(2f));
30936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        getInstrumentation().waitForIdleSync();
30946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // measure text with double letter spacing
30966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final float doubleSpacing = textView.getLayout().getLineWidth(0);
30976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
30986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("Double spacing should have two times the spacing of single spacing",
30996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                doubleSpacing - zeroSpacing, 2f * (singleSpacing - zeroSpacing), 1f);
31006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
31016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
31036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetFontFeatureSettings_returnsValueThatWasSet() {
31046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = new TextView(mActivity);
31056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setFontFeatureSettings("\"smcp\" on");
31066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals("getFontFeatureSettings should return the value that was set",
31076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                "\"smcp\" on", mTextView.getFontFeatureSettings());
31086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
31096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
31116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetOffsetForPosition_singleLineLtr() {
31126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // asserts getOffsetPosition returns correct values for a single line LTR text
31136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        String text = "aaaaa";
31146a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(mActivity);
31156a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText(text);
31166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextSize(8f);
31176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setSingleLine(true);
31186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // add a compound drawable to TextView to make offset calculation more interesting
3120a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable drawable = TestUtils.getDrawable(mActivity, R.drawable.red);
31216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawable.setBounds(0, 0, 10, 10);
31226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
31236a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
31256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
31266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
31276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
31286a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.addView(textView, layoutParams);
31296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
31306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3131023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.runOnMainSync(() -> getActivity().setContentView(layout));
3132023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.waitForIdleSync();
31336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int firstOffset = 0;
31356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int lastOffset = text.length() - 1;
31366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final int midOffset = text.length() / 2;
31376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view
31396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float x = 0f;
31406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float y = textView.getHeight() / 2f;
31416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(firstOffset, textView.getOffsetForPosition(x, y));
31426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of text
31446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getLayout().getLineWidth(0) - 1f;
31456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(lastOffset, textView.getOffsetForPosition(x, y));
31466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view
31486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getWidth();
31496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(lastOffset + 1, textView.getOffsetForPosition(x, y));
31506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view - out of bounds
31526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = -1f;
31536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(firstOffset, textView.getOffsetForPosition(x, y));
31546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // horizontal center of text
3156023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        x = (float) Math.floor(textView.getLayout().getLineWidth(0) / 2f + 0.5f);
31576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(midOffset, textView.getOffsetForPosition(x, y));
31586a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
31596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
31616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetOffsetForPosition_multiLineLtr() {
3162023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        final String line = "aaa\n";
31636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final String threeLines = line + line + line;
31646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(mActivity);
31656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText(threeLines);
31666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextSize(8f);
31676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setLines(2);
31686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // add a compound drawable to TextView to make offset calculation more interesting
3170a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable drawable = TestUtils.getDrawable(mActivity, R.drawable.red);
31716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawable.setBounds(0, 0, 10, 10);
31726a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
31736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31746a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
31756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
31766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
31776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
31786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.addView(textView, layoutParams);
31796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
31806a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3181023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.runOnMainSync(() -> getActivity().setContentView(layout));
3182023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.waitForIdleSync();
31836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final Rect lineBounds = new Rect();
31856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.getLayout().getLineBounds(0, lineBounds);
31866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at first line
31886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float x = 0f;
31896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float y = lineBounds.height() / 2f;
31906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, textView.getOffsetForPosition(x, y));
31916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at first line
31936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getWidth() - 1f;
31946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length() - 1, textView.getOffsetForPosition(x, y));
31956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
31966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // update lineBounds to be the second line
31976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.getLayout().getLineBounds(1, lineBounds);
31986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        y = lineBounds.top + lineBounds.height() / 2;
31996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at second line
32016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = 0f;
32026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length(), textView.getOffsetForPosition(x, y));
32036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of text at second line
32056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getLayout().getLineWidth(1) - 1f;
32066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
32076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at second line
32096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getWidth() - 1f;
32106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
32116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // horizontal center of text at second line
3213023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        x = (float) Math.floor(textView.getLayout().getLineWidth(1) / 2f + 0.5f);
32146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // second line mid offset should not include next line, therefore subtract one
3215023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        assertEquals(line.length() + (line.length() - 1) / 2, textView.getOffsetForPosition(x, y));
32166a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
32176a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32186a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
32196a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetOffsetForPosition_multiLineRtl() {
3220023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        final String line = "\u0635\u0635\u0635\n";
32216a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final String threeLines = line + line + line;
32226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(mActivity);
32236a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText(threeLines);
32246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextSize(8f);
32256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setLines(2);
32266a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32276a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // add a compound drawable to TextView to make offset calculation more interesting
3228a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable drawable = TestUtils.getDrawable(mActivity, R.drawable.red);
32296a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawable.setBounds(0, 0, 10, 10);
32306a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
32316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32326a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(mActivity);
32336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
32346a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
32356a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.WRAP_CONTENT);
32366a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.addView(textView, layoutParams);
32376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
32386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
3239023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.runOnMainSync(() -> getActivity().setContentView(layout));
3240023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        mInstrumentation.waitForIdleSync();
32416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final Rect lineBounds = new Rect();
32436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.getLayout().getLineBounds(0, lineBounds);
32446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at first line
32466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float x = textView.getWidth() - 1f;
32476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        float y = lineBounds.height() / 2f;
32486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(0, textView.getOffsetForPosition(x, y));
32496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at first line
32516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = 0f;
32526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length() - 1, textView.getOffsetForPosition(x, y));
32536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // update lineBounds to be the second line
32556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.getLayout().getLineBounds(1, lineBounds);
32566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        y = lineBounds.top + lineBounds.height() / 2f;
32576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32586a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of view at second line
32596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getWidth() - 1f;
32606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length(), textView.getOffsetForPosition(x, y));
32616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // left edge of view at second line
32636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = 0f;
32646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
32656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // right edge of text at second line
32676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        x = textView.getWidth() - textView.getLayout().getLineWidth(1) + 1f;
32686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
32696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // horizontal center of text at second line
3271023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        x = textView.getWidth() - (float) Math.floor(
3272023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir                textView.getLayout().getLineWidth(1) / 2f + 0.5f);
32736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        // second line mid offset should not include next line, therefore subtract one
3274023f7673deecf213c762bc7358faba360ccb16e1Siyamed Sinir        assertEquals(line.length() + (line.length() - 1) / 2, textView.getOffsetForPosition(x, y));
32756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
32766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
32786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testIsTextSelectable_returnsFalseByDefault() {
32796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(getActivity());
32806a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText("any text");
32816a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isTextSelectable());
32826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
32836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
32856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testIsTextSelectable_returnsTrueIfSetTextIsSelectableCalledWithTrue() {
32866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(getActivity());
32876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setText("any text");
32886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextIsSelectable(true);
32896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isTextSelectable());
32906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
32916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
32936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testSetIsTextSelectable() {
32946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(getActivity());
32956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
32966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isTextSelectable());
32976a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isFocusable());
32986a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isFocusableInTouchMode());
32996a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isClickable());
33006a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertFalse(textView.isLongClickable());
33016a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33026a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setTextIsSelectable(true);
33036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
33046a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isTextSelectable());
33056a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isFocusable());
33066a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isFocusableInTouchMode());
33076a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isClickable());
33086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(textView.isLongClickable());
33096a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(textView.getMovementMethod());
33106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
3311f6d7a3822a73508d4bfeb0f21e1adb325a62fd18Siyamed Sinir
3312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessTransformationMethod() {
3313fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check the password attribute in xml
3314fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_password);
3315fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView);
3316fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(PasswordTransformationMethod.getInstance(),
3317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTransformationMethod());
3318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check the singleLine attribute in xml
3320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_singleLine);
3321fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(mTextView);
3322fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(SingleLineTransformationMethod.getInstance(),
3323fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTransformationMethod());
3324fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3325fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final QwertyKeyListener qwertyKeyListener = QwertyKeyListener.getInstance(false,
3326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                Capitalize.NONE);
3327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final TransformationMethod method = PasswordTransformationMethod.getInstance();
3328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // change transformation method by function
33296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
33306beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setKeyListener(qwertyKeyListener);
33316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setTransformationMethod(method);
33326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTransformedText = method.getTransformation(mTextView.getText(), mTextView);
3333fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
33346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
3335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
3336fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3337fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(PasswordTransformationMethod.getInstance(),
3338fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getTransformationMethod());
3339fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
334003818d9cc48f51e2ef65eacb2cdf40d90260c29eSiyamed Sinir        mKeyEventUtil.sendKeys(mTextView, "H E 2*L O");
33416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.append(" "));
3342fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3343fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3344354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // It will get transformed after a while
3345354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // We're waiting for transformation to "******"
3346354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(TIMEOUT, () -> mTransformedText.toString()
3347354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov                .equals("\u2022\u2022\u2022\u2022\u2022\u2022"));
3348fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3349fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set null
33506beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setTransformationMethod(null));
3351fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3352fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(mTextView.getTransformationMethod());
3353fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3354fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3355fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3356fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testCompound() {
3357fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3358fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int padding = 3;
3359fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Drawable[] drawables = mTextView.getCompoundDrawables();
3360fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[0]);
3361fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[1]);
3362fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[2]);
3363fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3364fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3365fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test setCompoundDrawablePadding and getCompoundDrawablePadding
3366fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawablePadding(padding);
3367fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(padding, mTextView.getCompoundDrawablePadding());
3368fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3369fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using resid, 0 represents null
3370fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.start, R.drawable.pass,
3371fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                R.drawable.failed, 0);
3372fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        drawables = mTextView.getCompoundDrawables();
3373fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3374fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableLeft
3375a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        WidgetTestUtils.assertEquals(TestUtils.getBitmap(mActivity, R.drawable.start),
3376fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                ((BitmapDrawable) drawables[0]).getBitmap());
3377fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableTop
3378a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        WidgetTestUtils.assertEquals(TestUtils.getBitmap(mActivity, R.drawable.pass),
3379fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                ((BitmapDrawable) drawables[1]).getBitmap());
3380fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableRight
3381a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        WidgetTestUtils.assertEquals(TestUtils.getBitmap(mActivity, R.drawable.failed),
3382fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                ((BitmapDrawable) drawables[2]).getBitmap());
3383fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableBottom
3384fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3385fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3386a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable left = TestUtils.getDrawable(mActivity, R.drawable.blue);
3387a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable right = TestUtils.getDrawable(mActivity, R.drawable.yellow);
3388a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3389fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3390fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // using drawables directly
3391fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawablesWithIntrinsicBounds(left, top, right, null);
3392fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        drawables = mTextView.getCompoundDrawables();
3393fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3394fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableLeft
3395fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(left, drawables[0]);
3396fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableTop
3397fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(top, drawables[1]);
3398fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableRight
3399fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(right, drawables[2]);
3400fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableBottom
3401fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3402fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3403fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check compound padding
3404fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingLeft() + padding + left.getIntrinsicWidth(),
3405fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingLeft());
3406fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingTop() + padding + top.getIntrinsicHeight(),
3407fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingTop());
3408fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingRight() + padding + right.getIntrinsicWidth(),
3409fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingRight());
3410fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingBottom(), mTextView.getCompoundPaddingBottom());
3411fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3412fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set bounds to drawables and set them again.
3413fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        left.setBounds(0, 0, 1, 2);
3414fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        right.setBounds(0, 0, 3, 4);
3415fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        top.setBounds(0, 0, 5, 6);
3416fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // usinf drawables
3417fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(left, top, right, null);
3418fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        drawables = mTextView.getCompoundDrawables();
3419fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3420fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableLeft
3421fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(left, drawables[0]);
3422fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableTop
3423fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(top, drawables[1]);
3424fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableRight
3425fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(right, drawables[2]);
3426fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // drawableBottom
3427fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(drawables[3]);
3428fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3429fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // check compound padding
3430fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingLeft() + padding + left.getBounds().width(),
3431fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingLeft());
3432fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingTop() + padding + top.getBounds().height(),
3433fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingTop());
3434fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingRight() + padding + right.getBounds().width(),
3435fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCompoundPaddingRight());
3436fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getPaddingBottom(), mTextView.getCompoundPaddingBottom());
3437fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3438fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
34396a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
34406a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @UiThreadTest
34416a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetCompoundDrawablesRelative() {
34426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // prepare textview
34436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView = new TextView(mActivity);
34446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        // prepare drawables
3446a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable start = TestUtils.getDrawable(mActivity, R.drawable.blue);
3447a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable end = TestUtils.getDrawable(mActivity, R.drawable.yellow);
3448a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3449a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable bottom = TestUtils.getDrawable(mActivity, R.drawable.black);
34506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(start);
34516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(end);
34526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(top);
34536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(bottom);
34546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34556a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        Drawable[] drawables = mTextView.getCompoundDrawablesRelative();
34566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
34576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
34586a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[0]);
34596a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[1]);
34606a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[2]);
34616a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[3]);
34626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
34646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
34656a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawables = mTextView.getCompoundDrawablesRelative();
34666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34676a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
34686a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
34696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(start, drawables[0]);
34706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(top, drawables[1]);
34716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(end, drawables[2]);
34726a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(bottom, drawables[3]);
34736a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34746a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
34756a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
34766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawables = mTextView.getCompoundDrawablesRelative();
34776a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34786a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
34796a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
34806a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(start, drawables[0]);
34816a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(top, drawables[1]);
34826a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(end, drawables[2]);
34836a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertSame(bottom, drawables[3]);
34846a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34856a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mTextView.setCompoundDrawablesRelative(null, null, null, null);
34866a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        drawables = mTextView.getCompoundDrawablesRelative();
34876a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34886a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNotNull(drawables);
34896a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(4, drawables.length);
34906a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[0]);
34916a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[1]);
34926a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[2]);
34936a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertNull(drawables[3]);
34946a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
34956a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
34966a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
3497fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSingleLine() {
3498013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        final TextView textView = new TextView(mActivity);
3499013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        setSpannableText(textView, "This is a really long sentence"
3500013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu                + " which can not be placed in one line on the screen.");
3501013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu
3502013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        // Narrow layout assures that the text will get wrapped.
35036a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout innerLayout = new FrameLayout(mActivity);
3504013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        innerLayout.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
3505013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        innerLayout.addView(textView);
3506013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu
3507013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        final FrameLayout layout = new FrameLayout(mActivity);
3508013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        layout.addView(innerLayout);
3509013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu
35106beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
35116beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.setContentView(layout);
35126beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            textView.setSingleLine(true);
3513013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        });
3514013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        mInstrumentation.waitForIdleSync();
3515fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3516fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(SingleLineTransformationMethod.getInstance(),
3517013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu                textView.getTransformationMethod());
3518da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
3519da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        int singleLineWidth = 0;
3520da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        int singleLineHeight = 0;
3521da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
3522da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        if (textView.getLayout() != null) {
3523da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu            singleLineWidth = textView.getLayout().getWidth();
3524da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu            singleLineHeight = textView.getLayout().getHeight();
3525da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        }
3526fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
35276beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> textView.setSingleLine(false));
3528fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3529013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu        assertEquals(null, textView.getTransformationMethod());
3530da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
3531da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        if (textView.getLayout() != null) {
3532da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu            assertTrue(textView.getLayout().getHeight() > singleLineHeight);
3533da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu            assertTrue(textView.getLayout().getWidth() < singleLineWidth);
3534da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        }
3535fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3536fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // same behaviours as setSingLine(true)
35376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> textView.setSingleLine());
3538fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3539fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(SingleLineTransformationMethod.getInstance(),
3540013d5ee5428a0fde1cbe1befa4587b0d7a5e39c1Brian Muramatsu                textView.getTransformationMethod());
3541da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu
3542da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        if (textView.getLayout() != null) {
3543da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu            assertEquals(singleLineHeight, textView.getLayout().getHeight());
3544da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu            assertEquals(singleLineWidth, textView.getLayout().getWidth());
3545da492b574cec4f919a3952d3e03b098e7eb01ffeWei Liu        }
3546fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3547fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3548fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
354998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov    public void testAccessMaxLines() {
3550fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3551fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3552fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        float[] widths = new float[LONG_TEXT.length()];
3553fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.getPaint().getTextWidths(LONG_TEXT, widths);
3554fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        float totalWidth = 0.0f;
3555fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        for (float f : widths) {
3556fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            totalWidth += f;
3557fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
3558fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int stringWidth = (int) totalWidth;
3559fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(stringWidth >> 2);
3560fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(LONG_TEXT);
3561fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3562fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        final int maxLines = 2;
3563fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineCount() > maxLines);
3564fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3565fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setMaxLines(maxLines);
3566fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.requestLayout();
3567fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
356898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(2, mTextView.getMaxLines());
356998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMaxHeight());
3570fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getHeight() <= maxLines * mTextView.getLineHeight());
3571fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3572fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3573636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    public int calculateTextWidth(String text) {
3574636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        mTextView = findTextView(R.id.textview_text);
3575636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3576636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        // Set the TextView width as the half of the whole text.
3577636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        float[] widths = new float[text.length()];
3578636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        mTextView.getPaint().getTextWidths(text, widths);
3579636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        float textfieldWidth = 0.0f;
3580636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        for (int i = 0; i < text.length(); ++i) {
3581636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            textfieldWidth += widths[i];
3582636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        }
3583636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        return (int)textfieldWidth;
3584636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3585636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    }
3586636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3587636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    @UiThreadTest
3588636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    public void testHyphenationNotHappen_frequencyNone() {
3589636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        final int[] BREAK_STRATEGIES = {
3590636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.BREAK_STRATEGY_SIMPLE, Layout.BREAK_STRATEGY_HIGH_QUALITY,
3591636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.BREAK_STRATEGY_BALANCED };
3592636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3593636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        mTextView = findTextView(R.id.textview_text);
3594636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3595636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        for (int breakStrategy : BREAK_STRATEGIES) {
3596636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            for (int charWidth = 10; charWidth < 120; charWidth += 5) {
3597636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                // Change the text view's width to charWidth width.
3598636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setWidth(calculateTextWidth(LONG_TEXT.substring(0, charWidth)));
3599636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3600636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setText(LONG_TEXT);
3601636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setBreakStrategy(breakStrategy);
3602636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3603636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
3604636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3605636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.requestLayout();
3606636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.onPreDraw();  // For freezing the layout.
3607636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                Layout layout = mTextView.getLayout();
3608636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3609636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                final int lineCount = layout.getLineCount();
3610636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                for (int line = 0; line < lineCount; ++line) {
3611636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    final int lineEnd = layout.getLineEnd(line);
3612636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // In any width, any break strategy, hyphenation should not happen if
3613636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // HYPHENATION_FREQUENCY_NONE is specified.
3614636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    assertTrue(lineEnd == LONG_TEXT.length() ||
3615636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                            Character.isWhitespace(LONG_TEXT.charAt(lineEnd - 1)));
3616636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                }
3617636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            }
3618636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        }
3619636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    }
3620636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3621636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    @UiThreadTest
3622636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    public void testHyphenationNotHappen_breakStrategySimple() {
3623636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        final int[] HYPHENATION_FREQUENCIES = {
3624636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.HYPHENATION_FREQUENCY_NORMAL, Layout.HYPHENATION_FREQUENCY_FULL,
3625636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            Layout.HYPHENATION_FREQUENCY_NONE };
3626636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3627636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        mTextView = findTextView(R.id.textview_text);
3628636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3629636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        for (int hyphenationFrequency: HYPHENATION_FREQUENCIES) {
3630636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            for (int charWidth = 10; charWidth < 120; charWidth += 5) {
3631636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                // Change the text view's width to charWidth width.
3632636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setWidth(calculateTextWidth(LONG_TEXT.substring(0, charWidth)));
3633636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3634636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setText(LONG_TEXT);
3635636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
3636636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3637636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.setHyphenationFrequency(hyphenationFrequency);
3638636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3639636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.requestLayout();
3640636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                mTextView.onPreDraw();  // For freezing the layout.
3641636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                Layout layout = mTextView.getLayout();
3642636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3643636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                final int lineCount = layout.getLineCount();
3644636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                for (int line = 0; line < lineCount; ++line) {
3645636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    final int lineEnd = layout.getLineEnd(line);
3646636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // In any width, any hyphenation frequency, hyphenation should not happen if
3647636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    // BREAK_STRATEGY_SIMPLE is specified.
3648636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                    assertTrue(lineEnd == LONG_TEXT.length() ||
3649636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                            Character.isWhitespace(LONG_TEXT.charAt(lineEnd - 1)));
3650636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka                }
3651636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka            }
3652636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka        }
3653636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka    }
3654636e9b2547b13f54b22ffd1451d5625a5183a4cdSeigo Nonaka
3655fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3656fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetMaxLinesException() {
365772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
365872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mActivity.setContentView(mTextView);
3659fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(mTextView.getWidth() >> 3);
366072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setMaxLines(-1);
3661fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3662fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
366398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov    public void testAccessMinLines() {
3664fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3665fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setWidth(mTextView.getWidth() >> 3);
3666fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int originalLines = mTextView.getLineCount();
3667fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3668fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinLines(originalLines - 1);
3669fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines - 1) * mTextView.getLineHeight() <= mTextView.getHeight());
367098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalLines - 1, mTextView.getMinLines());
367198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinHeight());
3672fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3673fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setMinLines(originalLines + 1);
3674fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines + 1) * mTextView.getLineHeight() <= mTextView.getHeight());
367598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(originalLines + 1, mTextView.getMinLines());
367698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(-1, mTextView.getMinHeight());
3677fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3678fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3679fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetLines() {
3680fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3681fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make it multiple lines
3682fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setWidth(mTextView.getWidth() >> 3);
3683fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int originalLines = mTextView.getLineCount();
3684fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3685fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(originalLines - 1);
3686fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines - 1) * mTextView.getLineHeight() <= mTextView.getHeight());
3687fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3688fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(originalLines + 1);
3689fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue((originalLines + 1) * mTextView.getLineHeight() <= mTextView.getHeight());
3690fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3691fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3692fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3693fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetLinesException() {
369472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
369572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mActivity.setContentView(mTextView);
369672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setWidth(mTextView.getWidth() >> 3);
369772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setLines(-1);
3698fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3699fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3700fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3701fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetExtendedPaddingTop() {
3702fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3703fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3704fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getExtendedPaddingTop());
3705fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3706fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3707a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3708fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        top.setBounds(0, 0, 100, 10);
3709fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(null, top, null, null);
3710fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingTop(), mTextView.getExtendedPaddingTop());
3711fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3712fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
3713fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLines(mTextView.getLineCount() - 1);
3714fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.BOTTOM);
3715fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3716fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getExtendedPaddingTop() > 0);
3717fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3718fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3719fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3720fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetExtendedPaddingBottom() {
3721fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3722fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3723fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getExtendedPaddingBottom());
3724fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3725fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3726a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable bottom = TestUtils.getDrawable(mActivity, R.drawable.red);
3727fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        bottom.setBounds(0, 0, 100, 10);
3728fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(null, null, null, bottom);
3729fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingBottom(), mTextView.getExtendedPaddingBottom());
3730fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3731fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
3732fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setLines(mTextView.getLineCount() - 1);
3733fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.CENTER_VERTICAL);
3734fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3735fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getExtendedPaddingBottom() > 0);
3736fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3737fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3738fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTotalPaddingTop() {
3739fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3740fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3741fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingTop());
3742fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3743fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3744a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable top = TestUtils.getDrawable(mActivity, R.drawable.red);
3745fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        top.setBounds(0, 0, 100, 10);
37466beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
37476beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setCompoundDrawables(null, top, null, null);
37486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setLines(mTextView.getLineCount() - 1);
37496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.BOTTOM);
3750fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
3751fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3752fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getExtendedPaddingTop(), mTextView.getTotalPaddingTop());
3753fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3754fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
3755fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(mTextView.getLineCount() + 1);
3756fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int expected = mTextView.getHeight()
3757fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getExtendedPaddingBottom()
3758fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getLayout().getLineTop(mTextView.getLineCount());
3759fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, mTextView.getTotalPaddingTop());
3760fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3761fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3762fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTotalPaddingBottom() {
3763fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3764fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3765fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingBottom());
3766fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3767fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3768a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        final Drawable bottom = TestUtils.getDrawable(mActivity, R.drawable.red);
3769fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        bottom.setBounds(0, 0, 100, 10);
37706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
37716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setCompoundDrawables(null, null, null, bottom);
37726beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setLines(mTextView.getLineCount() - 1);
37736beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setGravity(Gravity.CENTER_VERTICAL);
3774fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        });
3775fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
3776fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getExtendedPaddingBottom(), mTextView.getTotalPaddingBottom());
3777fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3778fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change line count
3779fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setLines(mTextView.getLineCount() + 1);
3780fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        int expected = ((mTextView.getHeight()
3781fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getExtendedPaddingBottom()
3782fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getExtendedPaddingTop()
3783fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                - mTextView.getLayout().getLineBottom(mTextView.getLineCount())) >> 1)
3784fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                + mTextView.getExtendedPaddingBottom();
3785fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(expected, mTextView.getTotalPaddingBottom());
3786fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3787fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3788fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3789fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTotalPaddingLeft() {
3790fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3791fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3792fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingLeft());
3793fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3794fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3795a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable left = TestUtils.getDrawable(mActivity, R.drawable.red);
3796fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        left.setBounds(0, 0, 10, 100);
3797fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(left, null, null, null);
3798fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.RIGHT);
3799fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingLeft(), mTextView.getTotalPaddingLeft());
3800fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3801fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change width
3802fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(Integer.MAX_VALUE);
3803fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingLeft(), mTextView.getTotalPaddingLeft());
3804fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3805fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3806fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    @UiThreadTest
3807fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetTotalPaddingRight() {
3808fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3809fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Initialized value
3810fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getTotalPaddingRight());
3811fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3812fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // After Set a Drawable
3813a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable right = TestUtils.getDrawable(mActivity, R.drawable.red);
3814fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        right.setBounds(0, 0, 10, 100);
3815fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setCompoundDrawables(null, null, right, null);
3816fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setGravity(Gravity.CENTER_HORIZONTAL);
3817fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingRight(), mTextView.getTotalPaddingRight());
3818fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3819fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Change width
3820fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setWidth(Integer.MAX_VALUE);
3821fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mTextView.getCompoundPaddingRight(), mTextView.getTotalPaddingRight());
3822fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3823fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3824fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetUrls() {
3825fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3826fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3827fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        URLSpan[] spans = mTextView.getUrls();
3828fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, spans.length);
3829fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3830fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String url = "http://www.google.com";
3831fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String email = "name@gmail.com";
3832fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        String string = url + " mailto:" + email;
3833fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        SpannableString spannable = new SpannableString(string);
3834fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spannable.setSpan(new URLSpan(url), 0, url.length(), 0);
3835fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(spannable, BufferType.SPANNABLE);
3836fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = mTextView.getUrls();
3837fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, spans.length);
3838fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(url, spans[0].getURL());
3839fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3840fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spannable.setSpan(new URLSpan(email), 0, email.length(), 0);
3841fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(spannable, BufferType.SPANNABLE);
3842fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3843fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = mTextView.getUrls();
3844fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, spans.length);
3845fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(url, spans[0].getURL());
3846fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(email, spans[1].getURL());
3847fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3848fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test the situation that param what is not a URLSpan
3849fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spannable.setSpan(new Object(), 0, 9, 0);
3850fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setText(spannable, BufferType.SPANNABLE);
3851fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        spans = mTextView.getUrls();
3852fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, spans.length);
3853fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3854fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3855fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetPadding() {
3856fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3857fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3858fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPadding(0, 1, 2, 4);
3859fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, mTextView.getPaddingLeft());
3860fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getPaddingTop());
3861fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(2, mTextView.getPaddingRight());
3862fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(4, mTextView.getPaddingBottom());
3863fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3864fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setPadding(10, 20, 30, 40);
3865fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(10, mTextView.getPaddingLeft());
3866fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(20, mTextView.getPaddingTop());
3867fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(30, mTextView.getPaddingRight());
3868fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(40, mTextView.getPaddingBottom());
3869fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3870fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3871fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    public void testDeprecatedSetTextAppearance() {
3872fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = new TextView(mActivity);
3873fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3874fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_All);
3875fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.black),
3876fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentTextColor());
3877fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(20f, mTextView.getTextSize(), 0.01f);
3878fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Typeface.BOLD, mTextView.getTypeface().getStyle());
3879fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.red),
3880fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentHintTextColor());
3881fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
3882fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getLinkTextColors().getDefaultColor());
3883fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3884fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_Colors);
3885fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.black),
3886fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentTextColor());
3887fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
3888fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getCurrentHintTextColor());
3889fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
3890fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                mTextView.getLinkTextColors().getDefaultColor());
3891fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3892fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_NotColors);
3893fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(17f, mTextView.getTextSize(), 0.01f);
3894fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(Typeface.NORMAL, mTextView.getTypeface().getStyle());
3895fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3896fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView.setTextAppearance(mActivity, R.style.TextAppearance_Style);
3897fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(null, mTextView.getTypeface());
3898fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3899fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3900fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    public void testSetTextAppearance() {
3901fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView = new TextView(mActivity);
3902fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3903fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_All);
3904fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.black),
3905fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentTextColor());
3906fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(20f, mTextView.getTextSize(), 0.01f);
3907fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(Typeface.BOLD, mTextView.getTypeface().getStyle());
3908fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.red),
3909fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentHintTextColor());
3910fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
3911fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getLinkTextColors().getDefaultColor());
39126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
39136a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                mTextView.getHighlightColor());
3914fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3915fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_Colors);
3916fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.black),
3917fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentTextColor());
3918fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.blue),
3919fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getCurrentHintTextColor());
3920fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
3921fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai                mTextView.getLinkTextColors().getDefaultColor());
39226a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(mActivity.getResources().getColor(R.drawable.red),
39236a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                mTextView.getHighlightColor());
3924fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3925fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_NotColors);
3926fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(17f, mTextView.getTextSize(), 0.01f);
3927fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(Typeface.NORMAL, mTextView.getTypeface().getStyle());
3928fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3929fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setTextAppearance(R.style.TextAppearance_Style);
3930fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(null, mTextView.getTypeface());
3931fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    }
3932fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3933fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnPreDraw() {
3934fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
3935fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3936fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3937fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    public void testAccessCompoundDrawableTint() {
3938fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView = new TextView(mActivity);
3939fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3940fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        ColorStateList colors = ColorStateList.valueOf(Color.RED);
3941fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setCompoundDrawableTintList(colors);
3942fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        mTextView.setCompoundDrawableTintMode(PorterDuff.Mode.XOR);
3943fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertSame(colors, mTextView.getCompoundDrawableTintList());
3944fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
3945f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette
3946f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        // Ensure the tint is preserved across drawable changes.
3947f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        mTextView.setCompoundDrawablesRelative(null, null, null, null);
3948f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertSame(colors, mTextView.getCompoundDrawableTintList());
3949f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
3950f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette
3951f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        mTextView.setCompoundDrawables(null, null, null, null);
3952f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertSame(colors, mTextView.getCompoundDrawableTintList());
3953f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
3954f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette
3955f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr1 = new ColorDrawable(Color.RED);
3956f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr2 = new ColorDrawable(Color.GREEN);
3957f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr3 = new ColorDrawable(Color.BLUE);
3958f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        ColorDrawable dr4 = new ColorDrawable(Color.YELLOW);
3959f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        mTextView.setCompoundDrawables(dr1, dr2, dr3, dr4);
3960f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertSame(colors, mTextView.getCompoundDrawableTintList());
3961f7773bad2586cf5562f81e49ad5353396744542eAlan Viverette        assertEquals(PorterDuff.Mode.XOR, mTextView.getCompoundDrawableTintMode());
3962fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai    }
3963fc8d65e3fed8c61cd1cb442ecafc24ecf2a9a56bJun Mukai
3964fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetHorizontallyScrolling() {
3965fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make the text view has more than one line
3966fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mTextView = findTextView(R.id.textview_text);
3967fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setWidth(mTextView.getWidth() >> 1);
3968fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineCount() > 1);
3969fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3970fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setHorizontallyScrolling(true);
3971fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(1, mTextView.getLineCount());
3972fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3973fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        setHorizontallyScrolling(false);
3974fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(mTextView.getLineCount() > 1);
3975fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3976fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3977fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testComputeHorizontalScrollRange() {
3978fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
3979fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test when layout is null
3980fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getLayout());
3981fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(textView.getWidth(), textView.computeHorizontalScrollRange());
3982fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3983fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setFrame(0, 0, 40, 50);
3984fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(textView.getWidth(), textView.computeHorizontalScrollRange());
3985fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3986fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // set the layout
3987fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(textView);
3988fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(textView.getLayout().getWidth(), textView.computeHorizontalScrollRange());
3989fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
3990fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3991fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testComputeVerticalScrollRange() {
3992fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
3993fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // test when layout is null
3994fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getLayout());
3995fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(0, textView.computeVerticalScrollRange());
3996fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
3997fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setFrame(0, 0, 40, 50);
3998fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(textView.getHeight(), textView.computeVerticalScrollRange());
3999fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4000fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //set the layout
4001fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        layout(textView);
4002fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(textView.getLayout().getHeight(), textView.computeVerticalScrollRange());
4003fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4004fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4005fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testDrawableStateChanged() {
4006b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        MockTextView textView = spy(new MockTextView(mActivity));
4007b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        reset(textView);
4008fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.refreshDrawableState();
4009b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(textView, times(1)).drawableStateChanged();
4010fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4011fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4012fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetDefaultEditable() {
4013fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
4014fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4015fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //the TextView#getDefaultEditable() does nothing, and always return false.
4016fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(textView.getDefaultEditable());
4017fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4018fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4019fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testGetDefaultMovementMethod() {
4020fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
4021fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4022fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //the TextView#getDefaultMovementMethod() does nothing, and always return null.
4023fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getDefaultMovementMethod());
4024fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4025fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4026fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnCreateContextMenu() {
4027fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4028fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4029fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4030fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnDetachedFromWindow() {
4031fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4032fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4033fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4034fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnDraw() {
4035fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4036fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4037fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4038fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnFocusChanged() {
4039fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4040fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4041fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4042fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnMeasure() {
4043fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4044fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4045fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4046fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnTextChanged() {
4047fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4048fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4049fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4050fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testSetFrame() {
4051fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        MockTextView textView = new MockTextView(mActivity);
4052fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4053fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //Assign a new size to this view
4054fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.setFrame(0, 0, 320, 480));
4055b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(0, textView.getLeft());
4056b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(0, textView.getTop());
4057b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(320, textView.getRight());
4058b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(480, textView.getBottom());
4059fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4060fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //Assign a same size to this view
4061fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(textView.setFrame(0, 0, 320, 480));
4062fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4063fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        //negative input
4064fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.setFrame(-1, -1, -1, -1));
4065b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getLeft());
4066b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getTop());
4067b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getRight());
4068b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        assertEquals(-1, textView.getBottom());
4069fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4070fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4071fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testMarquee() {
4072354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Both are pointing to the same object. This works around current limitation in CTS
4073354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // coverage report tool for properly reporting coverage of base class method calls.
4074354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final MockTextView mockTextView = new MockTextView(mActivity);
4075354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final TextView textView = mockTextView;
4076354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
4077fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setText(LONG_TEXT);
4078fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setSingleLine();
4079fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setEllipsize(TruncateAt.MARQUEE);
4080bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu        textView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
4081bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu
4082bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu        final FrameLayout layout = new FrameLayout(mActivity);
4083bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu        layout.addView(textView);
4084bed9d222439713a766c3d5c91fae1526b5bc35dcBrian Muramatsu
4085fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // make the fading to be shown
4086fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setHorizontalFadingEdgeEnabled(true);
4087fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4088354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> mActivity.setContentView(layout));
4089fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4090fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4091fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TestSelectedRunnable runnable = new TestSelectedRunnable(textView) {
4092fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            public void run() {
4093fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                textView.setMarqueeRepeatLimit(-1);
4094fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                // force the marquee to start
4095fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected1();
4096fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                textView.setSelected(true);
4097fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected2();
4098fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            }
4099fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        };
4100fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.runOnUiThread(runnable);
4101fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4102fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // wait for the marquee to run
4103fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // fading is shown on both sides if the marquee runs for a while
4104354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(TIMEOUT, () -> mockTextView.getLeftFadingEdgeStrength() > 0.0f
4105354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov                && mockTextView.getRightFadingEdgeStrength() > 0.0f);
4106fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
41070f095ca986d7558f9f5260c71a12cef4474d9da3Siyamed Sinir        // wait for left marquee to fully apply
4108354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(TIMEOUT, () -> mockTextView.getLeftFadingEdgeStrength() > 0.99f);
4109354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
4110fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(runnable.getIsSelected1());
4111fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(runnable.getIsSelected2());
4112354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(-1, textView.getMarqueeRepeatLimit());
4113fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4114fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        runnable = new TestSelectedRunnable(textView) {
4115fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            public void run() {
4116fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                textView.setMarqueeRepeatLimit(0);
4117fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                // force the marquee to stop
4118fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected1();
4119fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                textView.setSelected(false);
4120fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                saveIsSelected2();
4121fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                textView.setGravity(Gravity.LEFT);
4122fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            }
4123fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        };
4124fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // force the marquee to stop
4125fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mActivity.runOnUiThread(runnable);
4126fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4127fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(runnable.getIsSelected1());
4128fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertFalse(runnable.getIsSelected2());
4129354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(0.0f, mockTextView.getLeftFadingEdgeStrength(), 0.01f);
4130354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mockTextView.getRightFadingEdgeStrength() > 0.0f);
4131354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(0, textView.getMarqueeRepeatLimit());
4132fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4133354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setGravity(Gravity.RIGHT));
4134fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4135354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mockTextView.getLeftFadingEdgeStrength() > 0.0f);
4136354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(0.0f, mockTextView.getRightFadingEdgeStrength(), 0.01f);
4137fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4138354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setGravity(Gravity.CENTER_HORIZONTAL));
4139fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
4140fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // there is no left fading (Is it correct?)
4141354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(0.0f, mockTextView.getLeftFadingEdgeStrength(), 0.01f);
4142354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mockTextView.getRightFadingEdgeStrength() > 0.0f);
4143fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4144fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
41456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
41466a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testGetMarqueeRepeatLimit() {
41476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final TextView textView = new TextView(mActivity);
41486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
41496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        textView.setMarqueeRepeatLimit(10);
41506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertEquals(10, textView.getMarqueeRepeatLimit());
41516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
41526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4153fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnKeyMultiple() {
4154fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4155fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4156fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4157fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessInputExtras() throws XmlPullParserException, IOException {
4158fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView textView = new TextView(mActivity);
4159fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setText(null, BufferType.EDITABLE);
4160fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_TEXT);
4161fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4162fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // do not create the extras
4163fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getInputExtras(false));
4164fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4165fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // create if it does not exist
4166fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        Bundle inputExtras = textView.getInputExtras(true);
4167fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(inputExtras);
4168fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(inputExtras.isEmpty());
4169fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4170fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // it is created already
4171fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNotNull(textView.getInputExtras(false));
4172fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4173fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        try {
4174fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            textView.setInputExtras(R.xml.input_extras);
4175fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            fail("Should throw NullPointerException!");
4176fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        } catch (NullPointerException e) {
4177fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
4178fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4179fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4180fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessContentType() {
4181fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView textView = new TextView(mActivity);
4182fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setText(null, BufferType.EDITABLE);
4183fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setKeyListener(null);
4184fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setTransformationMethod(null);
4185fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4186fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_DATETIME
4187fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_NORMAL);
4188fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
4189fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_NORMAL, textView.getInputType());
4190fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getKeyListener() instanceof DateTimeKeyListener);
4191fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4192fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_DATETIME
4193fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_DATE);
4194fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
4195fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_DATE, textView.getInputType());
4196fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getKeyListener() instanceof DateKeyListener);
4197fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4198fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_DATETIME
4199fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_TIME);
4200fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
4201fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_TIME, textView.getInputType());
4202fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getKeyListener() instanceof TimeKeyListener);
4203fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4204fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_NUMBER
4205fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
4206fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_SIGNED);
4207fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_NUMBER
4208fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
4209fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_SIGNED, textView.getInputType());
4210fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(textView.getKeyListener(), DigitsKeyListener.getInstance(true, true));
4211fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4212fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_PHONE);
4213fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_PHONE, textView.getInputType());
4214fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getKeyListener() instanceof DialerKeyListener);
4215fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4216fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_TEXT
4217fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
4218fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4219fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT, textView.getInputType());
4220fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(textView.getKeyListener(), TextKeyListener.getInstance(true, Capitalize.NONE));
4221fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4222fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setSingleLine();
4223fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4224fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_TEXT
4225fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
4226fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
4227fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4228fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
4229fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS, textView.getInputType());
4230fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(textView.getKeyListener(),
4231fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                TextKeyListener.getInstance(false, Capitalize.CHARACTERS));
4232fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4233fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4234fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_TEXT
4235fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
4236fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4237fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_WORDS, textView.getInputType());
4238fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(textView.getKeyListener(),
4239fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                TextKeyListener.getInstance(false, Capitalize.WORDS));
4240fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4241fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4242fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_CLASS_TEXT
4243fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
4244fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4245fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES, textView.getInputType());
4246fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertSame(textView.getKeyListener(),
4247fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                TextKeyListener.getInstance(false, Capitalize.SENTENCES));
4248fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4249fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setInputType(InputType.TYPE_NULL);
4250fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_NULL, textView.getInputType());
4251fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getKeyListener() instanceof TextKeyListener);
4252fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4253fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4254fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testAccessRawContentType() {
4255fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        TextView textView = new TextView(mActivity);
4256fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setText(null, BufferType.EDITABLE);
4257fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setKeyListener(null);
4258fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setTransformationMethod(null);
4259fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4260fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_DATETIME
4261fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_NORMAL);
4262fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
4263fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_NORMAL, textView.getInputType());
4264fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4265fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4266fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4267fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_DATETIME
4268fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_DATE);
4269fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
4270fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_DATE, textView.getInputType());
4271fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4272fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4273fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4274fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_DATETIME
4275fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_TIME);
4276fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_DATETIME
4277fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_DATETIME_VARIATION_TIME, textView.getInputType());
4278fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4279fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4280fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4281fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_NUMBER
4282fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
4283fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_SIGNED);
4284fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_NUMBER
4285fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_DECIMAL
4286fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_NUMBER_FLAG_SIGNED, textView.getInputType());
4287fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4288fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4289fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4290fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_PHONE);
4291fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_PHONE, textView.getInputType());
4292fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4293fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4294fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4295fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_TEXT
4296fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
4297fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4298fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT, textView.getInputType());
4299fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getTransformationMethod());
4300fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4301fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4302fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setSingleLine();
4303fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4304fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_TEXT
4305fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
4306fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
4307fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4308fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
4309fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS, textView.getInputType());
4310fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4311fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4312fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4313fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_TEXT
4314fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
4315fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4316fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_WORDS, textView.getInputType());
4317fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4318fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4319fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4320fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_CLASS_TEXT
4321fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
4322fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertEquals(InputType.TYPE_CLASS_TEXT
4323fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES, textView.getInputType());
4324fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4325fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4326fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4327fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        textView.setRawInputType(InputType.TYPE_NULL);
4328fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
4329fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        assertNull(textView.getKeyListener());
4330fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4331fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
4332fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    public void testOnPrivateIMECommand() {
4333fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        // Do not test. Implementation details.
4334fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
4335fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
433672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testFoo() {
433772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // Do not test. Implementation details.
433872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
433972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
434072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testVerifyDrawable() {
434172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        MockTextView textView = new MockTextView(mActivity);
434272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4343a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable d = TestUtils.getDrawable(mActivity, R.drawable.pass);
434472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(textView.verifyDrawable(d));
434572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
434672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        textView.setCompoundDrawables(null, d, null, null);
434772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(textView.verifyDrawable(d));
434872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
434972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
435072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testAccessPrivateImeOptions() {
435172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
435272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertNull(mTextView.getPrivateImeOptions());
435372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
435472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setPrivateImeOptions("com.example.myapp.SpecialMode=3");
435572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals("com.example.myapp.SpecialMode=3", mTextView.getPrivateImeOptions());
435672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
435772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setPrivateImeOptions(null);
435872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertNull(mTextView.getPrivateImeOptions());
435972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
436072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
436172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testSetOnEditorActionListener() {
436272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
436372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
436498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final TextView.OnEditorActionListener mockOnEditorActionListener =
436598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                mock(TextView.OnEditorActionListener.class);
436698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verifyZeroInteractions(mockOnEditorActionListener);
436772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
436898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setOnEditorActionListener(mockOnEditorActionListener);
436998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verifyZeroInteractions(mockOnEditorActionListener);
437072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
437172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.onEditorAction(EditorInfo.IME_ACTION_DONE);
437298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockOnEditorActionListener, times(1)).onEditorAction(mTextView,
437398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                EditorInfo.IME_ACTION_DONE, null);
437472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
437572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
437672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testAccessImeOptions() {
437772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
437872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_NULL, mTextView.getImeOptions());
437972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
438072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeOptions(EditorInfo.IME_ACTION_GO);
438172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_ACTION_GO, mTextView.getImeOptions());
438272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
438372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeOptions(EditorInfo.IME_ACTION_DONE);
438472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_ACTION_DONE, mTextView.getImeOptions());
438572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
438672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeOptions(EditorInfo.IME_NULL);
438772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(EditorInfo.IME_NULL, mTextView.getImeOptions());
438872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
438972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
439072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testAccessImeActionLabel() {
439172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
439272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertNull(mTextView.getImeActionLabel());
439372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, mTextView.getImeActionId());
439472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
439572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setImeActionLabel("pinyin", 1);
439672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals("pinyin", mTextView.getImeActionLabel().toString());
439772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(1, mTextView.getImeActionId());
439872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
439972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4400d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa    public void testAccessImeHintLocales() {
4401d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        final TextView textView = new TextView(mActivity);
4402d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setText("", BufferType.EDITABLE);
4403d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setKeyListener(null);
4404d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setRawInputType(InputType.TYPE_CLASS_TEXT);
4405d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        assertNull(textView.getImeHintLocales());
4406d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        {
4407d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            final EditorInfo editorInfo = new EditorInfo();
4408d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            textView.onCreateInputConnection(editorInfo);
4409d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            assertNull(editorInfo.hintLocales);
4410d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        }
4411d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa
4412d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        final LocaleList localeList = LocaleList.forLanguageTags("en-PH,en-US");
4413d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        textView.setImeHintLocales(localeList);
4414d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        assertEquals(localeList, textView.getImeHintLocales());
4415d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        {
4416d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            final EditorInfo editorInfo = new EditorInfo();
4417d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            textView.onCreateInputConnection(editorInfo);
4418d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa            assertEquals(localeList, editorInfo.hintLocales);
4419d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa        }
4420d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa    }
4421d14d9c9a3d9d8eeed720ecf28716fc51942c096aYohei Yukawa
4422c873101a88e7ba584065de5e912508237378ca99Victoria Lease    @UiThreadTest
442372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testSetExtractedText() {
442472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
442572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
442672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach                mTextView.getText().toString());
442772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
442872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        ExtractedText et = new ExtractedText();
4429ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4430ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        // Update text and selection.
443172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        et.text = "test";
4432ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionStart = 0;
4433ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionEnd = 2;
443472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
443572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setExtractedText(et);
443672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals("test", mTextView.getText().toString());
4437ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(0, mTextView.getSelectionStart());
4438ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(2, mTextView.getSelectionEnd());
4439ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4440ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        // Use partialStartOffset and partialEndOffset
4441ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialStartOffset = 2;
4442ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialEndOffset = 3;
4443ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.text = "x";
4444ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionStart = 2;
4445ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.selectionEnd = 3;
4446ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4447ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        mTextView.setExtractedText(et);
4448ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals("text", mTextView.getText().toString());
4449ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(2, mTextView.getSelectionStart());
4450ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(3, mTextView.getSelectionEnd());
4451ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4452ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        // Update text with spans.
4453ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final SpannableString ss = new SpannableString("ex");
4454ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        ss.setSpan(new UnderlineSpan(), 0, 2, 0);
4455ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        ss.setSpan(new URLSpan("ctstest://TextView/test"), 1, 2, 0);
4456ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4457ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.text = ss;
4458ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialStartOffset = 1;
4459ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        et.partialEndOffset = 3;
4460ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        mTextView.setExtractedText(et);
4461ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4462ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals("text", mTextView.getText().toString());
4463ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final Editable editable = mTextView.getEditableText();
4464ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final UnderlineSpan[] underlineSpans = mTextView.getEditableText().getSpans(
4465ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi                0, editable.length(), UnderlineSpan.class);
4466ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(1, underlineSpans.length);
4467ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(1, editable.getSpanStart(underlineSpans[0]));
4468ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(3, editable.getSpanEnd(underlineSpans[0]));
4469ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi
4470ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        final URLSpan[] urlSpans = mTextView.getEditableText().getSpans(
4471ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi                0, editable.length(), URLSpan.class);
4472ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(1, urlSpans.length);
4473ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(2, editable.getSpanStart(urlSpans[0]));
4474ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals(3, editable.getSpanEnd(urlSpans[0]));
4475ba5ce949fafd36e5318108a261af06763651d6b7Keisuke Kuroyanagi        assertEquals("ctstest://TextView/test", urlSpans[0].getURL());
447672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
447772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
447872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testMoveCursorToVisibleOffset() throws Throwable {
447972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
448072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
448172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // not a spannable text
44826beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        runTestOnUiThread(() -> assertFalse(mTextView.moveCursorToVisibleOffset()));
448372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
448472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
448572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // a selection range
448672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        final String spannableText = "text";
448772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
448872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
44896beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        runTestOnUiThread(() -> mTextView.setText(spannableText, BufferType.SPANNABLE));
449072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
449172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        Selection.setSelection((Spannable) mTextView.getText(), 0, spannableText.length());
449272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
449372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, mTextView.getSelectionStart());
449472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(spannableText.length(), mTextView.getSelectionEnd());
44956beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        runTestOnUiThread(() -> assertFalse(mTextView.moveCursorToVisibleOffset()));
449672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
449772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
449872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        // a spannable without range
44996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        runTestOnUiThread(() -> {
45006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = findTextView(R.id.textview_text);
45016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(spannableText, BufferType.SPANNABLE);
450272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        });
450372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
450472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
45056beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        runTestOnUiThread(() -> assertTrue(mTextView.moveCursorToVisibleOffset()));
450672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mInstrumentation.waitForIdleSync();
450772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
450872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4509afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsu    public void testIsInputMethodTarget() throws Throwable {
451072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
451172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.isInputMethodTarget());
451272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
451372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.isFocused());
45146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        runTestOnUiThread(() -> {
45156beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setFocusable(true);
45166beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
45176beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu         });
4518afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsu        mInstrumentation.waitForIdleSync();
4519afefb471cb741d3787da90aa03338f28c5cb6d87Brian Muramatsu        assertTrue(mTextView.isFocused());
452004d12809ae731ea2aea678707bcc606f05efb23aBrian Muramatsu
4521354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(() -> mTextView.isInputMethodTarget());
452272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
452372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
45246a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
45256a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testBeginEndBatchEditAreNotCalledForNonEditableText() {
4526b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        final TextView mockTextView = spy(new TextView(mActivity));
4527b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir
4528b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // TextView should not call onBeginBatchEdit or onEndBatchEdit during initialization
4529b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4530b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
45316a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
453272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
45336a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.beginBatchEdit();
4534b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // Since TextView doesn't support editing, the callbacks should not be called
4535b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4536b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
45376a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
45386a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.endBatchEdit();
4539b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        // Since TextView doesn't support editing, the callbacks should not be called
4540b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4541b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
45426a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
45436a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
45446a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    @MediumTest
45456a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    public void testBeginEndBatchEditCallbacksAreCalledForEditableText() {
4546b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        final TextView mockTextView = spy(new TextView(mActivity));
45476a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
45486a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        final FrameLayout layout = new FrameLayout(getActivity());
45496a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
45506a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT,
45516a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir                ViewGroup.LayoutParams.MATCH_PARENT);
45526a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.addView(mockTextView, layoutParams);
45536a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        layout.setLayoutParams(layoutParams);
45546a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4555b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        mActivity.runOnUiThread(() -> mActivity.setContentView(layout));
45566a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mInstrumentation.waitForIdleSync();
45576a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4558b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        mActivity.runOnUiThread(() -> {
4559b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir            mockTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
4560b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir            mockTextView.setText("", BufferType.EDITABLE);
4561b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir            mockTextView.requestFocus();
45626a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        });
45636a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mInstrumentation.waitForIdleSync();
45646a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4565b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        reset(mockTextView);
45666a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        assertTrue(mockTextView.hasFocus());
4567b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4568b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
45696a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
45706a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.beginBatchEdit();
45716a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
4572b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, times(1)).onBeginBatchEdit();
4573b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onEndBatchEdit();
4574b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir
4575b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        reset(mockTextView);
45766a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mockTextView.endBatchEdit();
4577b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, never()).onBeginBatchEdit();
4578b0bae288153f4ac94e7b6fd83595acdedf1f1f6aSiyamed Sinir        verify(mockTextView, times(1)).onEndBatchEdit();
457972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
458072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
458172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    @UiThreadTest
458272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testBringPointIntoView() throws Throwable {
458372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
458472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.bringPointIntoView(1));
458572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
458672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.layout(0, 0, 100, 100);
458772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.bringPointIntoView(2));
458872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
458972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
459072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testCancelLongPress() {
459172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
459272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        TouchUtils.longClickView(this, mTextView);
459372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.cancelLongPress();
459472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
459572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
459672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    @UiThreadTest
459772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testClearComposingText() {
459872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
459972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setText("Hello world!", BufferType.SPANNABLE);
460072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        Spannable text = (Spannable) mTextView.getText();
460172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
460272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
460372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
460472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
460572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        BaseInputConnection.setComposingSpans((Spannable) mTextView.getText());
460672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, BaseInputConnection.getComposingSpanStart(text));
460772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, BaseInputConnection.getComposingSpanStart(text));
460872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
460972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.clearComposingText();
461072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
461172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(-1, BaseInputConnection.getComposingSpanStart(text));
461272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
461372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
461472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testComputeVerticalScrollExtent() {
461572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        MockTextView textView = new MockTextView(mActivity);
461672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, textView.computeVerticalScrollExtent());
461772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
4618a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        Drawable d = TestUtils.getDrawable(mActivity, R.drawable.pass);
461972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        textView.setCompoundDrawables(null, d, null, d);
462072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
462172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(0, textView.computeVerticalScrollExtent());
462272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
462372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
462472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    @UiThreadTest
462572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testDidTouchFocusSelect() {
4626c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        mTextView = new EditText(mActivity);
462772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertFalse(mTextView.didTouchFocusSelect());
462872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
462972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.setFocusable(true);
463072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView.requestFocus();
463172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(mTextView.didTouchFocusSelect());
463272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
463372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
46340ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka    public void testSelectAllJustAfterTap() {
46350ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // Prepare an EditText with focus.
46366beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
46376beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = new EditText(mActivity);
46386beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.setContentView(mTextView);
46390ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
46406beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertFalse(mTextView.didTouchFocusSelect());
46416beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setFocusable(true);
46426beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
46436beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            assertTrue(mTextView.didTouchFocusSelect());
46440ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
46456beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText("Hello, World.", BufferType.SPANNABLE);
46460ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        });
46470ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        mInstrumentation.waitForIdleSync();
46480ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
46490ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // Tap the view to show InsertPointController.
46500ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        TouchUtils.tapView(this, mTextView);
465183a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        // bad workaround for waiting onStartInputView of LeanbackIme.apk done
465283a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        try {
465383a70cb57c839148a4feff786cdbb3803828d484Bobby Wang            Thread.sleep(1000);
465483a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        } catch (InterruptedException e) {
465583a70cb57c839148a4feff786cdbb3803828d484Bobby Wang            e.printStackTrace();
465683a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        }
46570ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
46580ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // Execute SelectAll context menu.
46596beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.onTextContextMenuItem(android.R.id.selectAll));
46600ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        mInstrumentation.waitForIdleSync();
46610ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
46620ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        // The selection must be whole of the text contents.
46630ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        assertEquals(0, mTextView.getSelectionStart());
466483a70cb57c839148a4feff786cdbb3803828d484Bobby Wang        assertEquals("Hello, World.", mTextView.getText().toString());
46650ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka        assertEquals(mTextView.length(), mTextView.getSelectionEnd());
46660ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka    }
46670ddd054a4a00b9843563a38ab236fe3e47c99e9aSeigo Nonaka
466872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    public void testExtractText() {
466972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = new TextView(mActivity);
467072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
467172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        ExtractedTextRequest request = new ExtractedTextRequest();
467272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        ExtractedText outText = new ExtractedText();
467372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
467472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.token = 0;
467572b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.flags = 10;
467672b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.hintMaxLines = 2;
467772b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        request.hintMaxChars = 20;
467872b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(mTextView.extractText(request, outText));
467972b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
468072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        mTextView = findTextView(R.id.textview_text);
468172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertTrue(mTextView.extractText(request, outText));
468272b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
468372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach        assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
468472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach                outText.text.toString());
4685c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi
4686c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        // Tests for invalid arguments.
4687c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        assertFalse(mTextView.extractText(request, null));
4688c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        assertFalse(mTextView.extractText(null, outText));
4689c778c0d53d612a73b39cbf965f5068a3b0a10695Yoshiki Iguchi        assertFalse(mTextView.extractText(null, null));
469072b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
469172b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
469294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
469394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testTextDirectionDefault() {
4694c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
46952a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getRawTextDirection());
469694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
469794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
469894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
469994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testSetGetTextDirection() {
4700c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
470194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
470294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
47032a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getRawTextDirection());
470494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
470594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
47062a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getRawTextDirection());
470794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
470894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
47092a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getRawTextDirection());
471094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
471194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
47122a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getRawTextDirection());
471394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
471494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
47152a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getRawTextDirection());
471694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
471794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
47182a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getRawTextDirection());
471902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
472002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
472102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getRawTextDirection());
472202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
472302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
472402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getRawTextDirection());
472594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
472694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
472794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
472894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionLtr() {
4729c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
473094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("this is a test");
473194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
47322a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
473394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
473494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
47352a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
473694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
473794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
47382a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
473994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
474094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
47412a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
474294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
474394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
47442a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
474594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
474694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
47472a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
474894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
474994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
47502a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
475102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
475202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
475302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
475402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
475502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
475602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
475794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
475894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
475994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
476094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionLtrWithInheritance() {
4761c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        LinearLayout ll = new LinearLayout(mActivity);
476294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
476394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
4764c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
476594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("this is a test");
476694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.addView(tv);
476794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
476894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
47692a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
477094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
477194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
47722a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
477394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
477494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
47752a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
477694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
477794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
47782a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
477994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
478094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
47812a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
478294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
478394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
47842a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
478502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
478602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
478702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
478802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
478902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
479002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
479194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
479294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
479394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
479494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionRtl() {
4795c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
479694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("\u05DD\u05DE"); // hebrew
479794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
47982a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
479994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
480094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
48012a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
480294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
480394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
48042a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
480594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
480694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
48072a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
480894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
480994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
48102a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
481194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
481294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
48132a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
481494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
481594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
48162a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
481702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
481802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
481902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
482002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
482102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
482202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
482394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
482494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
482594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
482694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testGetResolvedTextDirectionRtlWithInheritance() {
4827c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        LinearLayout ll = new LinearLayout(mActivity);
482894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
482994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
4830c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = new TextView(mActivity);
483194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setText("\u05DD\u05DE"); // hebrew
483294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.addView(tv);
483394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
483494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
48352a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
483694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
483794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
48382a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
483994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
484094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
48412a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
484294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
484394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
48442a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
484594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
484694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
48472a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
484894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
484994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
48502a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
485194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
485202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
485302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
485402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
485502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
485602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
485702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
485894c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        // Force to RTL text direction on the layout
485994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
486094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
486194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
48622a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
486394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
486494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
48652a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
486694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
486794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
48682a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
486994c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
487094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
48712a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
487294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
487394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
48742a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
487594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
487694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
48772a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
487802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
487902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
488002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
488102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
488202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
488302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
488494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
488594c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
488694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    @UiThreadTest
488794c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    public void testResetTextDirection() {
4888c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        LinearLayout ll = (LinearLayout) mActivity.findViewById(R.id.layout_textviewtest);
4889c2499432269114271f4b8ec17d07b469d2966fbeGilles Debunne        TextView tv = (TextView) mActivity.findViewById(R.id.textview_rtl);
489094c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
489194c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
489294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
48932a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
489494c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
4895f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        // No reset when we remove the view
489694c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio        ll.removeView(tv);
4897f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
4898f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio
4899f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        // Reset is done when we add the view
4900f0d2af33ae194bead489caef9b461f2bee6f45a6Fabrice Di Meglio        ll.addView(tv);
49012a9c5b3b05fd5fae0fd01352283739c5f85ea8e0Fabrice Di Meglio        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
490294c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio    }
490394c94377f8f741065c7f15d52e4398699dae0844Fabrice Di Meglio
490402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    @UiThreadTest
490502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    public void testTextDirectionFirstStrongLtr() {
490602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
490702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is LTR, the paragraph direction is LTR.
490802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
490902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
491002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
491102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("this is a test");
491202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
491302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
491402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
491502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
491602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
491702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
491802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
491902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_LEFT_TO_RIGHT, layout.getParagraphDirection(0));
492002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
492102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
492202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is RTL, the paragraph direction is RTL.
492302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
492402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
492502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
492602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\u05DD\u05DE"); // Hebrew
492702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
492802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
492902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
493002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
493102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
493202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
493302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
493402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_RIGHT_TO_LEFT, layout.getParagraphDirection(0));
493502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
493602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
493702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is not a strong directional character, the paragraph
493802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // direction is LTR.
493902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
494002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
494102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
494202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\uFFFD");  // REPLACEMENT CHARACTER. Neutral direction.
494302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
494402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
494502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_LTR);
494602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_LTR, tv.getTextDirection());
494702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
494802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
494902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
495002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_LEFT_TO_RIGHT, layout.getParagraphDirection(0));
495102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
495202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    }
495302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
495402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    @UiThreadTest
495502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    public void testTextDirectionFirstStrongRtl() {
495602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
495702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is LTR, the paragraph direction is LTR.
495802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
495902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
496002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
496102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("this is a test");
496202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
496302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
496402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
496502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
496602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
496702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
496802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
496902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_LEFT_TO_RIGHT, layout.getParagraphDirection(0));
497002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
497102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
497202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is RTL, the paragraph direction is RTL.
497302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
497402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
497502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
497602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\u05DD\u05DE"); // Hebrew
497702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
497802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
497902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
498002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
498102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
498202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
498302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
498402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_RIGHT_TO_LEFT, layout.getParagraphDirection(0));
498502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
498602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        {
498702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // The first directional character is not a strong directional character, the paragraph
498802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            // direction is RTL.
498902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            LinearLayout ll = new LinearLayout(mActivity);
499002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
499102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            TextView tv = new TextView(mActivity);
499202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setText("\uFFFD");  // REPLACEMENT CHARACTER. Neutral direction.
499302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            ll.addView(tv);
499402c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
499502c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG_RTL);
499602c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(View.TEXT_DIRECTION_FIRST_STRONG_RTL, tv.getTextDirection());
499702c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
499802c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            tv.onPreDraw();  // For freezing layout.
499902c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            Layout layout = tv.getLayout();
500002c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka            assertEquals(Layout.DIR_RIGHT_TO_LEFT, layout.getParagraphDirection(0));
500102c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka        }
500202c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka    }
500302c09dc324e915d3786f0188704ad1753039bd40Seigo Nonaka
5004c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader    public void testTextLocales() {
5005c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        TextView tv = new TextView(mActivity);
5006c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(Locale.getDefault(), tv.getTextLocale());
5007c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(LocaleList.getDefault(), tv.getTextLocales());
5008c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5009c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        tv.setTextLocale(Locale.CHINESE);
5010c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(Locale.CHINESE, tv.getTextLocale());
5011c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(new LocaleList(Locale.CHINESE), tv.getTextLocales());
5012c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5013c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        tv.setTextLocales(LocaleList.forLanguageTags("en,ja"));
5014c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(Locale.forLanguageTag("en"), tv.getTextLocale());
5015c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        assertEquals(LocaleList.forLanguageTags("en,ja"), tv.getTextLocales());
5016c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5017c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        try {
5018c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            tv.setTextLocale(null);
5019c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            fail("Setting the text locale to null should throw");
5020c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        } catch (Throwable e) {
5021c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            assertEquals(IllegalArgumentException.class, e.getClass());
5022c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        }
5023c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5024c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        try {
5025c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            tv.setTextLocales(null);
5026c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            fail("Setting the text locales to null should throw");
5027c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        } catch (Throwable e) {
5028c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            assertEquals(IllegalArgumentException.class, e.getClass());
5029c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        }
5030c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5031c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        try {
5032c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            tv.setTextLocales(new LocaleList());
5033c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            fail("Setting the text locale to an empty list should throw");
5034c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        } catch (Throwable e) {
5035c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader            assertEquals(IllegalArgumentException.class, e.getClass());
5036c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader        }
5037c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader    }
5038c2c082a53615033ece708f7e392474fef8ae2417Roozbeh Pournader
5039b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka    public void testAllCapsLocalization() {
5040b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        String testString = "abcdefghijklmnopqrstuvwxyz";
5041b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka
5042b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        // The capitalized characters of "i" on Turkish and Azerbaijani are different from English.
5043b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        Locale[] testLocales = {
5044b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            new Locale("az", "AZ"),
5045b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            new Locale("tr", "TR"),
5046b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            new Locale("en", "US"),
5047b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        };
5048b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka
5049b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        TextView tv = new TextView(mActivity);
5050b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        tv.setAllCaps(true);
5051b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        for (Locale locale: testLocales) {
5052b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            tv.setTextLocale(locale);
5053b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka            assertEquals("Locale: " + locale.getDisplayName(),
5054b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka                         testString.toUpperCase(locale),
5055b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka                         tv.getTransformationMethod().getTransformation(testString, tv).toString());
5056b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka        }
5057b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka    }
5058b8eb7fd352a5fac5911460ebcedf53e6270c97dbSeigo Nonaka
5059dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5060dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testTextAlignmentDefault() {
5061dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        TextView tv = new TextView(getActivity());
50627fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getRawTextAlignment());
5063dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // resolved default text alignment is GRAVITY
50647fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5065dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5066dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5067dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5068dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testSetGetTextAlignment() {
5069dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        TextView tv = new TextView(getActivity());
5070dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5071dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
50727fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getRawTextAlignment());
5073dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5074dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
50757fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getRawTextAlignment());
5076dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5077dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
50787fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getRawTextAlignment());
5079dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5080dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
50817fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getRawTextAlignment());
5082dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5083dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
50847fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getRawTextAlignment());
5085dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5086dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
50877fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getRawTextAlignment());
5088dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5089dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5090dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5091dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testGetResolvedTextAlignment() {
5092dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        TextView tv = new TextView(getActivity());
5093dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
50947fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5095dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5096757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        // Test center alignment first so that we dont hit the default case
5097dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
50987fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5099dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5100757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        // Test the default case too
5101757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
5102757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5103757ec4fdfd1798a8e28d050433c67e628a7f578dFabrice Di Meglio
5104dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
51057fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getTextAlignment());
5106dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5107dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
51087fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getTextAlignment());
5109dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5110dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
51117fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getTextAlignment());
5112dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5113dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
51147fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getTextAlignment());
5115dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5116dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5117dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5118dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testGetResolvedTextAlignmentWithInheritance() {
5119dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        LinearLayout ll = new LinearLayout(getActivity());
5120dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
5121dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5122dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        TextView tv = new TextView(getActivity());
5123dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.addView(tv);
5124dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5125dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // check defaults
51267fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getRawTextAlignment());
5127dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5128dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5129dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // set inherit and check that child is following parent
5130dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT);
51317fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_INHERIT, tv.getRawTextAlignment());
5132dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5133dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
51347fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5135dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5136dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
51377fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getTextAlignment());
5138dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5139dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
51407fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getTextAlignment());
5141dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5142dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
51437fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getTextAlignment());
5144dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5145dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
51467fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getTextAlignment());
5147dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5148dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        // now get rid of the inheritance but still change the parent
5149dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
5150dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5151dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
51527fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5153dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5154dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
51557fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5156dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5157dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
51587fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5159dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5160dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
51617fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5162dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5163dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
51647fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5165dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5166dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5167dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    @UiThreadTest
5168dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    public void testResetTextAlignment() {
51694ca04c0729a0e810b5af16edcd52bb8cb59bf55eChenjie Luo        TextViewCtsActivity activity = getActivity();
5170dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5171dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        LinearLayout ll = (LinearLayout) activity.findViewById(R.id.layout_textviewtest);
5172dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        TextView tv = (TextView) activity.findViewById(R.id.textview_rtl);
5173dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5174dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
5175dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        tv.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT);
51767fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
5177dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
51784f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        // No reset when we remove the view
5179dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio        ll.removeView(tv);
51804f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
51814f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio
51824f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        // Reset is done when we add the view
51834f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        // Default text alignment is GRAVITY
51844f6c5d77dfc74b490b8567d0b21adec0ccd72d22Fabrice Di Meglio        ll.addView(tv);
51857fc94900b8661e27f89ae21523bd952127d510eaFabrice Di Meglio        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
5186dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio    }
5187dd7e30e4e18f67c4257379adecaa1df2bbe1992cFabrice Di Meglio
5188938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    @UiThreadTest
5189938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    public void testDrawableResolution() {
5190b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 1.1: left / right drawable defined in default LTR mode
5191938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
5192a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5193938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5194a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, -1, -1,
5195938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5196b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5197b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 1.2: left / right drawable defined in default RTL mode
5198938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
5199a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5200938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5201a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, -1, -1,
5202938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5203b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5204b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 2.1: start / end drawable defined in LTR mode
5205938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_1);
5206a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5207938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5208a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5209938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5210b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5211b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 2.2: start / end drawable defined in RTL mode
5212938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_2);
5213a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5214938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5215a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5216938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5217b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5218b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 3.1: left / right / start / end drawable defined in LTR mode
5219938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_1);
5220a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5221938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5222a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5223938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5224b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5225b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 3.2: left / right / start / end drawable defined in RTL mode
5226938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_2);
5227a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5228938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5229a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5230938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5231b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5232b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 4.1: start / end drawable defined in LTR mode inside a layout
5233b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5234938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_1);
5235a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5236938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5237a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5238938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5239b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5240b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 4.2: start / end drawable defined in RTL mode inside a layout
5241b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5242938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_2);
5243a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5244938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5245a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5246938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5247b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5248b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 5.1: left / right / start / end drawable defined in LTR mode inside a layout
5249b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5250938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_1);
5251a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5252938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5253a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5254938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5255b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
5256b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // Case 5.2: left / right / start / end drawable defined in RTL mode inside a layout
5257b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio        // that defines the layout direction
5258938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_2);
5259a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
5260938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5261a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
5262938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
5263b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio    }
5264b44fc868dc396032a3dae2ba8871168df95e620aFabrice Di Meglio
52659776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio    @UiThreadTest
52669776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio    public void testDrawableResolution2() {
52679776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio        // Case 1.1: left / right drawable defined in default LTR mode
5268938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
5269a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5270938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
52719776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5272a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawables(null, null,
5273a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                TestUtils.getDrawable(mActivity, R.drawable.icon_yellow), null);
5274a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, -1, R.drawable.icon_yellow, -1, -1);
52759776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5276938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
5277a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
5278938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.drawable.icon_green, R.drawable.icon_yellow);
52799776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5280a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawables(TestUtils.getDrawable(mActivity, R.drawable.icon_yellow), null,
5281a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                null, null);
5282a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
52839776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5284938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        tv = (TextView) mActivity.findViewById(R.id.textview_ltr);
5285a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, -1, -1, -1, -1);
52869776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5287a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawables(TestUtils.getDrawable(mActivity, R.drawable.icon_blue), null,
5288a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                TestUtils.getDrawable(mActivity, R.drawable.icon_red), null);
5289a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red, -1, -1);
52909776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5291a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        tv.setCompoundDrawablesRelative(TestUtils.getDrawable(mActivity, R.drawable.icon_yellow),
5292a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov                null, null, null);
5293a82283fc3d03aadf14baa7e731bd43ab744e732aKirill Grouchnikov        TestUtils.verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
5294938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    }
5295938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
5296938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov    public void testCompoundAndTotalPadding() {
5297938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final Resources res = mActivity.getResources();
5298938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int drawablePadding = res.getDimensionPixelSize(R.dimen.textview_drawable_padding);
5299938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingLeft = res.getDimensionPixelSize(R.dimen.textview_padding_left);
5300938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingRight = res.getDimensionPixelSize(R.dimen.textview_padding_right);
5301938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingTop = res.getDimensionPixelSize(R.dimen.textview_padding_top);
5302938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int paddingBottom = res.getDimensionPixelSize(R.dimen.textview_padding_bottom);
5303938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int iconSize = TestUtils.dpToPx(mActivity, 32);
5304938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
5305938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final TextView textViewLtr = (TextView) mActivity.findViewById(
5306938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.id.textview_compound_drawable_ltr);
5307938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingLeftLtr = paddingLeft + drawablePadding + iconSize;
5308938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingRightLtr = paddingRight + drawablePadding + iconSize;
5309938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingLeft());
5310938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingStart());
5311938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingLeft());
5312938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingStart());
5313938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingRight());
5314938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingEnd());
5315938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingRight());
5316938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingEnd());
5317938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingTop + drawablePadding + iconSize,
5318938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewLtr.getCompoundPaddingTop());
5319938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingBottom + drawablePadding + iconSize,
5320938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewLtr.getCompoundPaddingBottom());
5321938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov
5322938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final TextView textViewRtl = (TextView) mActivity.findViewById(
5323938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                R.id.textview_compound_drawable_rtl);
5324938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingLeftRtl = paddingLeft + drawablePadding + iconSize;
5325938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        final int combinedPaddingRightRtl = paddingRight + drawablePadding + iconSize;
5326938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingLeft());
5327938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingEnd());
5328938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingLeft());
5329938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingEnd());
5330938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingRight());
5331938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingStart());
5332938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingRight());
5333938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingStart());
5334938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingTop + drawablePadding + iconSize,
5335938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewRtl.getCompoundPaddingTop());
5336938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov        assertEquals(paddingBottom + drawablePadding + iconSize,
5337938e01e2ecbc870a6de7296ea3cbb1550404439dKirill Grouchnikov                textViewRtl.getCompoundPaddingBottom());
53389776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio    }
53399776f6746985a3740892cec4df71fbbc94bdaf84Fabrice Di Meglio
5340e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    public void testSetGetBreakStrategy() {
5341e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        TextView tv = new TextView(mActivity);
5342e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
53432751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        final PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
53442751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka
5345d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        // The default value is from the theme, here the default is BREAK_STRATEGY_HIGH_QUALITY for
53462751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        // TextView except for Android Wear. The default value for Android Wear is
53472751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        // BREAK_STRATEGY_BALANCED.
53482751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
53492751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            // Android Wear
53502751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            assertEquals(Layout.BREAK_STRATEGY_BALANCED, tv.getBreakStrategy());
53512751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        } else {
53522751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            // All other form factor.
53532751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka            assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
53542751d704e7028d7b7a3919318c0b7381be24197aSeigo Nonaka        }
5355e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5356e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
5357e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, tv.getBreakStrategy());
5358e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5359e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY);
5360e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
5361e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5362e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
5363e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.BREAK_STRATEGY_BALANCED, tv.getBreakStrategy());
5364d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5365d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        EditText et = new EditText(mActivity);
5366d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5367d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        // The default value is from the theme, here the default is BREAK_STRATEGY_SIMPLE for
5368d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        // EditText.
5369d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, et.getBreakStrategy());
5370d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5371d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        et.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
5372d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, et.getBreakStrategy());
5373d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5374d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        et.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY);
5375d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, et.getBreakStrategy());
5376d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi
5377d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        et.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
5378d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.BREAK_STRATEGY_BALANCED, et.getBreakStrategy());
5379e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    }
5380e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5381e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    public void testSetGetHyphenationFrequency() {
5382e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        TextView tv = new TextView(mActivity);
5383e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5384d86c8a9d3dd63c69a09e5fa5c23b1ffc4d2fc2e2Keisuke Kuroyanagi        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL, tv.getHyphenationFrequency());
5385e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5386e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
5387e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.HYPHENATION_FREQUENCY_NONE, tv.getHyphenationFrequency());
5388e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5389e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
5390e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL, tv.getHyphenationFrequency());
5391e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
5392e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        tv.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
5393e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka        assertEquals(Layout.HYPHENATION_FREQUENCY_FULL, tv.getHyphenationFrequency());
5394e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka    }
5395e5862867943e7c107c70e825af58fffd30be7a9fSeigo Nonaka
539632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi    public void testSetAndGetCustomSelectionActionModeCallback() {
539732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        final String text = "abcde";
53986beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
53996beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView = new EditText(mActivity);
54006beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mActivity.setContentView(mTextView);
54016beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setText(text, BufferType.SPANNABLE);
54026beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setTextIsSelectable(true);
54036beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.requestFocus();
54046beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.setSelected(true);
540532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
540632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
540732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
540832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Check default value.
540932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        assertNull(mTextView.getCustomSelectionActionModeCallback());
541032944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
541198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
541298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
541398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                thenReturn(Boolean.FALSE);
541498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setCustomSelectionActionModeCallback(mockActionModeCallback);
541598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(mockActionModeCallback,
541632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi                mTextView.getCustomSelectionActionModeCallback());
541732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
54186beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
54196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Set selection and try to start action mode.
54206beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            final Bundle args = new Bundle();
54216beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
54226beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, text.length());
54236beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.performAccessibilityAction(
54246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    AccessibilityNodeInfo.ACTION_SET_SELECTION, args);
542532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
542632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
542732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
542898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, times(1)).onCreateActionMode(
542998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                any(ActionMode.class), any(Menu.class));
543032944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
54316beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
54326beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Remove selection and stop action mode.
54336beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.copy);
543432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
543532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
543632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
543732944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Action mode was blocked.
543898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, never()).onDestroyActionMode(any(ActionMode.class));
543932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
544098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        // Reset and reconfigure callback.
544198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        reset(mockActionModeCallback);
544298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
544398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                thenReturn(Boolean.TRUE);
544498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(mockActionModeCallback, mTextView.getCustomSelectionActionModeCallback());
544532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
54466beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
54476beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Set selection and try to start action mode.
54486beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            final Bundle args = new Bundle();
54496beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
54506beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            args.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, text.length());
54516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.performAccessibilityAction(
54526beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu                    AccessibilityNodeInfo.ACTION_SET_SELECTION, args);
545332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
545432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
545532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
545632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
545798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, times(1)).onCreateActionMode(
545898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                any(ActionMode.class), any(Menu.class));
545932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
54606beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
54616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            // Remove selection and stop action mode.
54626beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu            mTextView.onTextContextMenuItem(android.R.id.copy);
546332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        });
546432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        mInstrumentation.waitForIdleSync();
546532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
546632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Action mode was started
546798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        verify(mockActionModeCallback, times(1)).onDestroyActionMode(any(ActionMode.class));
546832944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi    }
546932944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
54706beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu    @UiThreadTest
547198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov    public void testSetAndGetCustomInsertionActionMode() {
547232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        initTextViewForTyping();
547332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // Check default value.
547432944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        assertNull(mTextView.getCustomInsertionActionModeCallback());
547532944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
547698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
547798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
547898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                thenReturn(Boolean.FALSE);
547998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mTextView.setCustomInsertionActionModeCallback(mockActionModeCallback);
548098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(mockActionModeCallback, mTextView.getCustomInsertionActionModeCallback());
548132944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi        // TODO(Bug: 22033189): Tests the set callback is actually used.
548232944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi    }
548332944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
548498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov    public void testTextShadows() {
548598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final TextView textViewWithConfiguredShadow =
548698d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov                (TextView) mActivity.findViewById(R.id.textview_with_shadow);
548798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(1.0f, textViewWithConfiguredShadow.getShadowDx());
548898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(2.0f, textViewWithConfiguredShadow.getShadowDy());
548998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(3.0f, textViewWithConfiguredShadow.getShadowRadius());
549098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(Color.GREEN, textViewWithConfiguredShadow.getShadowColor());
549132944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
549298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
549398d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(0.0f, textView.getShadowDx());
549498d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(0.0f, textView.getShadowDy());
549598d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(0.0f, textView.getShadowRadius());
549632944498e0627347cbe7c275b6ff6f21b8c983faKeisuke Kuroyanagi
549798d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setShadowLayer(5.0f, 3.0f, 4.0f, Color.RED));
549898d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        mInstrumentation.waitForIdleSync();
549998d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(3.0f, textView.getShadowDx());
550098d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(4.0f, textView.getShadowDy());
550198d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(5.0f, textView.getShadowRadius());
550298d000ba45f2a9485e391b8a8abff1d891ea4dbbKirill Grouchnikov        assertEquals(Color.RED, textView.getShadowColor());
550372b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach    }
550472b705b4df314c5cb81a9db2347fb6a6f9384b9aPhil Dubach
5505354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    public void testFontFeatureSettings() {
5506354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
5507354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(TextUtils.isEmpty(textView.getFontFeatureSettings()));
5508354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5509354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setFontFeatureSettings("smcp"));
5510354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5511354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals("smcp", textView.getFontFeatureSettings());
5512354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5513354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> textView.setFontFeatureSettings("frac"));
5514354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5515354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals("frac", textView.getFontFeatureSettings());
5516354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    }
5517354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5518354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    private static class SoftInputResultReceiver extends ResultReceiver {
5519354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        private boolean mIsDone;
5520354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        private int mResultCode;
5521354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5522354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        public SoftInputResultReceiver(Handler handler) {
5523354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            super(handler);
5524354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5525354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5526354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        @Override
5527354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        protected void onReceiveResult(int resultCode, Bundle resultData) {
5528354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mResultCode = resultCode;
5529354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mIsDone = true;
5530354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5531354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5532354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        public void reset() {
5533354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            mIsDone = false;
5534354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5535354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    }
5536354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5537354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    public void testAccessShowSoftInputOnFocus() {
5538354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)) {
5539354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov            return;
5540354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        }
5541354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5542354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Scroll down to our EditText
5543354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final ScrollView scrollView = (ScrollView) mActivity.findViewById(R.id.scroller);
5544354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mTextView = findTextView(R.id.editview_text);
5545354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> scrollView.fullScroll(View.FOCUS_DOWN));
5546354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5547354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5548354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Mark it to show soft input on focus
5549354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(true));
5550354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5551354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(mTextView.getShowSoftInputOnFocus());
5552354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5553354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // And emulate click on it
5554354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        TouchUtils.clickView(this, mTextView);
5555354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5556354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Verify that input method manager is active and accepting text
5557354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        final InputMethodManager imManager = (InputMethodManager) mActivity
5558354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov                .getSystemService(Context.INPUT_METHOD_SERVICE);
5559354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(() -> imManager.isActive());
5560354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(imManager.isAcceptingText());
5561354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertTrue(imManager.isActive(mTextView));
5562354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5563354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Since there is no API to check that soft input is showing, we're going to ask
5564354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // the input method manager to show soft input, passing our custom result receiver.
5565354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // We're expecting to get UNCHANGED_SHOWN, indicating that the soft input was already
5566354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // showing before showSoftInput was called.
5567354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        SoftInputResultReceiver receiver = new SoftInputResultReceiver(mHandler);
5568354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        imManager.showSoftInput(mTextView, 0, receiver);
5569354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(() -> receiver.mIsDone);
5570354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(InputMethodManager.RESULT_UNCHANGED_SHOWN, receiver.mResultCode);
5571354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5572354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Close soft input
5573354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        sendKeys(KeyEvent.KEYCODE_BACK);
5574354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5575354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Reconfigure our edit text to not show soft input on focus
5576354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mActivity.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(false));
5577354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        mInstrumentation.waitForIdleSync();
5578354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertFalse(mTextView.getShowSoftInputOnFocus());
5579354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5580354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Emulate click on it
5581354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        TouchUtils.clickView(this, mTextView);
5582354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5583354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Ask input method manager to show soft input again. This time we're expecting to get
5584354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // SHOWN, indicating that the soft input was not showing before showSoftInput was called.
5585354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        receiver.reset();
5586354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        imManager.showSoftInput(mTextView, 0, receiver);
5587354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        PollingCheck.waitFor(() -> receiver.mIsDone);
5588354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        assertEquals(InputMethodManager.RESULT_SHOWN, receiver.mResultCode);
5589354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
5590354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        // Close soft input
5591354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov        sendKeys(KeyEvent.KEYCODE_BACK);
5592354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov    }
5593354a3744faf4006b2d997ca71ffedef1da823c5eKirill Grouchnikov
559441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    public void testIsSuggestionsEnabled() {
559541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView = findTextView(R.id.textview_text);
559641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
559741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Anything without InputType.TYPE_CLASS_TEXT doesn't have suggestions enabled
559841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_DATETIME));
559941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
560041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
560141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_PHONE));
560241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
560341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
560441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_NUMBER));
560541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
560641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
560741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // From this point our text view has InputType.TYPE_CLASS_TEXT
560841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
560941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Anything with InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS doesn't have suggestions enabled
561041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
561141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
561241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
561341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
561441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
561541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
561641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
561741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL |
561841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
561941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
562041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
562141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
562241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
562341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS |
562441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
562541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
562641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
562741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Otherwise suggestions are enabled for specific type variations enumerated in the
562841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // documentation of TextView.isSuggestionsEnabled
562941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
563041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
563141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL));
563241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
563341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
563441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
563541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
563641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT));
563741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
563841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
563941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
564041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
564141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE));
564241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
564341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
564441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
564541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
564641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
564741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
564841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
564941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
565041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
565141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT));
565241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertTrue(mTextView.isSuggestionsEnabled());
565341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
565441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // and not on any other type variation
565541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
565641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
565741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS));
565841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
565941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
566041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
566141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
566241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER));
566341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
566441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
566541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
566641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
566741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD));
566841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
566941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
567041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
567141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
567241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME));
567341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
567441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
567541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
567641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
567741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC));
567841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
567941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
568041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
568141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
568241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS));
568341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
568441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
568541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
568641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
568741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI));
568841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
568941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
569041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
569141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
569241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT |
569341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD));
569441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
569541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
569641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
569741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
569841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT |
569941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                                InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS));
570041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
570141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
570241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mInstrumentation.runOnMainSync(
570341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setInputType(
570441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD));
570541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertFalse(mTextView.isSuggestionsEnabled());
570641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
570741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
570841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    public void testAccessLetterSpacing() {
570941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView = findTextView(R.id.textview_text);
571041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertEquals(0.0f, mTextView.getLetterSpacing());
571141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
571241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final CharSequence text = mTextView.getText();
571341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int textLength = text.length();
571441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
571541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get advance widths of each character at the default letter spacing
571641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final float[] initialWidths = new float[textLength];
571741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView.getPaint().getTextWidths(text.toString(), initialWidths);
571841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
571941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get advance widths of each character at letter spacing = 1.0f
572041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView,
572141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setLetterSpacing(1.0f));
572241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertEquals(1.0f, mTextView.getLetterSpacing());
572341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final float[] singleWidths = new float[textLength];
572441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView.getPaint().getTextWidths(text.toString(), singleWidths);
572541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
572641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get advance widths of each character at letter spacing = 2.0f
572741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView,
572841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                () -> mTextView.setLetterSpacing(2.0f));
572941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertEquals(2.0f, mTextView.getLetterSpacing());
573041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final float[] doubleWidths = new float[textLength];
573141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView.getPaint().getTextWidths(text.toString(), doubleWidths);
573241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
573341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Since letter spacing setter treats the parameter as EM units, and we don't have
573441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // a way to convert EMs into pixels, go over the three arrays of advance widths and
573541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // test that the extra advance width at letter spacing 2.0f is double the extra
573641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // advance width at letter spacing 1.0f.
573741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        for (int i = 0; i < textLength; i++) {
573841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            float singleWidthDelta = singleWidths[i] - initialWidths[i];
573941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            float doubleWidthDelta = doubleWidths[i] - initialWidths[i];
574041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            assertEquals("At index " + i + " initial is " + initialWidths[i] +
574141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                ", single is " + singleWidths[i] + " and double is " + doubleWidths[i],
574241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov                    singleWidthDelta * 2.0f, doubleWidthDelta, 0.05f);
574341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        }
574441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
574541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
5746288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu    public void testTextIsSelectableFocusAndOnClick() {
5747288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // Prepare a focusable TextView with an onClickListener attached.
5748288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        final View.OnClickListener mockOnClickListener = mock(View.OnClickListener.class);
5749288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        mActivity.runOnUiThread(() -> {
5750288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView = new TextView(mActivity);
5751288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView.setText("...zekiel 25:17. The path of the righteous...");
5752288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView.setFocusable(true);
5753288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mTextView.setOnClickListener(mockOnClickListener);
5754288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu            mActivity.setContentView(mTextView);
5755288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        });
5756288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
5757288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocusable());
5758288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isTextSelectable());
5759288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocusableInTouchMode());
5760288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
5761288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isInTouchMode());
5762288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
5763288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // First tap on the view triggers onClick() but does not focus the TextView.
5764288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
5765288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
5766288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
5767288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, times(1)).onClick(mTextView);
5768288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // So does the second tap.
5769288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        reset(mockOnClickListener);
5770288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
5771288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
5772288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
5773288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, times(1)).onClick(mTextView);
5774288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
5775288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setTextIsSelectable(true));
5776288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        mInstrumentation.waitForIdleSync();
5777288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocusable());
5778288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isTextSelectable());
5779288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocusableInTouchMode());
5780288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertFalse(mTextView.isFocused());
5781288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
5782288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // First tap on the view focuses the TextView but does not trigger onClick().
5783288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        reset(mockOnClickListener);
5784288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
5785288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
5786288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocused());
5787288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, never()).onClick(mTextView);
5788288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        // The second tap triggers onClick() and keeps the focus.
5789288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        reset(mockOnClickListener);
5790288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mTextView);
5791288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isInTouchMode());
5792288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        assertTrue(mTextView.isFocused());
5793288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu        verify(mockOnClickListener, times(1)).onClick(mTextView);
5794288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu    }
5795288d156a90ddd9dd93c05e4892a73390e3778c00Andrei Stingaceanu
579641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    private void verifyGetOffsetForPosition(final int x, final int y) {
579741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int actual = mTextView.getOffsetForPosition(x, y);
579841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
579941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final Layout layout = mTextView.getLayout();
580041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        if (layout == null) {
580141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            assertEquals("For [" + x + ", " + y + "]", -1, actual);
580241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            return;
580341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        }
580441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
580541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get the line which corresponds to the Y position
580641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int line = layout.getLineForVertical(y + mTextView.getScrollY());
580741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        // Get the offset in that line that corresponds to the X position
580841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int expected = layout.getOffsetForHorizontal(line, x + mTextView.getScrollX());
580941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertEquals("For [" + x + ", " + y + "]", expected, actual);
581041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
581141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
581241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    public void testGetOffsetForPosition() {
581341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        mTextView = findTextView(R.id.textview_text);
581441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView, () -> {
581541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            mTextView.setText(LONG_TEXT);
581641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov            mTextView.setPadding(0, 0, 0, 0);
581741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        });
581841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
581941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        assertNotNull(mTextView.getLayout());
582041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int viewWidth = mTextView.getWidth();
582141b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int viewHeight = mTextView.getHeight();
582241b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        final int lineHeight = mTextView.getLineHeight();
582341b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
582441b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(0, 0);
582541b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(0, viewHeight / 2);
582641b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(viewWidth / 3, lineHeight / 2);
582741b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(viewWidth / 2, viewHeight / 2);
582841b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov        verifyGetOffsetForPosition(viewWidth, viewHeight);
582941b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov    }
583041b3e249a7d16d5b58a079f64ed9d769393391b6Kirill Grouchnikov
583157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    @UiThreadTest
583257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    public void testOnResolvePointerIcon() throws InterruptedException {
583357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final TextView selectableTextView = findTextView(R.id.textview_pointer);
583457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final MotionEvent event = createMouseHoverEvent(selectableTextView);
583557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
583657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // A selectable view shows the I beam
583757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setTextIsSelectable(true);
583857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
583957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT),
584057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                selectableTextView.onResolvePointerIcon(event, 0));
584157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setTextIsSelectable(false);
584257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
584357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // A clickable view shows the hand
584457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setLinksClickable(true);
584557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        SpannableString builder = new SpannableString("hello world");
584657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setText(builder, BufferType.SPANNABLE);
584757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        Spannable text = (Spannable) selectableTextView.getText();
584857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        text.setSpan(
584957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                new ClickableSpan() {
585057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                    @Override
585157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                    public void onClick(View widget) {
585257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
585357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                    }
585457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                }, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
585557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
585657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HAND),
585757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                selectableTextView.onResolvePointerIcon(event, 0));
585857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
585957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // A selectable & clickable view shows hand
586057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        selectableTextView.setTextIsSelectable(true);
586157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
586257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HAND),
586357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                selectableTextView.onResolvePointerIcon(event, 0));
586457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
586557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        // An editable view shows the I-beam
586657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final TextView editableTextView = new EditText(mActivity);
586757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
586857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT),
586957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                editableTextView.onResolvePointerIcon(event, 0));
587057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    }
587157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
587257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    private MotionEvent createMouseHoverEvent(View view) {
587357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int[] xy = new int[2];
587457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        view.getLocationOnScreen(xy);
587557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int viewWidth = view.getWidth();
587657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int viewHeight = view.getHeight();
587757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        float x = xy[0] + viewWidth / 2.0f;
587857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        float y = xy[1] + viewHeight / 2.0f;
587957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        long eventTime = SystemClock.uptimeMillis();
588057c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[1];
588157c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerCoords[0] = new MotionEvent.PointerCoords();
588257c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerCoords[0].x = x;
588357c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerCoords[0].y = y;
588457c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        final int[] pointerIds = new int[1];
588557c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        pointerIds[0] = 0;
588657c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri        return MotionEvent.obtain(0, eventTime, MotionEvent.ACTION_HOVER_MOVE, 1, pointerIds,
588757c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri                pointerCoords, 0, 0, 0, 0, 0, InputDevice.SOURCE_MOUSE, 0);
588857c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri    }
588957c708762722100ec4e7b4fa57c67248c5a50b66Clara Bayarri
5890fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void layout(final TextView textView) {
58916beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mActivity.setContentView(textView));
5892fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5893fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5894fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5895fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void layout(final int layoutId) {
58966beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mActivity.setContentView(layoutId));
5897fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5898fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5899fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5900fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private TextView findTextView(int id) {
5901fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        return (TextView) mActivity.findViewById(id);
5902fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5903fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5904fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private int getAutoLinkMask(int id) {
5905fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        return findTextView(id).getAutoLinkMask();
5906fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5907fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
59086a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    private void setMaxLines(final int lines) {
59096beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMaxLines(lines));
59106a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir        mInstrumentation.waitForIdleSync();
59116a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir    }
59126a7d70f520117b679dc0e8af433e4241b47fe8b6Siyamed Sinir
5913fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMaxWidth(final int pixels) {
59146beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMaxWidth(pixels));
5915fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5916fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5917fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5918fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMinWidth(final int pixels) {
59196beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMinWidth(pixels));
5920fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5921fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5922fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5923fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMaxHeight(final int pixels) {
59246beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMaxHeight(pixels));
5925fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5926fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5927fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5928fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMinHeight(final int pixels) {
59296beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMinHeight(pixels));
5930fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5931fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5932fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5933fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMinLines(final int minlines) {
59346beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMinLines(minlines));
5935fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5936fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5937fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5938fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    /**
5939fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * Convenience for {@link TextView#setText(CharSequence, BufferType)}. And
5940fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * the buffer type is fixed to SPANNABLE.
5941fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     *
5942fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * @param tv the text view
5943fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     * @param content the content
5944fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su     */
5945fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setSpannableText(final TextView tv, final String content) {
59466beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> tv.setText(content, BufferType.SPANNABLE));
5947fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5948fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5949fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5950fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setLines(final int lines) {
59516beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setLines(lines));
5952fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5953fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5954fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5955fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setHorizontallyScrolling(final boolean whether) {
59566beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setHorizontallyScrolling(whether));
5957fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5958fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5959fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5960fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setWidth(final int pixels) {
59616beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setWidth(pixels));
5962fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5963fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5964fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5965fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setHeight(final int pixels) {
59666beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setHeight(pixels));
5967fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5968fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5969fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5970fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMinEms(final int ems) {
59716beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMinEms(ems));
5972fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5973fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5974fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5975fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setMaxEms(final int ems) {
59766beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setMaxEms(ems));
5977fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5978fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5979fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5980fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setEms(final int ems) {
59816beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setEms(ems));
5982fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5983fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5984fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5985fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private void setLineSpacing(final float add, final float mult) {
59866beed5d1888fd4878ad9bbcaa8a8a83a4e1ebfa9Andrei Stingaceanu        mActivity.runOnUiThread(() -> mTextView.setLineSpacing(add, mult));
5987fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        mInstrumentation.waitForIdleSync();
5988fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
5989fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5990fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static abstract class TestSelectedRunnable implements Runnable {
5991fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private TextView mTextView;
5992fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mIsSelected1;
5993fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mIsSelected2;
5994fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5995fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public TestSelectedRunnable(TextView textview) {
5996fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView = textview;
5997fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
5998fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
5999fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean getIsSelected1() {
6000fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mIsSelected1;
6001fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6002fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6003fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean getIsSelected2() {
6004fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mIsSelected2;
6005fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6006fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6007fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void saveIsSelected1() {
6008fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mIsSelected1 = mTextView.isSelected();
6009fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6010fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6011fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void saveIsSelected2() {
6012fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mIsSelected2 = mTextView.isSelected();
6013fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6014fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6015fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6016fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static abstract class TestLayoutRunnable implements Runnable {
6017fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private TextView mTextView;
6018fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private Layout mLayout;
6019fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6020fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public TestLayoutRunnable(TextView textview) {
6021fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mTextView = textview;
6022fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6023fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6024fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public Layout getLayout() {
6025fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mLayout;
6026fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6027fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6028fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void saveLayout() {
6029fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mLayout = mTextView.getLayout();
6030fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6031fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6032fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6033fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    private static class MockTextWatcher implements TextWatcher {
6034fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mHasCalledAfterTextChanged;
6035fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mHasCalledBeforeTextChanged;
6036fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        private boolean mHasOnTextChanged;
6037fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6038fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void reset(){
6039fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledAfterTextChanged = false;
6040fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledBeforeTextChanged = false;
6041fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasOnTextChanged = false;
6042fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6043fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6044fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean hasCalledAfterTextChanged() {
6045fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mHasCalledAfterTextChanged;
6046fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6047fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6048fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean hasCalledBeforeTextChanged() {
6049fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mHasCalledBeforeTextChanged;
6050fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6051fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6052fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public boolean hasCalledOnTextChanged() {
6053fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            return mHasOnTextChanged;
6054fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6055fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6056fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void afterTextChanged(Editable s) {
6057fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledAfterTextChanged = true;
6058fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6059fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6060fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
6061fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasCalledBeforeTextChanged = true;
6062fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6063fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6064fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        public void onTextChanged(CharSequence s, int start, int before, int count) {
6065fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su            mHasOnTextChanged = true;
6066fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su        }
6067fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    }
6068fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su
6069fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su    /**
6070277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook     * A TextWatcher that converts the text to spaces whenever the text changes.
6071277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook     */
6072277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    private static class ConvertToSpacesTextWatcher implements TextWatcher {
6073277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        boolean mChangingText;
6074277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
6075277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        @Override
6076277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
6077277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        }
6078277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
6079277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        @Override
6080277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        public void onTextChanged(CharSequence s, int start, int before, int count) {
6081277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        }
6082277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook
6083277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        @Override
6084277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        public void afterTextChanged(Editable s) {
6085277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            // Avoid infinite recursion.
6086277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            if (mChangingText) {
6087277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook                return;
6088277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            }
6089277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            mChangingText = true;
6090277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            // Create a string of s.length() spaces.
6091277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            StringBuilder builder = new StringBuilder(s.length());
6092277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            for (int i = 0; i < s.length(); i++) {
6093277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook                builder.append(' ');
6094277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            }
6095277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            s.replace(0, s.length(), builder.toString());
6096277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook            mChangingText = false;
6097277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook        }
6098277fd69e9d1f08b601cd6f12ff5f13e200a6b63aJames Cook    }
6099fa0bdcfa2bdacc555a6cecd0e5e0ed46afa06970Scott Su}
6100