/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.graphics.cts;

import com.android.cts.graphics.R;


import android.content.res.Resources;
import android.cts.util.WidgetTestUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.util.DisplayMetrics;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

public class BitmapTest extends AndroidTestCase {
    private Resources mRes;
    private Bitmap mBitmap;
    private BitmapFactory.Options mOptions;

    // small alpha values cause color values to be pre-multiplied down, losing accuracy
    private final int PREMUL_COLOR = Color.argb(2, 255, 254, 253);
    private final int PREMUL_ROUNDED_COLOR = Color.argb(2, 255, 255, 255);
    private final int PREMUL_STORED_COLOR = Color.argb(2, 2, 2, 2);

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        mRes = getContext().getResources();
        mOptions = new BitmapFactory.Options();
        mOptions.inScaled = false;
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
    }

    public void testCompress(){
        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.compress(CompressFormat.JPEG, 0, null);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        // abnormal case: out stream is null
        try{
            mBitmap.compress(CompressFormat.JPEG, 0, null);
            fail("shouldn't come to here");
        }catch(NullPointerException e){
        }

        // abnormal case: quality less than 0
        try{
            mBitmap.compress(CompressFormat.JPEG, -1, new ByteArrayOutputStream());
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // abnormal case: quality bigger than 100
        try{
            mBitmap.compress(CompressFormat.JPEG, 101, new ByteArrayOutputStream());
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //normal case
        assertTrue(mBitmap.compress(CompressFormat.JPEG, 50, new ByteArrayOutputStream()));
    }

    public void testCopy(){
        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.copy(Config.RGB_565, false);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
            // expected
        }

        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap = mBitmap.copy(Config.ARGB_8888, false);
        WidgetTestUtils.assertEquals(mBitmap, bitmap);
    }

    public void testCopyPixelsToBuffer(){
        final int pixSize = mBitmap.getRowBytes() * mBitmap.getHeight();
        final int tooSmall = pixSize / 2;

        // abnormal case: unsupported Buffer subclass
        try{
            mBitmap.copyPixelsToBuffer(CharBuffer.allocate(pixSize));
            fail("shouldn't come to here");
        }catch(RuntimeException e1){
        }

        // abnormal case: Buffer not large enough for pixels
        try{
            mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
            fail("shouldn't come to here");
        }catch(RuntimeException e2){
        }

        // normal case
        ByteBuffer byteBuf = ByteBuffer.allocate(pixSize);
        assertEquals(0, byteBuf.position());
        mBitmap.copyPixelsToBuffer(byteBuf);
        assertEquals(pixSize, byteBuf.position());

        // abnormal case: Buffer not large enough for pixels
        try{
            mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
            fail("shouldn't come to here");
        }catch(RuntimeException e3){
        }

        // normal case
        ShortBuffer shortBuf = ShortBuffer.allocate(pixSize);
        assertEquals(0, shortBuf.position());
        mBitmap.copyPixelsToBuffer(shortBuf);
        assertEquals(pixSize >> 1, shortBuf.position());

        // abnormal case: Buffer not large enough for pixels
        try{
            mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
            fail("shouldn't come to here");
        }catch(RuntimeException e4){
        }

        // normal case
        IntBuffer intBuf1 = IntBuffer.allocate(pixSize);
        assertEquals(0, intBuf1.position());
        mBitmap.copyPixelsToBuffer(intBuf1);
        assertEquals(pixSize >> 2, intBuf1.position());

        Bitmap bitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(),
                mBitmap.getConfig());
        intBuf1.position(0); // copyPixelsToBuffer adjusted the position, so rewind to start
        bitmap.copyPixelsFromBuffer(intBuf1);
        IntBuffer intBuf2 = IntBuffer.allocate(pixSize);
        bitmap.copyPixelsToBuffer(intBuf2);

        assertEquals(pixSize >> 2, intBuf2.position());
        assertEquals(intBuf1.position(), intBuf2.position());
        int size = intBuf1.position();
        intBuf1.position(0);
        intBuf2.position(0);
        for (int i = 0; i < size; i++) {
            assertEquals("mismatching pixels at position " + i, intBuf1.get(), intBuf2.get());
        }
    }

    public void testCreateBitmap1(){
        int[] colors = createColors(100);
        Bitmap bitmap = Bitmap.createBitmap(colors, 10, 10, Config.RGB_565);
        Bitmap ret = Bitmap.createBitmap(bitmap);
        assertNotNull(ret);
        assertEquals(10, ret.getWidth());
        assertEquals(10, ret.getHeight());
        assertEquals(Config.RGB_565, ret.getConfig());
    }

    public void testCreateBitmap2(){
        //abnormal case: Illegal Argument
        try{
            Bitmap.createBitmap(mBitmap, -100, 50, 50, 200);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // special case: output bitmap is equal to the input bitmap
        mBitmap = Bitmap.createBitmap(new int[100 * 100], 100, 100, Config.ARGB_8888);
        Bitmap ret = Bitmap.createBitmap(mBitmap, 0, 0, 100, 100);
        assertNotNull(ret);
        assertTrue(mBitmap.equals(ret));

        //normal case
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        ret = Bitmap.createBitmap(mBitmap, 10, 10, 50, 50);
        assertNotNull(ret);
        assertFalse(mBitmap.equals(ret));
    }

    public void testCreateBitmap3(){
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);

        //abnormal case: x and/or y less than 0
        try{
            Bitmap.createBitmap(mBitmap, -1, -1, 10, 10, null, false);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: width and/or height less than 0
        try{
            Bitmap.createBitmap(mBitmap, 1, 1, -10, -10, null, false);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: (x + width) bigger than source bitmap's width
        try{
            Bitmap.createBitmap(mBitmap, 10, 10, 95, 50, null, false);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: (y + height) bigger than source bitmap's height
        try{
            Bitmap.createBitmap(mBitmap, 10, 10, 50, 95, null, false);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // special case: output bitmap is equal to the input bitmap
        mBitmap = Bitmap.createBitmap(new int[100 * 100], 100, 100, Config.ARGB_8888);
        Bitmap ret = Bitmap.createBitmap(mBitmap, 0, 0, 100, 100, null, false);
        assertNotNull(ret);
        assertTrue(mBitmap.equals(ret));

        // normal case
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        ret = Bitmap.createBitmap(mBitmap, 10, 10, 50, 50, new Matrix(), true);
        assertNotNull(ret);
        assertFalse(mBitmap.equals(ret));
    }

    public void testCreateBitmap4(){
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        assertNotNull(ret);
        assertEquals(100, ret.getWidth());
        assertEquals(200, ret.getHeight());
        assertEquals(Config.RGB_565, ret.getConfig());
    }

    public void testCreateBitmap6(){
        int[] colors = createColors(100);

        //abnormal case: width and/or height less than 0
        try{
            Bitmap.createBitmap(colors, 0, 100, -1, 100, Config.RGB_565);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: stride less than width and bigger than -width
        try{
            Bitmap.createBitmap(colors, 10, 10, 100, 100, Config.RGB_565);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: offset less than 0
        try{
            Bitmap.createBitmap(colors, -10, 100, 100, 100, Config.RGB_565);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        //abnormal case: (offset + width) bigger than colors' length
        try{
            Bitmap.createBitmap(colors, 10, 100, 100, 100, Config.RGB_565);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        //abnormal case: (lastScanline + width) bigger than colors' length
        try{
            Bitmap.createBitmap(colors, 10, 100, 50, 100, Config.RGB_565);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        // normal case
        Bitmap ret = Bitmap.createBitmap(colors, 5, 10, 10, 5, Config.RGB_565);
        assertNotNull(ret);
        assertEquals(10, ret.getWidth());
        assertEquals(5, ret.getHeight());
        assertEquals(Config.RGB_565, ret.getConfig());
    }

    public void testCreateScaledBitmap(){
        mBitmap = Bitmap.createBitmap(100, 200, Config.RGB_565);
        Bitmap ret = Bitmap.createScaledBitmap(mBitmap, 50, 100, false);
        assertNotNull(ret);
        assertEquals(50, ret.getWidth());
        assertEquals(100, ret.getHeight());
    }

    public void testDescribeContents(){
        assertEquals(0, mBitmap.describeContents());
    }

    public void testEraseColor(){
        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.eraseColor(0);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        //abnormal case: bitmap is immutable
        try{
            mBitmap.eraseColor(0);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        // normal case
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        mBitmap.eraseColor(0xffff0000);
        assertEquals(0xffff0000, mBitmap.getPixel(10, 10));
        assertEquals(0xffff0000, mBitmap.getPixel(50, 50));
    }

    public void testExtractAlpha1(){
        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.extractAlpha();
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        // normal case
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        Bitmap ret = mBitmap.extractAlpha();
        assertNotNull(ret);
        int color = ret.getPixel(10, 20);
        assertEquals(0x00, Color.alpha(color));
    }

    public void testExtractAlpha2(){
        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.extractAlpha(new Paint(), new int[]{0, 1});
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        // normal case
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        Bitmap ret = mBitmap.extractAlpha(new Paint(), new int[]{0, 1});
        assertNotNull(ret);
        int color = ret.getPixel(10, 20);
        assertEquals(0x00, Color.alpha(color));
    }

    public void testGetAllocationByteCount() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ALPHA_8);
        int alloc = mBitmap.getAllocationByteCount();
        assertEquals(mBitmap.getByteCount(), alloc);

        // reconfigure same size
        mBitmap.reconfigure(50, 100, Bitmap.Config.ARGB_8888);
        assertEquals(mBitmap.getByteCount(), alloc);
        assertEquals(mBitmap.getAllocationByteCount(), alloc);

        // reconfigure different size
        mBitmap.reconfigure(10, 10, Bitmap.Config.ALPHA_8);
        assertEquals(mBitmap.getByteCount(), 100);
        assertEquals(mBitmap.getAllocationByteCount(), alloc);
    }

    public void testGetConfig(){
        Bitmap bm0 = Bitmap.createBitmap(100, 200, Bitmap.Config.ALPHA_8);
        Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        Bitmap bm3 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444);

        assertEquals(Bitmap.Config.ALPHA_8, bm0.getConfig());
        assertEquals(Bitmap.Config.ARGB_8888, bm1.getConfig());
        assertEquals(Bitmap.Config.RGB_565, bm2.getConfig());
        // Attempting to create a 4444 bitmap actually creates an 8888 bitmap.
        assertEquals(Bitmap.Config.ARGB_8888, bm3.getConfig());
    }

    public void testGetHeight(){
        assertEquals(31, mBitmap.getHeight());
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        assertEquals(200, mBitmap.getHeight());
    }

    public void testGetNinePatchChunk(){
        assertNull(mBitmap.getNinePatchChunk());
    }

    public void testGetPixel(){
        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.getPixel(10, 16);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        //abnormal case: x bigger than the source bitmap's width
        try{
            mBitmap.getPixel(200, 16);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: y bigger than the source bitmap's height
        try{
            mBitmap.getPixel(10, 300);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // normal case 565
        mBitmap.setPixel(10, 16, 0xFF << 24);
        assertEquals(0xFF << 24, mBitmap.getPixel(10, 16));

        // normal case A_8
        mBitmap = Bitmap.createBitmap(10, 10, Config.ALPHA_8);
        mBitmap.setPixel(5, 5, 0xFFFFFFFF);
        assertEquals(0xFFFFFFFF, mBitmap.getPixel(5, 5));
        mBitmap.setPixel(5, 5, 0xA8A8A8A8);
        assertEquals(0xA8A8A8A8, mBitmap.getPixel(5, 5));
        mBitmap.setPixel(5, 5, 0x00000000);
        assertEquals(0x00000000, mBitmap.getPixel(5, 5));

        // test reconstructing color channels
        mBitmap.setPixel(5, 5, 0x1F000000);
        assertEquals(0x1F1F1F1F, mBitmap.getPixel(5, 5));
    }

    public void testGetRowBytes(){
        Bitmap bm0 = Bitmap.createBitmap(100, 200, Bitmap.Config.ALPHA_8);
        Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        Bitmap bm3 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444);

        assertEquals(100, bm0.getRowBytes());
        assertEquals(400, bm1.getRowBytes());
        assertEquals(200, bm2.getRowBytes());
        // Attempting to create a 4444 bitmap actually creates an 8888 bitmap.
        assertEquals(400, bm3.getRowBytes());
    }

    public void testGetWidth(){
        assertEquals(31, mBitmap.getWidth());
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        assertEquals(100, mBitmap.getWidth());
    }

    public void testHasAlpha(){
        assertFalse(mBitmap.hasAlpha());
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        assertTrue(mBitmap.hasAlpha());
    }

    public void testIsMutable(){
        assertFalse(mBitmap.isMutable());
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        assertTrue(mBitmap.isMutable());
    }

    public void testIsRecycled(){
        assertFalse(mBitmap.isRecycled());
        mBitmap.recycle();
        assertTrue(mBitmap.isRecycled());
    }

    public void testReconfigure() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        int alloc = mBitmap.getAllocationByteCount();

        // test shrinking
        mBitmap.reconfigure(50, 100, Bitmap.Config.ALPHA_8);
        assertEquals(mBitmap.getAllocationByteCount(), alloc);
        assertEquals(mBitmap.getByteCount() * 8, alloc);

        // test expanding
        try {
            mBitmap.reconfigure(101, 201, Bitmap.Config.ARGB_8888);
            fail("shouldn't come to here");
        } catch (IllegalArgumentException e) {
        }

        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        try {
            mBitmap.reconfigure(1, 1, Bitmap.Config.ALPHA_8);
            fail("shouldn't come to here");
        } catch (IllegalStateException e) {
        }
    }

    // Used by testAlphaAndPremul. FIXME: Should we also test Index8? That would require decoding a
    // Bitmap, since one cannot be created directly. It will also have a Config of null, since it
    // has no Java equivalent.
    private static Config[] CONFIGS = new Config[] { Config.ALPHA_8, Config.ARGB_4444,
            Config.ARGB_8888, Config.RGB_565 };

    // test that reconfigure, setHasAlpha, and setPremultiplied behave as expected with
    // respect to alpha and premultiplied.
    public void testAlphaAndPremul() {
        boolean falseTrue[] = new boolean[] { false, true };
        for (Config fromConfig : CONFIGS) {
            for (Config toConfig : CONFIGS) {
                for (boolean hasAlpha : falseTrue) {
                    for (boolean isPremul : falseTrue) {
                        Bitmap bitmap = Bitmap.createBitmap(10, 10, fromConfig);

                        // 4444 is deprecated, and will convert to 8888. No need to
                        // attempt a reconfigure, which will be tested when fromConfig
                        // is 8888.
                        if (fromConfig == Config.ARGB_4444) {
                            assertEquals(bitmap.getConfig(), Config.ARGB_8888);
                            break;
                        }

                        bitmap.setHasAlpha(hasAlpha);
                        bitmap.setPremultiplied(isPremul);

                        checkAlphaAndPremul(bitmap, hasAlpha, isPremul, false);

                        // reconfigure to a smaller size so the function will still succeed when
                        // going to a Config that requires more bits.
                        bitmap.reconfigure(1, 1, toConfig);
                        if (toConfig == Config.ARGB_4444) {
                            assertEquals(bitmap.getConfig(), Config.ARGB_8888);
                        } else {
                            assertEquals(bitmap.getConfig(), toConfig);
                        }

                        // Check that the alpha and premultiplied state has not changed (unless
                        // we expected it to).
                        checkAlphaAndPremul(bitmap, hasAlpha, isPremul, fromConfig == Config.RGB_565);
                    }
                }
            }
        }
    }

    /**
     *  Assert that bitmap returns the appropriate values for hasAlpha() and isPremultiplied().
     *  @param bitmap Bitmap to check.
     *  @param expectedAlpha Expected return value from bitmap.hasAlpha(). Note that this is based
     *          on what was set, but may be different from the actual return value depending on the
     *          Config and convertedFrom565.
     *  @param expectedPremul Expected return value from bitmap.isPremultiplied(). Similar to
     *          expectedAlpha, this is based on what was set, but may be different from the actual
     *          return value depending on the Config.
     *  @param convertedFrom565 Whether bitmap was converted to its current Config by being
     *          reconfigured from RGB_565. If true, and bitmap is now a Config that supports alpha,
     *          hasAlpha() is expected to be true even if expectedAlpha is false.
     */
    private void checkAlphaAndPremul(Bitmap bitmap, boolean expectedAlpha, boolean expectedPremul,
            boolean convertedFrom565) {
        switch (bitmap.getConfig()) {
            case ARGB_4444:
                // This shouldn't happen, since we don't allow creating or converting
                // to 4444.
                assertFalse(true);
                break;
            case RGB_565:
                assertFalse(bitmap.hasAlpha());
                assertFalse(bitmap.isPremultiplied());
                break;
            case ALPHA_8:
                // ALPHA_8 behaves mostly the same as 8888, except for premultiplied. Fall through.
            case ARGB_8888:
                // Since 565 is necessarily opaque, we revert to hasAlpha when switching to a type
                // that can have alpha.
                if (convertedFrom565) {
                    assertTrue(bitmap.hasAlpha());
                } else {
                    assertEquals(bitmap.hasAlpha(), expectedAlpha);
                }

                if (bitmap.hasAlpha()) {
                    // ALPHA_8's premultiplied status is undefined.
                    if (bitmap.getConfig() != Config.ALPHA_8) {
                        assertEquals(bitmap.isPremultiplied(), expectedPremul);
                    }
                } else {
                    // Opaque bitmap is never considered premultiplied.
                    assertFalse(bitmap.isPremultiplied());
                }
                break;
        }
    }

    public void testSetConfig() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        int alloc = mBitmap.getAllocationByteCount();

        // test shrinking
        mBitmap.setConfig(Bitmap.Config.ALPHA_8);
        assertEquals(mBitmap.getAllocationByteCount(), alloc);
        assertEquals(mBitmap.getByteCount() * 2, alloc);

        // test expanding
        try {
            mBitmap.setConfig(Bitmap.Config.ARGB_8888);
            fail("shouldn't come to here");
        } catch (IllegalArgumentException e) {
        }

        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        try {
            mBitmap.setConfig(Bitmap.Config.ALPHA_8);
            fail("shouldn't come to here");
        } catch (IllegalStateException e) {
        }
    }

    public void testSetHeight() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        int alloc = mBitmap.getAllocationByteCount();

        // test shrinking
        mBitmap.setHeight(100);
        assertEquals(mBitmap.getAllocationByteCount(), alloc);
        assertEquals(mBitmap.getByteCount() * 2, alloc);

        // test expanding
        try {
            mBitmap.setHeight(201);
            fail("shouldn't come to here");
        } catch (IllegalArgumentException e) {
        }

        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        try {
            mBitmap.setHeight(1);
            fail("shouldn't come to here");
        } catch (IllegalStateException e) {
        }
    }

    public void testSetPixel(){
        int color = 0xff << 24;

        mBitmap.recycle();

        //abnormal case: the bitmap has been recycled
        try{
            mBitmap.setPixel(10, 16, color);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        //abnormal case: the bitmap is immutable
        try{
            mBitmap.setPixel(10, 16, color);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        //abnormal case: x bigger than the source bitmap's width
        try{
            mBitmap.setPixel(200, 16, color);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        //abnormal case: y bigger than the source bitmap's height
        try{
            mBitmap.setPixel(10, 300, color);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // normal case
        mBitmap.setPixel(10, 16, 0xFF << 24);
        assertEquals(0xFF << 24, mBitmap.getPixel(10, 16));
    }

    public void testSetPixels(){
        int[] colors = createColors(100);

        //abnormal case: the bitmap has been recycled
        mBitmap.recycle();

        try{
            mBitmap.setPixels(colors, 0, 0, 0, 0, 0, 0);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        // abnormal case: the bitmap is immutable
        try{
            mBitmap.setPixels(colors, 0, 0, 0, 0, 0, 0);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: x and/or y less than 0
        try{
            mBitmap.setPixels(colors, 0, 0, -1, -1, 200, 16);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // abnormal case: width and/or height less than 0
        try{
            mBitmap.setPixels(colors, 0, 0, 0, 0, -1, -1);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // abnormal case: (x + width) bigger than the source bitmap's width
        try{
            mBitmap.setPixels(colors, 0, 0, 10, 10, 95, 50);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // abnormal case: (y + height) bigger than the source bitmap's height
        try{
            mBitmap.setPixels(colors, 0, 0, 10, 10, 50, 95);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // abnormal case: stride less than width and bigger than -width
        try{
            mBitmap.setPixels(colors, 0, 10, 10, 10, 50, 50);
            fail("shouldn't come to here");
        }catch(IllegalArgumentException e){
        }

        // abnormal case: offset less than 0
        try{
            mBitmap.setPixels(colors, -1, 50, 10, 10, 50, 50);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        // abnormal case: (offset + width) bigger than the length of colors
        try{
            mBitmap.setPixels(colors, 60, 50, 10, 10, 50, 50);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        // abnormal case: lastScanline less than 0
        try{
            mBitmap.setPixels(colors, 10, -50, 10, 10, 50, 50);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        // abnormal case: (lastScanline + width) bigger than the length of colors
        try{
            mBitmap.setPixels(colors, 10, 50, 10, 10, 50, 50);
            fail("shouldn't come to here");
        }catch(ArrayIndexOutOfBoundsException e){
        }

        // normal case
        colors = createColors(100 * 100);
        mBitmap.setPixels(colors, 0, 100, 0, 0, 100, 100);
        int[] ret = new int[100 * 100];
        mBitmap.getPixels(ret, 0, 100, 0, 0, 100, 100);

        for(int i = 0; i < 10000; i++){
            assertEquals(ret[i], colors[i]);
        }
    }

    private void checkPremultipliedBitmapConfig(Config config, boolean expectedPremul) {
        Bitmap bitmap = Bitmap.createBitmap(1, 1, config);
        bitmap.setPremultiplied(true);
        bitmap.setPixel(0, 0, Color.TRANSPARENT);
        assertTrue(bitmap.isPremultiplied() == expectedPremul);

        bitmap.setHasAlpha(false);
        assertFalse(bitmap.isPremultiplied());
    }

    public void testSetPremultipliedSimple() {
        checkPremultipliedBitmapConfig(Bitmap.Config.ALPHA_8, true);
        checkPremultipliedBitmapConfig(Bitmap.Config.RGB_565, false);
        checkPremultipliedBitmapConfig(Bitmap.Config.ARGB_4444, true);
        checkPremultipliedBitmapConfig(Bitmap.Config.ARGB_8888, true);
    }

    public void testSetPremultipliedData() {
        // with premul, will store 2,2,2,2, so it doesn't get value correct
        Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        bitmap.setPixel(0, 0, PREMUL_COLOR);
        assertEquals(bitmap.getPixel(0, 0), PREMUL_ROUNDED_COLOR);

        // read premultiplied value directly
        bitmap.setPremultiplied(false);
        assertEquals(bitmap.getPixel(0, 0), PREMUL_STORED_COLOR);

        // value can now be stored/read correctly
        bitmap.setPixel(0, 0, PREMUL_COLOR);
        assertEquals(bitmap.getPixel(0, 0), PREMUL_COLOR);

        // verify with array methods
        int testArray[] = new int[] { PREMUL_COLOR };
        bitmap.setPixels(testArray, 0, 1, 0, 0, 1, 1);
        bitmap.getPixels(testArray, 0, 1, 0, 0, 1, 1);
        assertEquals(bitmap.getPixel(0, 0), PREMUL_COLOR);
    }

    public void testPremultipliedCanvas() {
        Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        bitmap.setHasAlpha(true);
        bitmap.setPremultiplied(false);
        assertFalse(bitmap.isPremultiplied());

        Canvas c = new Canvas();
        try {
            c.drawBitmap(bitmap, 0, 0, null);
            fail("canvas should fail with exception");
        } catch (RuntimeException e) {
        }
    }

    private int getBitmapRawInt(Bitmap bitmap) {
        IntBuffer buffer = IntBuffer.allocate(1);
        bitmap.copyPixelsToBuffer(buffer);
        return buffer.get(0);
    }

    private void bitmapStoreRawInt(Bitmap bitmap, int value) {
        IntBuffer buffer = IntBuffer.allocate(1);
        buffer.put(0, value);
        bitmap.copyPixelsFromBuffer(buffer);
    }

    public void testSetPremultipliedToBuffer() {
        Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        bitmap.setPixel(0, 0, PREMUL_COLOR);
        int storedPremul = getBitmapRawInt(bitmap);

        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        bitmap.setPremultiplied(false);
        bitmap.setPixel(0, 0, PREMUL_STORED_COLOR);

        assertEquals(getBitmapRawInt(bitmap), storedPremul);
    }

    public void testSetPremultipliedFromBuffer() {
        Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        bitmap.setPremultiplied(false);
        bitmap.setPixel(0, 0, PREMUL_COLOR);
        int rawTestColor = getBitmapRawInt(bitmap);

        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        bitmap.setPremultiplied(false);
        bitmapStoreRawInt(bitmap, rawTestColor);
        assertEquals(bitmap.getPixel(0, 0), PREMUL_COLOR);
    }

    public void testSetWidth() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        int alloc = mBitmap.getAllocationByteCount();

        // test shrinking
        mBitmap.setWidth(50);
        assertEquals(mBitmap.getAllocationByteCount(), alloc);
        assertEquals(mBitmap.getByteCount() * 2, alloc);

        // test expanding
        try {
            mBitmap.setWidth(101);
            fail("shouldn't come to here");
        } catch (IllegalArgumentException e) {
        }

        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        try {
            mBitmap.setWidth(1);
            fail("shouldn't come to here");
        } catch (IllegalStateException e) {
        }
    }

    public void testWriteToParcel(){
        mBitmap.recycle();

        // abnormal case: the bitmap to be written has been recycled
        try{
            mBitmap.writeToParcel(null, 0);
            fail("shouldn't come to here");
        }catch(IllegalStateException e){
        }

        // abnormal case: failed to unparcel Bitmap
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        Parcel p = Parcel.obtain();
        mBitmap.writeToParcel(p, 0);

        try{
            Bitmap.CREATOR.createFromParcel(p);
            fail("shouldn't come to here");
        }catch(RuntimeException e){
        }

        // normal case
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        mBitmap.writeToParcel(p, 0);
        p.setDataPosition(0);
        mBitmap.equals(Bitmap.CREATOR.createFromParcel(p));
    }

    public void testGetScaledHeight1() {
        int dummyDensity = 5;
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        int scaledHeight = scaleFromDensity(ret.getHeight(), ret.getDensity(), dummyDensity);
        assertNotNull(ret);
        assertEquals(scaledHeight, ret.getScaledHeight(dummyDensity));
    }

    public void testGetScaledHeight2() {
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        DisplayMetrics metrics = new DisplayMetrics();
        metrics = getContext().getResources().getDisplayMetrics();
        int scaledHeight = scaleFromDensity(ret.getHeight(), ret.getDensity(), metrics.densityDpi);
        assertEquals(scaledHeight, ret.getScaledHeight(metrics));
    }

    public void testGetScaledHeight3() {
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        Bitmap mMutableBitmap = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
        Canvas mCanvas = new Canvas(mMutableBitmap);
        // set Density
        mCanvas.setDensity(DisplayMetrics.DENSITY_HIGH);
        int scaledHeight = scaleFromDensity(
                ret.getHeight(), ret.getDensity(), mCanvas.getDensity());
        assertEquals(scaledHeight, ret.getScaledHeight(mCanvas));
    }

    public void testGetScaledWidth1() {
        int dummyDensity = 5;
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        int scaledWidth = scaleFromDensity(ret.getWidth(), ret.getDensity(), dummyDensity);
        assertNotNull(ret);
        assertEquals(scaledWidth, ret.getScaledWidth(dummyDensity));
    }

    public void testGetScaledWidth2() {
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        DisplayMetrics metrics = new DisplayMetrics();
        metrics = getContext().getResources().getDisplayMetrics();
        int scaledWidth = scaleFromDensity(ret.getWidth(), ret.getDensity(), metrics.densityDpi);
        assertEquals(scaledWidth, ret.getScaledWidth(metrics));
    }

    public void testGetScaledWidth3() {
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        Bitmap mMutableBitmap = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
        Canvas mCanvas = new Canvas(mMutableBitmap);
        // set Density
        mCanvas.setDensity(DisplayMetrics.DENSITY_HIGH);
        int scaledWidth = scaleFromDensity(ret.getWidth(), ret.getDensity(),  mCanvas.getDensity());
        assertEquals(scaledWidth, ret.getScaledWidth(mCanvas));
    }

    private int scaleFromDensity(int size, int sdensity, int tdensity) {
        if (sdensity == Bitmap.DENSITY_NONE || sdensity == tdensity) {
            return size;
        }

        // Scale by tdensity / sdensity, rounding up.
        return ((size * tdensity) + (sdensity >> 1)) / sdensity;
    }

    private int[] createColors(int size){
        int[] colors = new int[size];

        for (int i = 0; i < size; i++) {
            colors[i] = (0xFF << 24) | (i << 16) | (i << 8) | i;
        }

        return colors;
    }
}
