Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2008 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 android.graphics.drawable.cts;
     18 
     19 import com.android.cts.stub.R;
     20 
     21 import dalvik.annotation.KnownFailure;
     22 import dalvik.annotation.TestLevel;
     23 import dalvik.annotation.TestTargetClass;
     24 import dalvik.annotation.TestTargetNew;
     25 import dalvik.annotation.TestTargets;
     26 import dalvik.annotation.ToBeFixed;
     27 
     28 import org.xmlpull.v1.XmlPullParser;
     29 import org.xmlpull.v1.XmlPullParserException;
     30 
     31 import android.content.res.Resources;
     32 import android.content.res.XmlResourceParser;
     33 import android.graphics.Bitmap;
     34 import android.graphics.BitmapFactory;
     35 import android.graphics.Canvas;
     36 import android.graphics.Color;
     37 import android.graphics.ColorFilter;
     38 import android.graphics.NinePatch;
     39 import android.graphics.Paint;
     40 import android.graphics.PixelFormat;
     41 import android.graphics.Rect;
     42 import android.graphics.Region;
     43 import android.graphics.Bitmap.Config;
     44 import android.graphics.drawable.NinePatchDrawable;
     45 import android.graphics.drawable.Drawable.ConstantState;
     46 import android.test.InstrumentationTestCase;
     47 import android.util.AttributeSet;
     48 import android.util.Xml;
     49 
     50 import java.io.IOException;
     51 
     52 @TestTargetClass(NinePatchDrawable.class)
     53 public class NinePatchDrawableTest extends InstrumentationTestCase {
     54     private static final int MIN_CHUNK_SIZE = 32;
     55 
     56     private NinePatchDrawable mNinePatchDrawable;
     57 
     58     private Resources mResources;
     59 
     60     @Override
     61     protected void setUp() throws Exception {
     62         super.setUp();
     63         mResources = getInstrumentation().getTargetContext().getResources();
     64         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_0);
     65     }
     66 
     67     @TestTargets({
     68         @TestTargetNew(
     69             level = TestLevel.COMPLETE,
     70             method = "NinePatchDrawable",
     71             args = {Bitmap.class, byte[].class, Rect.class, String.class}
     72         ),
     73         @TestTargetNew(
     74             level = TestLevel.COMPLETE,
     75             method = "NinePatchDrawable",
     76             args = {android.graphics.NinePatch.class}
     77         )
     78     })
     79     @SuppressWarnings("deprecation")
     80     public void testConstructors() {
     81         byte[] chunk = new byte[MIN_CHUNK_SIZE];
     82         chunk[MIN_CHUNK_SIZE - 1] = 1;
     83 
     84         Rect r = new Rect();
     85 
     86         Bitmap bmp = BitmapFactory.decodeResource(mResources, R.drawable.ninepatch_0);
     87         String name = mResources.getResourceName(R.drawable.ninepatch_0);
     88 
     89         new NinePatchDrawable(bmp, chunk, r, name);
     90 
     91         new NinePatchDrawable(new NinePatch(bmp, chunk, name));
     92 
     93         chunk = new byte[MIN_CHUNK_SIZE - 1];
     94         chunk[MIN_CHUNK_SIZE - 2] = 1;
     95         try {
     96             new NinePatchDrawable(bmp, chunk, r, name);
     97             fail("The constructor should check whether the chunk is illegal.");
     98         } catch (RuntimeException e) {
     99             // This exception is thrown by native method.
    100         }
    101     }
    102 
    103     @TestTargetNew(
    104         level = TestLevel.COMPLETE,
    105         method = "draw",
    106         args = {android.graphics.Canvas.class}
    107     )
    108     @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
    109             + "NinePatchDrawable#draw(Canvas) when param canvas is null")
    110     public void testDraw() {
    111         Bitmap bmp = Bitmap.createBitmap(9, 9, Config.ARGB_8888);
    112         Canvas c = new Canvas(bmp);
    113 
    114         int ocean = Color.rgb(0, 0xFF, 0x80);
    115 
    116         mNinePatchDrawable.setBounds(0, 0, 9, 9);
    117         mNinePatchDrawable.draw(c);
    118         assertColorFillRect(bmp, 0, 0, 4, 4, Color.RED);
    119         assertColorFillRect(bmp, 5, 0, 4, 4, Color.BLUE);
    120         assertColorFillRect(bmp, 0, 5, 4, 4, ocean);
    121         assertColorFillRect(bmp, 5, 5, 4, 4, Color.YELLOW);
    122         assertColorFillRect(bmp, 4, 0, 1, 9, Color.WHITE);
    123         assertColorFillRect(bmp, 0, 4, 9, 1, Color.WHITE);
    124 
    125         bmp.eraseColor(0xff000000);
    126 
    127         mNinePatchDrawable.setBounds(0, 0, 3, 3);
    128         mNinePatchDrawable.draw(c);
    129         assertColorFillRect(bmp, 0, 0, 1, 1, Color.RED);
    130         assertColorFillRect(bmp, 2, 0, 1, 1, Color.BLUE);
    131         assertColorFillRect(bmp, 0, 2, 1, 1, ocean);
    132         assertColorFillRect(bmp, 2, 2, 1, 1, Color.YELLOW);
    133         assertColorFillRect(bmp, 1, 0, 1, 3, Color.WHITE);
    134         assertColorFillRect(bmp, 0, 1, 3, 1, Color.WHITE);
    135 
    136         try {
    137             mNinePatchDrawable.draw(null);
    138             fail("The method should check whether the canvas is null.");
    139         } catch (NullPointerException e) {
    140             // expected
    141         }
    142     }
    143 
    144     @TestTargetNew(
    145         level = TestLevel.COMPLETE,
    146         method = "getChangingConfigurations",
    147         args = {}
    148     )
    149     public void testGetChangingConfigurations() {
    150         ConstantState constantState = mNinePatchDrawable.getConstantState();
    151 
    152         // default
    153         assertEquals(0, constantState.getChangingConfigurations());
    154         assertEquals(0, mNinePatchDrawable.getChangingConfigurations());
    155 
    156         // change the drawable's configuration does not affect the state's configuration
    157         mNinePatchDrawable.setChangingConfigurations(0xff);
    158         assertEquals(0xff, mNinePatchDrawable.getChangingConfigurations());
    159         assertEquals(0, constantState.getChangingConfigurations());
    160 
    161         // the state's configuration get refreshed
    162         constantState = mNinePatchDrawable.getConstantState();
    163         assertEquals(0xff,  constantState.getChangingConfigurations());
    164 
    165         // set a new configuration to drawable
    166         mNinePatchDrawable.setChangingConfigurations(0xff00);
    167         assertEquals(0xff,  constantState.getChangingConfigurations());
    168         assertEquals(0xffff,  mNinePatchDrawable.getChangingConfigurations());
    169     }
    170 
    171     @TestTargetNew(
    172         level = TestLevel.COMPLETE,
    173         method = "getPadding",
    174         args = {android.graphics.Rect.class}
    175     )
    176     @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
    177             + "NinePatchDrawable#getPadding(Rect) when param padding is null or "
    178             + "the insternal padding field is not set ")
    179     public void testGetPadding() {
    180         Rect r = new Rect();
    181         NinePatchDrawable npd = (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatch_0);
    182         assertTrue(npd.getPadding(r));
    183         // exact padding unknown due to possible density scaling
    184         assertEquals(0, r.left);
    185         assertEquals(0, r.top);
    186         assertTrue(r.right > 0);
    187         assertTrue(r.bottom > 0);
    188 
    189         npd = (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatch_1);
    190         assertTrue(npd.getPadding(r));
    191         assertTrue(r.left > 0);
    192         assertTrue(r.top > 0);
    193         assertTrue(r.right > 0);
    194         assertTrue(r.bottom > 0);
    195     }
    196 
    197     @TestTargetNew(
    198         level = TestLevel.COMPLETE,
    199         method = "setAlpha",
    200         args = {int.class}
    201     )
    202     public void testSetAlpha() {
    203         assertEquals(0xff, mNinePatchDrawable.getPaint().getAlpha());
    204 
    205         mNinePatchDrawable.setAlpha(0);
    206         assertEquals(0, mNinePatchDrawable.getPaint().getAlpha());
    207 
    208         mNinePatchDrawable.setAlpha(-1);
    209         assertEquals(0xff, mNinePatchDrawable.getPaint().getAlpha());
    210 
    211         mNinePatchDrawable.setAlpha(0xfffe);
    212         assertEquals(0xfe, mNinePatchDrawable.getPaint().getAlpha());
    213     }
    214 
    215     @TestTargetNew(
    216         level = TestLevel.COMPLETE,
    217         method = "setColorFilter",
    218         args = {android.graphics.ColorFilter.class}
    219     )
    220     public void testSetColorFilter() {
    221         assertNull(mNinePatchDrawable.getPaint().getColorFilter());
    222 
    223         MockColorFilter cf = new MockColorFilter();
    224         mNinePatchDrawable.setColorFilter(cf);
    225         assertSame(cf, mNinePatchDrawable.getPaint().getColorFilter());
    226 
    227         mNinePatchDrawable.setColorFilter(null);
    228         assertNull(mNinePatchDrawable.getPaint().getColorFilter());
    229     }
    230 
    231     @TestTargetNew(
    232         level = TestLevel.COMPLETE,
    233         method = "setDither",
    234         args = {boolean.class}
    235     )
    236     public void testSetDither() {
    237         assertTrue(mNinePatchDrawable.getPaint().isDither());
    238 
    239         mNinePatchDrawable.setDither(false);
    240         assertFalse(mNinePatchDrawable.getPaint().isDither());
    241 
    242         mNinePatchDrawable.setDither(true);
    243         assertTrue(mNinePatchDrawable.getPaint().isDither());
    244     }
    245 
    246     @TestTargetNew(
    247         level = TestLevel.COMPLETE,
    248         method = "getPaint",
    249         args = {}
    250     )
    251     public void testGetPaint() {
    252         Paint paint = mNinePatchDrawable.getPaint();
    253         assertNotNull(paint);
    254 
    255         assertSame(paint, mNinePatchDrawable.getPaint());
    256     }
    257 
    258     @TestTargetNew(
    259         level = TestLevel.COMPLETE,
    260         method = "getIntrinsicWidth",
    261         args = {}
    262     )
    263     public void testGetIntrinsicWidth() {
    264         Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
    265         assertEquals(bmp.getWidth(), mNinePatchDrawable.getIntrinsicWidth());
    266         assertEquals(5, mNinePatchDrawable.getIntrinsicWidth());
    267 
    268         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
    269         bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
    270         assertEquals(bmp.getWidth(), mNinePatchDrawable.getIntrinsicWidth());
    271         assertEquals(9, mNinePatchDrawable.getIntrinsicWidth());
    272     }
    273 
    274     @TestTargetNew(
    275         level = TestLevel.COMPLETE,
    276         method = "getMinimumWidth",
    277         args = {}
    278     )
    279     public void testGetMinimumWidth() {
    280         Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
    281         assertEquals(bmp.getWidth(), mNinePatchDrawable.getMinimumWidth());
    282         assertEquals(5, mNinePatchDrawable.getMinimumWidth());
    283 
    284         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
    285         bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
    286         assertEquals(bmp.getWidth(), mNinePatchDrawable.getMinimumWidth());
    287         assertEquals(9, mNinePatchDrawable.getMinimumWidth());
    288     }
    289 
    290     @TestTargetNew(
    291         level = TestLevel.COMPLETE,
    292         method = "getIntrinsicHeight",
    293         args = {}
    294     )
    295     public void testGetIntrinsicHeight() {
    296         Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
    297         assertEquals(bmp.getHeight(), mNinePatchDrawable.getIntrinsicHeight());
    298         assertEquals(5, mNinePatchDrawable.getIntrinsicHeight());
    299 
    300         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
    301         bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
    302         assertEquals(bmp.getHeight(), mNinePatchDrawable.getIntrinsicHeight());
    303         assertEquals(9, mNinePatchDrawable.getIntrinsicHeight());
    304     }
    305 
    306     @TestTargetNew(
    307         level = TestLevel.COMPLETE,
    308         method = "getMinimumHeight",
    309         args = {}
    310     )
    311     public void testGetMinimumHeight() {
    312         Bitmap bmp = getBitmapUnscaled(R.drawable.ninepatch_0);
    313         assertEquals(bmp.getHeight(), mNinePatchDrawable.getMinimumHeight());
    314         assertEquals(5, mNinePatchDrawable.getMinimumHeight());
    315 
    316         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
    317         bmp = getBitmapUnscaled(R.drawable.ninepatch_1);
    318         assertEquals(bmp.getHeight(), mNinePatchDrawable.getMinimumHeight());
    319         assertEquals(9, mNinePatchDrawable.getMinimumHeight());
    320     }
    321 
    322     @TestTargetNew(
    323         level = TestLevel.COMPLETE,
    324         method = "getOpacity",
    325         args = {}
    326     )
    327     @KnownFailure("Bug 2834281 - Bitmap#hasAlpha seems to return true for "
    328         + "images without alpha.")
    329     public void testGetOpacity() {
    330         assertEquals(PixelFormat.OPAQUE, mNinePatchDrawable.getOpacity());
    331 
    332         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
    333         assertEquals(PixelFormat.TRANSLUCENT, mNinePatchDrawable.getOpacity());
    334     }
    335 
    336     @TestTargetNew(
    337         level = TestLevel.COMPLETE,
    338         method = "getTransparentRegion",
    339         args = {}
    340     )
    341     public void testGetTransparentRegion() {
    342         // opaque image
    343         Region r = mNinePatchDrawable.getTransparentRegion();
    344         assertNull(r);
    345 
    346         mNinePatchDrawable.setBounds(0, 0, 7, 7);
    347         r = mNinePatchDrawable.getTransparentRegion();
    348         assertNull(r);
    349 
    350         // translucent image
    351         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
    352         r = mNinePatchDrawable.getTransparentRegion();
    353         assertNull(r);
    354 
    355         mNinePatchDrawable.setBounds(1, 1, 7, 7);
    356         r = mNinePatchDrawable.getTransparentRegion();
    357         assertNotNull(r);
    358         assertEquals(new Rect(1, 1, 7, 7), r.getBounds());
    359     }
    360 
    361     @TestTargetNew(
    362         level = TestLevel.COMPLETE,
    363         method = "getConstantState",
    364         args = {}
    365     )
    366     public void testGetConstantState() {
    367         assertNotNull(mNinePatchDrawable.getConstantState());
    368 
    369         ConstantState constantState = mNinePatchDrawable.getConstantState();
    370         // change the drawable's configuration does not affect the state's configuration
    371         mNinePatchDrawable.setChangingConfigurations(0xff);
    372         assertEquals(0, constantState.getChangingConfigurations());
    373         // the state's configuration refreshed when getConstantState is called.
    374         constantState = mNinePatchDrawable.getConstantState();
    375         assertEquals(0xff, constantState.getChangingConfigurations());
    376     }
    377 
    378     @TestTargetNew(
    379         level = TestLevel.COMPLETE,
    380         method = "inflate",
    381         args = {Resources.class, XmlPullParser.class, AttributeSet.class}
    382     )
    383     public void testInflate() throws XmlPullParserException, IOException {
    384         final int width = 80;
    385         final int height = 120;
    386         final int[] COLOR = new int[width * height];
    387         Bitmap bitmap = Bitmap.createBitmap(COLOR, width, height, Bitmap.Config.RGB_565);
    388         NinePatchDrawable ninePatchDrawable =
    389             new NinePatchDrawable(mResources, bitmap, new byte[1000], null, "TESTNAME");
    390 
    391         assertEquals(height, ninePatchDrawable.getIntrinsicHeight());
    392         assertEquals(width, ninePatchDrawable.getIntrinsicWidth());
    393         XmlResourceParser parser = mResources.getXml(R.drawable.ninepatchdrawable);
    394         int type;
    395         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
    396                 && type != XmlPullParser.START_TAG) {
    397         }
    398         AttributeSet attrs = Xml.asAttributeSet(parser);
    399         ninePatchDrawable.inflate(mResources, parser, attrs);
    400 
    401         assertTrue(ninePatchDrawable.getPaint().isDither());
    402         assertTrue(height != ninePatchDrawable.getIntrinsicHeight());
    403         assertTrue(width != ninePatchDrawable.getIntrinsicWidth());
    404     }
    405 
    406     @TestTargetNew(
    407         level = TestLevel.SUFFICIENT,
    408         method = "mutate",
    409         args = {}
    410     )
    411     @ToBeFixed(bug = "", explanation = "mutate() always throw NullPointerException.")
    412     public void testMutate() {
    413         NinePatchDrawable d1 =
    414             (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable);
    415         NinePatchDrawable d2 =
    416             (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable);
    417         NinePatchDrawable d3 =
    418             (NinePatchDrawable) mResources.getDrawable(R.drawable.ninepatchdrawable);
    419 
    420         // the state is not shared before mutate.
    421         d1.setDither(false);
    422         assertFalse(d1.getPaint().isDither());
    423         assertTrue(d2.getPaint().isDither());
    424         assertTrue(d3.getPaint().isDither());
    425 
    426         // cannot test if mutate worked, since state was not shared before
    427         d1.mutate();
    428     }
    429 
    430     private void assertColorFillRect(Bitmap bmp, int x, int y, int w, int h, int color) {
    431         for (int i = x; i < x + w; i++) {
    432             for (int j = y; j < y + h; j++) {
    433                 assertEquals(color, bmp.getPixel(i, j));
    434             }
    435         }
    436     }
    437 
    438     private NinePatchDrawable getNinePatchDrawable(int resId) {
    439         // jump through hoops to avoid scaling the tiny ninepatch, which would skew the results
    440         // depending on device density
    441         Bitmap bitmap = getBitmapUnscaled(resId);
    442         NinePatch np = new NinePatch(bitmap, bitmap.getNinePatchChunk(), null);
    443         return new NinePatchDrawable(mResources, np);
    444     }
    445 
    446     private Bitmap getBitmapUnscaled(int resId) {
    447         BitmapFactory.Options opts = new BitmapFactory.Options();
    448         opts.inDensity = opts.inTargetDensity = mResources.getDisplayMetrics().densityDpi;
    449         Bitmap bitmap = BitmapFactory.decodeResource(mResources, resId, opts);
    450         return bitmap;
    451     }
    452 
    453     private class MockColorFilter extends ColorFilter {
    454     }
    455 }
    456