Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.appcompat.widget;
     18 
     19 import static org.junit.Assert.assertArrayEquals;
     20 import static org.junit.Assert.assertEquals;
     21 import static org.junit.Assert.assertNotEquals;
     22 import static org.junit.Assert.assertNotNull;
     23 import static org.junit.Assert.assertTrue;
     24 
     25 import android.app.Instrumentation;
     26 import android.graphics.Rect;
     27 import android.graphics.Typeface;
     28 import android.graphics.drawable.Drawable;
     29 import android.os.Build;
     30 import android.support.test.InstrumentationRegistry;
     31 import android.support.test.filters.MediumTest;
     32 import android.support.test.filters.SdkSuppress;
     33 import android.support.test.filters.SmallTest;
     34 import android.support.test.rule.ActivityTestRule;
     35 import android.text.TextUtils;
     36 import android.text.method.TransformationMethod;
     37 import android.util.DisplayMetrics;
     38 import android.util.TypedValue;
     39 import android.view.View;
     40 import android.view.ViewGroup;
     41 import android.widget.LinearLayout;
     42 import android.widget.TextView;
     43 
     44 import androidx.annotation.IdRes;
     45 import androidx.appcompat.test.R;
     46 import androidx.appcompat.testutils.BaseTestActivity;
     47 import androidx.core.content.res.ResourcesCompat;
     48 import androidx.core.widget.AutoSizeableTextView;
     49 import androidx.core.widget.TextViewCompat;
     50 
     51 import org.junit.Before;
     52 import org.junit.Rule;
     53 import org.junit.Test;
     54 
     55 /**
     56  * Base class for testing auto-size-text enabled views in appcompat-v7 that implement the
     57  * <code>AutoSizeableTextView</code> interface. Extensions of this class run all tests
     58  * from here and can add test cases specific to the functionality they add to the relevant
     59  * base view class.
     60  */
     61 public abstract class AppCompatBaseAutoSizeTest<A extends BaseTestActivity,
     62         T extends TextView & AutoSizeableTextView> {
     63 
     64     @Rule
     65     public final ActivityTestRule<A> mActivityTestRule;
     66 
     67     protected A mActivity;
     68     protected Instrumentation mInstrumentation;
     69     protected ViewGroup mContainer;
     70 
     71     public AppCompatBaseAutoSizeTest(Class clazz) {
     72         mActivityTestRule = new ActivityTestRule<A>(clazz);
     73     }
     74 
     75     @Before
     76     public void setup() {
     77         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     78         mActivity = mActivityTestRule.getActivity();
     79         mContainer = mActivity.findViewById(R.id.container);
     80     }
     81 
     82     @Test
     83     @MediumTest
     84     @SdkSuppress(minSdkVersion = 16)
     85     // public TextView#getMaxLines only introduced in API 16.
     86     public void testAutoSizeCallers_setMaxLines() throws Throwable {
     87         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
     88                 false);
     89         // Configure layout params and auto-size both in pixels to dodge flakiness on different
     90         // devices.
     91         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
     92                 500, 500);
     93         final String text = "one two three four five six seven eight nine ten";
     94         mActivity.runOnUiThread(new Runnable() {
     95             @Override
     96             public void run() {
     97                 autoSizeView.setLayoutParams(layoutParams);
     98                 ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
     99                         1 /* autoSizeMinTextSize */,
    100                         5000 /* autoSizeMaxTextSize */,
    101                         1 /* autoSizeStepGranularity */,
    102                         TypedValue.COMPLEX_UNIT_PX);
    103                 autoSizeView.setText(text);
    104             }
    105         });
    106         mInstrumentation.waitForIdleSync();
    107 
    108         float initialSize = 0;
    109         for (int i = 1; i < 10; i++) {
    110             final int maxLines = i;
    111             mActivity.runOnUiThread(new Runnable() {
    112                 @Override
    113                 public void run() {
    114                     autoSizeView.setMaxLines(maxLines);
    115                 }
    116             });
    117             mInstrumentation.waitForIdleSync();
    118             float expectedSmallerSize = autoSizeView.getTextSize();
    119             if (i == 1) {
    120                 initialSize = expectedSmallerSize;
    121             }
    122 
    123             mActivity.runOnUiThread(new Runnable() {
    124                 @Override
    125                 public void run() {
    126                     autoSizeView.setMaxLines(maxLines + 1);
    127                 }
    128             });
    129             mInstrumentation.waitForIdleSync();
    130             assertTrue(expectedSmallerSize <= autoSizeView.getTextSize());
    131         }
    132         assertTrue(initialSize < autoSizeView.getTextSize());
    133 
    134         initialSize = 999999;
    135         for (int i = 10; i > 1; i--) {
    136             final int maxLines = i;
    137             mActivity.runOnUiThread(new Runnable() {
    138                 @Override
    139                 public void run() {
    140                     autoSizeView.setMaxLines(maxLines);
    141                 }
    142             });
    143             mInstrumentation.waitForIdleSync();
    144             float expectedLargerSize = autoSizeView.getTextSize();
    145             if (i == 10) {
    146                 initialSize = expectedLargerSize;
    147             }
    148 
    149             mActivity.runOnUiThread(new Runnable() {
    150                 @Override
    151                 public void run() {
    152                     autoSizeView.setMaxLines(maxLines - 1);
    153                 }
    154             });
    155             mInstrumentation.waitForIdleSync();
    156             assertTrue(expectedLargerSize >= autoSizeView.getTextSize());
    157         }
    158         assertTrue(initialSize > autoSizeView.getTextSize());
    159     }
    160 
    161     @Test
    162     @MediumTest
    163     public void testAutoSizeUniform_autoSizeCalledWhenTypeChanged() throws Throwable {
    164         final T view = mContainer.findViewById(R.id.view_text);
    165 
    166         // Make sure we pick an already inflated non auto-sized text view.
    167         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
    168                 ((AutoSizeableTextView) view).getAutoSizeTextType());
    169         // Set the text size to a very low value in order to prepare for auto-size.
    170         final int customTextSize = 3;
    171         mActivityTestRule.runOnUiThread(new Runnable() {
    172             @Override
    173             public void run() {
    174                 view.setTextSize(TypedValue.COMPLEX_UNIT_PX, customTextSize);
    175             }
    176         });
    177         mInstrumentation.waitForIdleSync();
    178         assertEquals(customTextSize, view.getTextSize(), 0f);
    179         mActivityTestRule.runOnUiThread(new Runnable() {
    180             @Override
    181             public void run() {
    182                 ((AutoSizeableTextView) view).setAutoSizeTextTypeWithDefaults(
    183                         TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
    184             }
    185         });
    186         mInstrumentation.waitForIdleSync();
    187         // The size of the text should have changed.
    188         assertNotEquals(customTextSize, view.getTextSize(), 0f);
    189     }
    190 
    191     @Test
    192     @MediumTest
    193     public void testAutoSizeCallers_setText() throws Throwable {
    194         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    195                 false);
    196 
    197         // Configure layout params and auto-size both in pixels to dodge flakiness on different
    198         // devices.
    199         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    200                 500, 500);
    201         mActivity.runOnUiThread(new Runnable() {
    202             @Override
    203             public void run() {
    204                 autoSizeView.setLayoutParams(layoutParams);
    205                 ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
    206                         1, 5000, 1, TypedValue.COMPLEX_UNIT_PX);
    207             }
    208         });
    209         mInstrumentation.waitForIdleSync();
    210 
    211         final String initialText = "13characters ";
    212         final StringBuilder textToSet = new StringBuilder().append(initialText);
    213         float initialSize = 0;
    214 
    215         // As we add characters the text size shrinks.
    216         for (int i = 0; i < 10; i++) {
    217             mActivity.runOnUiThread(new Runnable() {
    218                 @Override
    219                 public void run() {
    220                     autoSizeView.setText(textToSet.toString());
    221                 }
    222             });
    223 
    224             mInstrumentation.waitForIdleSync();
    225             float expectedLargerSize = autoSizeView.getTextSize();
    226             if (i == 0) {
    227                 initialSize = expectedLargerSize;
    228             }
    229 
    230             textToSet.append(initialText);
    231             mActivity.runOnUiThread(new Runnable() {
    232                 @Override
    233                 public void run() {
    234                     autoSizeView.setText(textToSet.toString());
    235                 }
    236             });
    237             mInstrumentation.waitForIdleSync();
    238             assertTrue(expectedLargerSize >= autoSizeView.getTextSize());
    239         }
    240         assertTrue(initialSize > autoSizeView.getTextSize());
    241 
    242         initialSize = 9999999;
    243         // As we remove characters the text size expands.
    244         for (int i = 9; i >= 0; i--) {
    245             mActivity.runOnUiThread(new Runnable() {
    246                 @Override
    247                 public void run() {
    248                     autoSizeView.setText(textToSet.toString());
    249                 }
    250             });
    251             mInstrumentation.waitForIdleSync();
    252             float expectedSmallerSize = autoSizeView.getTextSize();
    253             if (i == 0) {
    254                 initialSize = expectedSmallerSize;
    255             }
    256 
    257             textToSet.replace((textToSet.length() - initialText.length()),
    258                     textToSet.length(), "");
    259             mActivity.runOnUiThread(new Runnable() {
    260                 @Override
    261                 public void run() {
    262                     autoSizeView.setText(textToSet.toString());
    263                 }
    264             });
    265             mInstrumentation.waitForIdleSync();
    266 
    267             assertTrue(autoSizeView.getTextSize() >= expectedSmallerSize);
    268         }
    269         assertTrue(autoSizeView.getTextSize() > initialSize);
    270     }
    271 
    272     @Test
    273     @MediumTest
    274     public void testAutoSizeUniform_equivalentConfigurations() throws Throwable {
    275         final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
    276         final int minTextSize = 10;
    277         final int maxTextSize = 20;
    278         final int granularity = 2;
    279         final int unit = TypedValue.COMPLEX_UNIT_SP;
    280 
    281         final T granularityView = getNewAutoSizeViewInstance();
    282         ((AutoSizeableTextView) granularityView).setAutoSizeTextTypeUniformWithConfiguration(
    283                 minTextSize, maxTextSize, granularity, unit);
    284 
    285         final T presetView = getNewAutoSizeViewInstance();
    286         ((AutoSizeableTextView) presetView).setAutoSizeTextTypeUniformWithPresetSizes(
    287                 new int[]{minTextSize, 12, 14, 16, 18, maxTextSize}, unit);
    288 
    289         // The TextViews have been configured differently but the end result should be nearly
    290         // identical.
    291         final int expectedAutoSizeType = AppCompatTextView.AUTO_SIZE_TEXT_TYPE_UNIFORM;
    292         assertEquals(expectedAutoSizeType,
    293                 ((AutoSizeableTextView) granularityView).getAutoSizeTextType());
    294         assertEquals(expectedAutoSizeType,
    295                 ((AutoSizeableTextView) presetView).getAutoSizeTextType());
    296 
    297         final int expectedMinTextSizeInPx = Math.round(
    298                 TypedValue.applyDimension(unit, minTextSize, dm));
    299         assertEquals(expectedMinTextSizeInPx,
    300                 ((AutoSizeableTextView) granularityView).getAutoSizeMinTextSize());
    301         assertEquals(expectedMinTextSizeInPx,
    302                 ((AutoSizeableTextView) presetView).getAutoSizeMinTextSize());
    303 
    304         final int expectedMaxTextSizeInPx = Math.round(
    305                 TypedValue.applyDimension(unit, maxTextSize, dm));
    306         assertEquals(expectedMaxTextSizeInPx,
    307                 ((AutoSizeableTextView) granularityView).getAutoSizeMaxTextSize());
    308         assertEquals(expectedMaxTextSizeInPx,
    309                 ((AutoSizeableTextView) presetView).getAutoSizeMaxTextSize());
    310 
    311         // Configured with granularity.
    312         assertEquals(Math.round(TypedValue.applyDimension(unit, granularity, dm)),
    313                 ((AutoSizeableTextView) granularityView).getAutoSizeStepGranularity());
    314         // Configured with preset values, there is no granularity.
    315         assertEquals(-1,
    316                 ((AutoSizeableTextView) presetView).getAutoSizeStepGranularity());
    317 
    318         // Both TextViews generate exactly the same sizes in pixels to choose from when auto-sizing.
    319         assertArrayEquals(
    320                 ((AutoSizeableTextView) granularityView).getAutoSizeTextAvailableSizes(),
    321                 ((AutoSizeableTextView) presetView).getAutoSizeTextAvailableSizes());
    322 
    323         final String someText = "This is a string";
    324         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    325                 500, 500);
    326         // Configure identically and attach to layout.
    327         mActivityTestRule.runOnUiThread(new Runnable() {
    328             @Override
    329             public void run() {
    330                 granularityView.setLayoutParams(layoutParams);
    331                 presetView.setLayoutParams(layoutParams);
    332 
    333                 LinearLayout ll = mActivity.findViewById(R.id.container);
    334                 ll.removeAllViews();
    335                 ll.addView(granularityView);
    336                 ll.addView(presetView);
    337 
    338                 granularityView.setText(someText);
    339                 presetView.setText(someText);
    340             }
    341         });
    342         mInstrumentation.waitForIdleSync();
    343 
    344         assertEquals(granularityView.getTextSize(), presetView.getTextSize(), 0f);
    345     }
    346 
    347     @Test
    348     @MediumTest
    349     public void testAutoSizeCallers_setHeight() throws Throwable {
    350         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(
    351                 R.id.view_autosize_uniform, true);
    352         // Do not force exact height only.
    353         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    354                 200,
    355                 LinearLayout.LayoutParams.WRAP_CONTENT);
    356         mActivityTestRule.runOnUiThread(new Runnable() {
    357             @Override
    358             public void run() {
    359                 autoSizeView.setLayoutParams(layoutParams);
    360             }
    361         });
    362         mInstrumentation.waitForIdleSync();
    363         final float initialTextSize = autoSizeView.getTextSize();
    364         mActivityTestRule.runOnUiThread(new Runnable() {
    365             @Override
    366             public void run() {
    367                 autoSizeView.setHeight(autoSizeView.getHeight() / 4);
    368             }
    369         });
    370         mInstrumentation.waitForIdleSync();
    371 
    372         assertTrue(autoSizeView.getTextSize() < initialTextSize);
    373     }
    374 
    375     @Test
    376     @MediumTest
    377     public void testAutoSizeCallers_setTransformationMethod() throws Throwable {
    378         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    379                 false);
    380         mActivityTestRule.runOnUiThread(new Runnable() {
    381             @Override
    382             public void run() {
    383                 autoSizeView.setTransformationMethod(null);
    384             }
    385         });
    386         mInstrumentation.waitForIdleSync();
    387         final float initialTextSize = autoSizeView.getTextSize();
    388         mActivityTestRule.runOnUiThread(new Runnable() {
    389             @Override
    390             public void run() {
    391                 autoSizeView.setTransformationMethod(new DoubleTextTransformationMethod());
    392             }
    393         });
    394         mInstrumentation.waitForIdleSync();
    395 
    396         assertTrue(autoSizeView.getTextSize() < initialTextSize);
    397     }
    398 
    399     @Test
    400     @MediumTest
    401     public void testAutoSizeCallers_setCompoundDrawables() throws Throwable {
    402         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    403                 false);
    404         final float initialTextSize = autoSizeView.getTextSize();
    405         final Drawable drawable = ResourcesCompat.getDrawable(mActivity.getResources(),
    406                 R.drawable.test_drawable_red, null);
    407         drawable.setBounds(0, 0, autoSizeView.getWidth() / 3, autoSizeView.getHeight() / 3);
    408         mActivityTestRule.runOnUiThread(new Runnable() {
    409             @Override
    410             public void run() {
    411                 autoSizeView.setCompoundDrawables(drawable, drawable, drawable, drawable);
    412             }
    413         });
    414         mInstrumentation.waitForIdleSync();
    415 
    416         assertTrue(autoSizeView.getTextSize() < initialTextSize);
    417     }
    418 
    419     @Test
    420     @MediumTest
    421     public void testAutoSizeCallers_setCompoundDrawablesRelative() throws Throwable {
    422         if (Build.VERSION.SDK_INT >= 17) {
    423             final T autoSizeView = prepareAndRetrieveAutoSizeTestData(
    424                     R.id.view_autosize_uniform, false);
    425             final float initialTextSize = autoSizeView.getTextSize();
    426             final Drawable drawable = ResourcesCompat.getDrawable(mActivity.getResources(),
    427                     R.drawable.test_drawable_red, null);
    428             drawable.setBounds(0, 0, autoSizeView.getWidth() / 3,
    429                     autoSizeView.getHeight() / 3);
    430             mActivityTestRule.runOnUiThread(new Runnable() {
    431                 @Override
    432                 public void run() {
    433                     if (Build.VERSION.SDK_INT >= 17) {
    434                         autoSizeView.setCompoundDrawablesRelative(
    435                                 drawable, drawable, drawable, drawable);
    436                     }
    437                 }
    438             });
    439             mInstrumentation.waitForIdleSync();
    440 
    441             assertTrue(autoSizeView.getTextSize() < initialTextSize);
    442         }
    443     }
    444 
    445     @Test
    446     @MediumTest
    447     public void testAutoSizeCallers_setCompoundDrawablePadding() throws Throwable {
    448         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    449                 false);
    450         // Prepare a larger layout in order not to hit the min value easily.
    451         mActivityTestRule.runOnUiThread(new Runnable() {
    452             @Override
    453             public void run() {
    454                 autoSizeView.setWidth(autoSizeView.getWidth() * 2);
    455                 autoSizeView.setHeight(autoSizeView.getHeight() * 2);
    456             }
    457         });
    458         mInstrumentation.waitForIdleSync();
    459         // Setup the drawables before setting their padding in order to modify the available
    460         // space and trigger a resize.
    461         final Drawable drawable = ResourcesCompat.getDrawable(mActivity.getResources(),
    462                 R.drawable.test_drawable_red, null);
    463         drawable.setBounds(0, 0, autoSizeView.getWidth() / 4, autoSizeView.getHeight() / 4);
    464         mActivityTestRule.runOnUiThread(new Runnable() {
    465             @Override
    466             public void run() {
    467                 autoSizeView.setCompoundDrawables(
    468                         drawable, drawable, drawable, drawable);
    469             }
    470         });
    471         mInstrumentation.waitForIdleSync();
    472         final float initialTextSize = autoSizeView.getTextSize();
    473         mActivityTestRule.runOnUiThread(new Runnable() {
    474             @Override
    475             public void run() {
    476                 autoSizeView.setCompoundDrawablePadding(
    477                         autoSizeView.getCompoundDrawablePadding() + 10);
    478             }
    479         });
    480         mInstrumentation.waitForIdleSync();
    481 
    482         assertTrue(autoSizeView.getTextSize() < initialTextSize);
    483     }
    484 
    485     @Test
    486     @MediumTest
    487     public void testAutoSizeCallers_setPadding() throws Throwable {
    488         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    489                 false);
    490         final float initialTextSize = autoSizeView.getTextSize();
    491         mActivityTestRule.runOnUiThread(new Runnable() {
    492             @Override
    493             public void run() {
    494                 autoSizeView.setPadding(
    495                         autoSizeView.getWidth() / 3, autoSizeView.getHeight() / 3,
    496                         autoSizeView.getWidth() / 3, autoSizeView.getHeight() / 3);
    497             }
    498         });
    499         mInstrumentation.waitForIdleSync();
    500 
    501         assertTrue(autoSizeView.getTextSize() < initialTextSize);
    502     }
    503 
    504     @Test
    505     @MediumTest
    506     public void testAutoSizeCallers_setPaddingRelative() throws Throwable {
    507         if (Build.VERSION.SDK_INT >= 16) {
    508             final T autoSizeView = prepareAndRetrieveAutoSizeTestData(
    509                     R.id.view_autosize_uniform, false);
    510             final float initialTextSize = autoSizeView.getTextSize();
    511 
    512             mActivityTestRule.runOnUiThread(new Runnable() {
    513                 @Override
    514                 public void run() {
    515                     if (Build.VERSION.SDK_INT > 16) {
    516                         autoSizeView.setPaddingRelative(
    517                                 autoSizeView.getWidth() / 3, autoSizeView.getHeight() / 3,
    518                                 autoSizeView.getWidth() / 3, autoSizeView.getHeight() / 3);
    519                     }
    520                 }
    521             });
    522             mInstrumentation.waitForIdleSync();
    523 
    524             assertTrue(autoSizeView.getTextSize() < initialTextSize);
    525         }
    526     }
    527 
    528     @Test
    529     @MediumTest
    530     public void testAutoSizeCallers_setTypeface() throws Throwable {
    531         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    532                 false);
    533         mActivityTestRule.runOnUiThread(new Runnable() {
    534             @Override
    535             public void run() {
    536                 autoSizeView.setText("The typeface change needs a bit more text then "
    537                         + "the default used for this batch of tests in order to get to resize text."
    538                         + " The resize function is always called but even with different typefaces "
    539                         + "there may not be a need to resize text because it just fits. The longer "
    540                         + "the text, the higher the chance for a resize. And here is yet another "
    541                         + "sentence to make sure this test is not flaky. Not flaky at all.");
    542             }
    543         });
    544         mInstrumentation.waitForIdleSync();
    545         final float initialTextSize = autoSizeView.getTextSize();
    546 
    547         mActivityTestRule.runOnUiThread(new Runnable() {
    548             @Override
    549             public void run() {
    550                 Typeface differentTypeface = Typeface.MONOSPACE;
    551                 if (autoSizeView.getTypeface() == Typeface.MONOSPACE) {
    552                     differentTypeface = Typeface.SANS_SERIF;
    553                 }
    554                 autoSizeView.setTypeface(differentTypeface);
    555             }
    556         });
    557         mInstrumentation.waitForIdleSync();
    558         final float changedTextSize = autoSizeView.getTextSize();
    559 
    560         // Don't really know if it is larger or smaller (depends on the typeface chosen above),
    561         // but it should definitely have changed.
    562         assertNotEquals(initialTextSize, changedTextSize, 0f);
    563 
    564         mActivityTestRule.runOnUiThread(new Runnable() {
    565             @Override
    566             public void run() {
    567                 autoSizeView.setTypeface(autoSizeView.getTypeface());
    568             }
    569         });
    570         mInstrumentation.waitForIdleSync();
    571 
    572         assertEquals(changedTextSize, autoSizeView.getTextSize(), 0f);
    573     }
    574 
    575     @Test
    576     @MediumTest
    577     public void testAutoSizeCallers_setLetterSpacing() throws Throwable {
    578         if (Build.VERSION.SDK_INT >= 21) {
    579             final T autoSizeView = prepareAndRetrieveAutoSizeTestData(
    580                     R.id.view_autosize_uniform, false);
    581             final float initialTextSize = autoSizeView.getTextSize();
    582 
    583             mActivityTestRule.runOnUiThread(new Runnable() {
    584                 @Override
    585                 public void run() {
    586                     if (Build.VERSION.SDK_INT >= 21) {
    587                         autoSizeView.setLetterSpacing(
    588                                 autoSizeView.getLetterSpacing() * 1.5f + 4.5f);
    589                     }
    590                 }
    591             });
    592             mInstrumentation.waitForIdleSync();
    593             final float changedTextSize = autoSizeView.getTextSize();
    594 
    595             assertTrue(changedTextSize < initialTextSize);
    596 
    597             mActivityTestRule.runOnUiThread(new Runnable() {
    598                 @Override
    599                 public void run() {
    600                     if (Build.VERSION.SDK_INT >= 21) {
    601                         autoSizeView.setLetterSpacing(autoSizeView.getLetterSpacing());
    602                     }
    603                 }
    604             });
    605             mInstrumentation.waitForIdleSync();
    606 
    607             assertEquals(changedTextSize, autoSizeView.getTextSize(), 0f);
    608         }
    609     }
    610 
    611     @Test
    612     @MediumTest
    613     public void testAutoSizeCallers_setMaxHeight() throws Throwable {
    614         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    615                 true);
    616         // Do not force exact height only.
    617         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    618                 200,
    619                 LinearLayout.LayoutParams.WRAP_CONTENT);
    620         mActivityTestRule.runOnUiThread(new Runnable() {
    621             @Override
    622             public void run() {
    623                 autoSizeView.setLayoutParams(layoutParams);
    624             }
    625         });
    626         mInstrumentation.waitForIdleSync();
    627         final float initialTextSize = autoSizeView.getTextSize();
    628         mActivityTestRule.runOnUiThread(new Runnable() {
    629             @Override
    630             public void run() {
    631                 autoSizeView.setMaxHeight(autoSizeView.getHeight() / 4);
    632             }
    633         });
    634         mInstrumentation.waitForIdleSync();
    635 
    636         assertTrue(autoSizeView.getTextSize() < initialTextSize);
    637     }
    638 
    639     @Test
    640     @MediumTest
    641     public void testAutoSizeCallers_setMaxWidth() throws Throwable {
    642         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    643                 true);
    644         // Do not force exact width only.
    645         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    646                 LinearLayout.LayoutParams.WRAP_CONTENT,
    647                 200);
    648         mActivityTestRule.runOnUiThread(new Runnable() {
    649             @Override
    650             public void run() {
    651                 autoSizeView.setLayoutParams(layoutParams);
    652             }
    653         });
    654         mInstrumentation.waitForIdleSync();
    655         final float initialTextSize = autoSizeView.getTextSize();
    656         mActivityTestRule.runOnUiThread(new Runnable() {
    657             @Override
    658             public void run() {
    659                 autoSizeView.setMaxWidth(autoSizeView.getWidth() / 4);
    660             }
    661         });
    662         mInstrumentation.waitForIdleSync();
    663 
    664         assertTrue(autoSizeView.getTextSize() != initialTextSize);
    665     }
    666 
    667     @Test
    668     @MediumTest
    669     public void testAutoSizeCallers_setWidth() throws Throwable {
    670         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    671                 true);
    672         // Do not force exact width only.
    673         final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    674                 LinearLayout.LayoutParams.WRAP_CONTENT,
    675                 200);
    676         mActivityTestRule.runOnUiThread(new Runnable() {
    677             @Override
    678             public void run() {
    679                 autoSizeView.setLayoutParams(layoutParams);
    680             }
    681         });
    682         mInstrumentation.waitForIdleSync();
    683 
    684         final float initialTextSize = autoSizeView.getTextSize();
    685         mActivityTestRule.runOnUiThread(new Runnable() {
    686             @Override
    687             public void run() {
    688                 autoSizeView.setWidth(autoSizeView.getWidth() / 4);
    689             }
    690         });
    691         mInstrumentation.waitForIdleSync();
    692 
    693         assertTrue(autoSizeView.getTextSize() != initialTextSize);
    694     }
    695 
    696     @Test
    697     @MediumTest
    698     public void testAutoSizeCallers_setTextSizeIsNoOp() throws Throwable {
    699         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    700                 false);
    701         final float initialTextSize = autoSizeView.getTextSize();
    702 
    703         mActivityTestRule.runOnUiThread(new Runnable() {
    704             @Override
    705             public void run() {
    706                 autoSizeView.setTextSize(initialTextSize + 123f);
    707             }
    708         });
    709         mInstrumentation.waitForIdleSync();
    710 
    711         assertEquals(initialTextSize, autoSizeView.getTextSize(), 0f);
    712     }
    713 
    714     @Test
    715     @MediumTest
    716     public void testAutoSizeCallers_setHorizontallyScrolling() throws Throwable {
    717         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
    718                 false);
    719         // Horizontal scrolling is expected to be deactivated for this test.
    720         final float initialTextSize = autoSizeView.getTextSize();
    721         mActivityTestRule.runOnUiThread(new Runnable() {
    722             @Override
    723             public void run() {
    724                 autoSizeView.setHorizontallyScrolling(true);
    725             }
    726         });
    727         mInstrumentation.waitForIdleSync();
    728         assertTrue(autoSizeView.getTextSize() > initialTextSize);
    729 
    730         mActivityTestRule.runOnUiThread(new Runnable() {
    731             @Override
    732             public void run() {
    733                 autoSizeView.setHorizontallyScrolling(false);
    734             }
    735         });
    736         mInstrumentation.waitForIdleSync();
    737         assertEquals(initialTextSize, autoSizeView.getTextSize(), 0f);
    738     }
    739 
    740     @Test
    741     @MediumTest
    742     public void testAutoSize_setEllipsize() throws Throwable {
    743         final T autoSizeView = mActivity.findViewById(R.id.view_autosize_uniform_predef_sizes);
    744         final int initialAutoSizeType = ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType();
    745         final int initialMinTextSize =
    746                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize();
    747         final int initialMaxTextSize =
    748                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize();
    749         final int initialAutoSizeGranularity =
    750                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity();
    751         final int initialSizes =
    752                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextAvailableSizes().length;
    753 
    754         assertEquals(null, autoSizeView.getEllipsize());
    755         // Verify styled attributes.
    756         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM, initialAutoSizeType);
    757         assertNotEquals(-1, initialMinTextSize);
    758         assertNotEquals(-1, initialMaxTextSize);
    759         // Because this TextView has been configured to use predefined sizes.
    760         assertEquals(-1, initialAutoSizeGranularity);
    761         assertNotEquals(0, initialSizes);
    762 
    763         final TextUtils.TruncateAt newEllipsizeValue = TextUtils.TruncateAt.END;
    764         mActivityTestRule.runOnUiThread(new Runnable() {
    765             @Override
    766             public void run() {
    767                 autoSizeView.setEllipsize(newEllipsizeValue);
    768             }
    769         });
    770         mInstrumentation.waitForIdleSync();
    771         assertEquals(newEllipsizeValue, autoSizeView.getEllipsize());
    772         // Beside the ellipsis no auto-size attribute has changed.
    773         assertEquals(initialAutoSizeType,
    774                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
    775         assertEquals(initialMinTextSize,
    776                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize());
    777         assertEquals(initialMaxTextSize,
    778                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize());
    779         assertEquals(initialAutoSizeGranularity,
    780                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
    781         assertEquals(initialSizes,
    782                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextAvailableSizes().length);
    783     }
    784 
    785     @Test
    786     @MediumTest
    787     public void testEllipsize_setAutoSize() throws Throwable {
    788         final T view = mActivity.findViewById(R.id.view_text);
    789         final TextUtils.TruncateAt newEllipsizeValue = TextUtils.TruncateAt.END;
    790         mActivityTestRule.runOnUiThread(new Runnable() {
    791             @Override
    792             public void run() {
    793                 view.setEllipsize(newEllipsizeValue);
    794             }
    795         });
    796         mInstrumentation.waitForIdleSync();
    797         assertEquals(newEllipsizeValue, view.getEllipsize());
    798         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
    799                 ((AutoSizeableTextView) view).getAutoSizeTextType());
    800         assertEquals(-1, ((AutoSizeableTextView) view).getAutoSizeMinTextSize());
    801         assertEquals(-1, ((AutoSizeableTextView) view).getAutoSizeMaxTextSize());
    802         assertEquals(-1, ((AutoSizeableTextView) view).getAutoSizeStepGranularity());
    803         assertEquals(0,
    804                 ((AutoSizeableTextView) view).getAutoSizeTextAvailableSizes().length);
    805 
    806         mActivityTestRule.runOnUiThread(new Runnable() {
    807             @Override
    808             public void run() {
    809                 ((AutoSizeableTextView) view).setAutoSizeTextTypeWithDefaults(
    810                         TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
    811             }
    812         });
    813         mInstrumentation.waitForIdleSync();
    814         assertEquals(newEllipsizeValue, view.getEllipsize());
    815         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
    816                 ((AutoSizeableTextView) view).getAutoSizeTextType());
    817         // The auto-size defaults have been used.
    818         assertNotEquals(-1, ((AutoSizeableTextView) view).getAutoSizeMinTextSize());
    819         assertNotEquals(-1, ((AutoSizeableTextView) view).getAutoSizeMaxTextSize());
    820         assertNotEquals(-1, ((AutoSizeableTextView) view).getAutoSizeStepGranularity());
    821         assertNotEquals(0,
    822                 ((AutoSizeableTextView) view).getAutoSizeTextAvailableSizes().length);
    823     }
    824 
    825     @Test
    826     @MediumTest
    827     public void testAutoSizeUniform_obtainStyledAttributesUsingPredefinedSizes() {
    828         DisplayMetrics m = mActivity.getResources().getDisplayMetrics();
    829         final T autoSizeViewUniform = mActivity.findViewById(
    830                 R.id.view_autosize_uniform_predef_sizes);
    831 
    832         // In arrays.xml predefined the step sizes as: 5px, 11dip, 19sp, 29pt, 43mm and 53in.
    833         // TypedValue can not use the math library and instead rounds the value by adding
    834         // 0.5f when obtaining styled attributes. Check TypedValue#complexToDimensionPixelSize(...)
    835         int[] expectedSizesInPx = new int[] {
    836                 Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 5f, m)),
    837                 Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 11f, m)),
    838                 Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 19f, m)),
    839                 Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, 29f, m)),
    840                 Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 43f, m)),
    841                 Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_IN, 53f, m))};
    842 
    843         boolean containsValueFromExpectedSizes = false;
    844         final int textSize = (int) autoSizeViewUniform.getTextSize();
    845         for (int i = 0; i < expectedSizesInPx.length; i++) {
    846             if (expectedSizesInPx[i] == textSize) {
    847                 containsValueFromExpectedSizes = true;
    848                 break;
    849             }
    850         }
    851         assertTrue(containsValueFromExpectedSizes);
    852     }
    853 
    854     @Test
    855     @MediumTest
    856     public void testAutoSizeUniform_obtainStyledAttributesPredefinedSizesFiltering() {
    857         T autoSizeViewUniform = mActivity.findViewById(
    858                 R.id.view_autosize_uniform_predef_sizes_redundant_values);
    859 
    860         // In arrays.xml predefined the step sizes as: 40px, 10px, 10px, 10px, 0dp.
    861         final int[] expectedSizes = new int[] {10, 40};
    862         assertArrayEquals(expectedSizes,
    863                 ((AutoSizeableTextView) autoSizeViewUniform).getAutoSizeTextAvailableSizes());
    864     }
    865 
    866     @Test
    867     @MediumTest
    868     public void testAutoSizeUniform_predefinedSizesFilteringAndSorting() throws Throwable {
    869         final T view = mActivity.findViewById(R.id.view_text);
    870         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
    871                 ((AutoSizeableTextView) view).getAutoSizeTextType());
    872 
    873         final int[] predefinedSizes = new int[] {400, 0, 10, 40, 10, 10, 0, 0};
    874         mActivityTestRule.runOnUiThread(new Runnable() {
    875             @Override
    876             public void run() {
    877                 ((AutoSizeableTextView) view).setAutoSizeTextTypeUniformWithPresetSizes(
    878                         predefinedSizes, TypedValue.COMPLEX_UNIT_PX);
    879             }
    880         });
    881         mInstrumentation.waitForIdleSync();
    882         assertArrayEquals(new int[] {10, 40, 400},
    883                 ((AutoSizeableTextView) view).getAutoSizeTextAvailableSizes());
    884     }
    885 
    886     @Test(expected = NullPointerException.class)
    887     @SmallTest
    888     public void testAutoSizeUniform_predefinedSizesNullArray() throws Throwable {
    889         final T view = mActivity.findViewById(R.id.view_text);
    890         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
    891                 ((AutoSizeableTextView) view).getAutoSizeTextType());
    892 
    893         final int[] predefinedSizes = null;
    894         mActivityTestRule.runOnUiThread(new Runnable() {
    895             @Override
    896             public void run() {
    897                 ((AutoSizeableTextView) view).setAutoSizeTextTypeUniformWithPresetSizes(
    898                         predefinedSizes, TypedValue.COMPLEX_UNIT_PX);
    899             }
    900         });
    901         mInstrumentation.waitForIdleSync();
    902     }
    903 
    904     @Test
    905     @MediumTest
    906     public void testAutoSizeUniform_predefinedSizesEmptyArray() throws Throwable {
    907         final T view = mActivity.findViewById(R.id.view_text);
    908         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
    909                 ((AutoSizeableTextView) view).getAutoSizeTextType());
    910 
    911         mActivityTestRule.runOnUiThread(new Runnable() {
    912             @Override
    913             public void run() {
    914                 ((AutoSizeableTextView) view).setAutoSizeTextTypeWithDefaults(
    915                         TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
    916             }
    917         });
    918         mInstrumentation.waitForIdleSync();
    919 
    920         final int[] defaultSizes = ((AutoSizeableTextView) view).getAutoSizeTextAvailableSizes();
    921         assertNotNull(defaultSizes);
    922         assertTrue(defaultSizes.length > 0);
    923 
    924         final int[] predefinedSizes = new int[0];
    925         mActivityTestRule.runOnUiThread(new Runnable() {
    926             @Override
    927             public void run() {
    928                 ((AutoSizeableTextView) view).setAutoSizeTextTypeUniformWithPresetSizes(
    929                         predefinedSizes, TypedValue.COMPLEX_UNIT_PX);
    930             }
    931         });
    932         mInstrumentation.waitForIdleSync();
    933 
    934         final int[] newSizes = ((AutoSizeableTextView) view).getAutoSizeTextAvailableSizes();
    935         assertNotNull(defaultSizes);
    936         assertArrayEquals(defaultSizes, newSizes);
    937     }
    938 
    939     @Test
    940     @MediumTest
    941     public void testAutoSizeUniform_buildsSizes() throws Throwable {
    942         final T autoSizeViewUniform = mActivity.findViewById(R.id.view_autosize_uniform);
    943 
    944         // Verify that the interval limits are both included.
    945         mActivityTestRule.runOnUiThread(new Runnable() {
    946             @Override
    947             public void run() {
    948                 ((AutoSizeableTextView) autoSizeViewUniform)
    949                         .setAutoSizeTextTypeUniformWithConfiguration(10, 20, 2,
    950                                 TypedValue.COMPLEX_UNIT_PX);
    951             }
    952         });
    953         mInstrumentation.waitForIdleSync();
    954         assertArrayEquals(
    955                 new int[] {10, 12, 14, 16, 18, 20},
    956                 ((AutoSizeableTextView) autoSizeViewUniform).getAutoSizeTextAvailableSizes());
    957 
    958         mActivityTestRule.runOnUiThread(new Runnable() {
    959             @Override
    960             public void run() {
    961                 ((AutoSizeableTextView) autoSizeViewUniform)
    962                         .setAutoSizeTextTypeUniformWithConfiguration(
    963                                 ((AutoSizeableTextView) autoSizeViewUniform)
    964                                         .getAutoSizeMinTextSize(),
    965                                 19,
    966                                 ((AutoSizeableTextView) autoSizeViewUniform)
    967                                         .getAutoSizeStepGranularity(),
    968                                 TypedValue.COMPLEX_UNIT_PX);
    969             }
    970         });
    971         mInstrumentation.waitForIdleSync();
    972         assertArrayEquals(
    973                 new int[] {10, 12, 14, 16, 18},
    974                 ((AutoSizeableTextView) autoSizeViewUniform).getAutoSizeTextAvailableSizes());
    975 
    976         mActivityTestRule.runOnUiThread(new Runnable() {
    977             @Override
    978             public void run() {
    979                 ((AutoSizeableTextView) autoSizeViewUniform)
    980                         .setAutoSizeTextTypeUniformWithConfiguration(
    981                                 ((AutoSizeableTextView) autoSizeViewUniform)
    982                                         .getAutoSizeMinTextSize(),
    983                                 21,
    984                                 ((AutoSizeableTextView) autoSizeViewUniform)
    985                                         .getAutoSizeStepGranularity(),
    986                                 TypedValue.COMPLEX_UNIT_PX);
    987             }
    988         });
    989         mInstrumentation.waitForIdleSync();
    990         assertArrayEquals(
    991                 new int[] {10, 12, 14, 16, 18, 20},
    992                 ((AutoSizeableTextView) autoSizeViewUniform).getAutoSizeTextAvailableSizes());
    993     }
    994 
    995     @Test
    996     @MediumTest
    997     public void testAutoSizeUniform_getSetAutoSizeTextDefaults() {
    998         final T autoSizeView = getNewAutoSizeViewInstance();
    999         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
   1000                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1001         // Min/Max/Granularity values for auto-sizing are 0 because they are not used.
   1002         assertEquals(-1, ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize());
   1003         assertEquals(-1, ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize());
   1004         assertEquals(-1,
   1005                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
   1006 
   1007         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeWithDefaults(
   1008                 TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
   1009         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
   1010                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1011         // Min/Max default values for auto-sizing XY have been loaded.
   1012         final int minSize = ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize();
   1013         final int maxSize = ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize();
   1014         assertTrue(0 < minSize);
   1015         assertTrue(minSize < maxSize);
   1016         assertNotEquals(0,
   1017                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
   1018 
   1019         ((AutoSizeableTextView) autoSizeView)
   1020                 .setAutoSizeTextTypeWithDefaults(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE);
   1021         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
   1022                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1023         // Min/Max values for auto-sizing XY have been cleared.
   1024         assertEquals(-1, ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize());
   1025         assertEquals(-1, ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize());
   1026         assertEquals(-1,
   1027                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
   1028     }
   1029 
   1030     @Test
   1031     @MediumTest
   1032     public void testAutoSizeUniform_getSetAutoSizeStepGranularity() {
   1033         final T autoSizeView = getNewAutoSizeViewInstance();
   1034         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE,
   1035                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1036         final int initialValue = -1;
   1037         assertEquals(initialValue,
   1038                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
   1039 
   1040         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeWithDefaults(
   1041                 TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
   1042         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
   1043                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1044         final int defaultValue = 1; // 1px.
   1045         // If the auto-size type is AUTO_SIZE_TEXT_TYPE_UNIFORM then it means autoSizeView went
   1046         // through the auto-size setup and given that 0 is an invalid value it changed it to the
   1047         // default.
   1048         assertEquals(defaultValue,
   1049                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
   1050 
   1051         final int newValue = 33;
   1052         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1053                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize(),
   1054                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize(),
   1055                 newValue,
   1056                 TypedValue.COMPLEX_UNIT_PX);
   1057         assertEquals(newValue, ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity());
   1058     }
   1059 
   1060     @Test
   1061     @MediumTest
   1062     public void testAutoSizeUniform_getSetAutoSizeMinTextSize() {
   1063         final T autoSizeView = getNewAutoSizeViewInstance();
   1064         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeWithDefaults(
   1065                 TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
   1066         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
   1067                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1068         final int minSize = ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize();
   1069         assertNotEquals(0, minSize);
   1070         final int maxSize = ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize();
   1071         assertNotEquals(0, maxSize);
   1072 
   1073         // This is just a test check to verify the next assertions. If this fails it is a problem
   1074         // of this test setup (we need at least 2 units).
   1075         assertTrue((maxSize - minSize) > 1);
   1076         final int newMinSize = maxSize - 1;
   1077         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1078                 newMinSize,
   1079                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize(),
   1080                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity(),
   1081                 TypedValue.COMPLEX_UNIT_PX);
   1082 
   1083         assertEquals(newMinSize, ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize());
   1084         // Max size has not changed.
   1085         assertEquals(maxSize, ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize());
   1086 
   1087         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1088                 newMinSize,
   1089                 newMinSize + 10,
   1090                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity(),
   1091                 TypedValue.COMPLEX_UNIT_SP);
   1092 
   1093         // It does not matter which unit has been used to set the min size, the getter always
   1094         // returns it in pixels.
   1095         assertEquals(Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
   1096                 newMinSize, mActivity.getResources().getDisplayMetrics())),
   1097                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize());
   1098     }
   1099 
   1100     @Test(expected = IllegalArgumentException.class)
   1101     @SmallTest
   1102     public void testAutoSizeUniform_throwsException_whenMaxLessThanMin() {
   1103         final T autoSizeView = getNewAutoSizeViewInstance();
   1104         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1105                 10, 9, 1, TypedValue.COMPLEX_UNIT_SP);
   1106     }
   1107 
   1108     @Test(expected = IllegalArgumentException.class)
   1109     @SmallTest
   1110     public void testAutoSizeUniform_throwsException_minLessThanZero() {
   1111         final T autoSizeView = getNewAutoSizeViewInstance();
   1112         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1113                 -1, 9, 1, TypedValue.COMPLEX_UNIT_SP);
   1114     }
   1115 
   1116     @Test(expected = IllegalArgumentException.class)
   1117     @SmallTest
   1118     public void testAutoSizeUniform_throwsException_maxLessThanZero() {
   1119         final T autoSizeView = getNewAutoSizeViewInstance();
   1120         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1121                 10, -1, 1, TypedValue.COMPLEX_UNIT_SP);
   1122     }
   1123 
   1124     @Test(expected = IllegalArgumentException.class)
   1125     @SmallTest
   1126     public void testAutoSizeUniform_throwsException_granularityLessThanZero() {
   1127         final T autoSizeView = getNewAutoSizeViewInstance();
   1128         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1129                 10, 20, -1, TypedValue.COMPLEX_UNIT_SP);
   1130     }
   1131 
   1132     @Test
   1133     @MediumTest
   1134     public void testAutoSizeUniform_getSetAutoSizeMaxTextSize() {
   1135         final T autoSizeView = getNewAutoSizeViewInstance();
   1136         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeWithDefaults(
   1137                 TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
   1138         assertEquals(TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM,
   1139                 ((AutoSizeableTextView) autoSizeView).getAutoSizeTextType());
   1140         final int minSize = ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize();
   1141         assertNotEquals(0, minSize);
   1142         final int maxSize = ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize();
   1143         assertNotEquals(0, maxSize);
   1144 
   1145         final int newMaxSize = maxSize + 11;
   1146         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1147                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize(),
   1148                 newMaxSize,
   1149                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity(),
   1150                 TypedValue.COMPLEX_UNIT_PX);
   1151 
   1152         assertEquals(newMaxSize, ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize());
   1153         // Min size has not changed.
   1154         assertEquals(minSize, ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize());
   1155         ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeUniformWithConfiguration(
   1156                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMinTextSize(),
   1157                 newMaxSize,
   1158                 ((AutoSizeableTextView) autoSizeView).getAutoSizeStepGranularity(),
   1159                 TypedValue.COMPLEX_UNIT_SP);
   1160         // It does not matter which unit has been used to set the max size, the getter always
   1161         // returns it in pixels.
   1162         assertEquals(Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
   1163                 newMaxSize, mActivity.getResources().getDisplayMetrics())),
   1164                 ((AutoSizeableTextView) autoSizeView).getAutoSizeMaxTextSize());
   1165     }
   1166 
   1167     @Test
   1168     @MediumTest
   1169     public void testAutoSizeCallers_setTextSizeChangesSizeWhenAutoSizeDisabled() throws Throwable {
   1170         final T autoSizeView = prepareAndRetrieveAutoSizeTestData(R.id.view_autosize_uniform,
   1171                 false);
   1172         // Disable auto-size.
   1173         mActivityTestRule.runOnUiThread(new Runnable() {
   1174             @Override
   1175             public void run() {
   1176                 ((AutoSizeableTextView) autoSizeView).setAutoSizeTextTypeWithDefaults(
   1177                         TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE);
   1178             }
   1179         });
   1180         mInstrumentation.waitForIdleSync();
   1181 
   1182         final float newTextSizeInPx = autoSizeView.getTextSize() + 10f;
   1183         mActivityTestRule.runOnUiThread(new Runnable() {
   1184             @Override
   1185             public void run() {
   1186                 autoSizeView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newTextSizeInPx);
   1187             }
   1188         });
   1189         mInstrumentation.waitForIdleSync();
   1190 
   1191         assertEquals(newTextSizeInPx, autoSizeView.getTextSize(), 0f);
   1192     }
   1193 
   1194     /**
   1195      * Some View attributes require non-fixed width and/or layout height. This function removes
   1196      * all other existing views from the layout leaving only one auto-size TextView (for exercising
   1197      * the auto-size behavior) which has been set up to suit the test needs.
   1198      *
   1199      * @param viewId The id of the view to prepare.
   1200      * @param shouldWrapLayoutContent Specifies if the layout params should wrap content
   1201      *
   1202      * @return a View configured for auto size tests.
   1203      */
   1204     private T prepareAndRetrieveAutoSizeTestData(final @IdRes int viewId,
   1205             final boolean shouldWrapLayoutContent) throws Throwable {
   1206         mActivityTestRule.runOnUiThread(new Runnable() {
   1207             @Override
   1208             public void run() {
   1209                 LinearLayout ll = mActivity.findViewById(R.id.container);
   1210                 T targetedView = mActivity.findViewById(viewId);
   1211                 ll.removeAllViews();
   1212                 ll.addView(targetedView);
   1213             }
   1214         });
   1215         mInstrumentation.waitForIdleSync();
   1216 
   1217         final T view = mActivity.findViewById(viewId);
   1218         if (shouldWrapLayoutContent) {
   1219             // Do not force exact width or height.
   1220             final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
   1221                     LinearLayout.LayoutParams.WRAP_CONTENT,
   1222                     LinearLayout.LayoutParams.WRAP_CONTENT);
   1223             mActivityTestRule.runOnUiThread(new Runnable() {
   1224                 @Override
   1225                 public void run() {
   1226                     view.setLayoutParams(layoutParams);
   1227                 }
   1228             });
   1229             mInstrumentation.waitForIdleSync();
   1230         }
   1231 
   1232         return view;
   1233     }
   1234 
   1235     /* Transformation method which duplicates text. */
   1236     private final class DoubleTextTransformationMethod implements TransformationMethod {
   1237         DoubleTextTransformationMethod() {
   1238             /* Nothing to do. */
   1239         }
   1240 
   1241         @Override
   1242         public CharSequence getTransformation(CharSequence source, View view) {
   1243             return new StringBuilder().append(source).append(source).toString();
   1244         }
   1245 
   1246         @Override
   1247         public void onFocusChanged(View view, CharSequence sourceText, boolean focused,
   1248                 int direction, Rect previouslyFocusedRect) {
   1249             /* Nothing to do. */
   1250         }
   1251     }
   1252 
   1253     // Returns a new instance of the auto-sizable view for mActivity.
   1254     protected abstract T getNewAutoSizeViewInstance();
   1255 }
   1256