/*
 * 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorSpace;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Debug;
import android.os.Parcel;
import android.os.StrictMode;
import android.util.DisplayMetrics;
import android.view.Surface;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.ColorUtils;
import com.android.compatibility.common.util.WidgetTestUtils;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class BitmapTest {
    // small alpha values cause color values to be pre-multiplied down, losing accuracy
    private static final int PREMUL_COLOR = Color.argb(2, 255, 254, 253);
    private static final int PREMUL_ROUNDED_COLOR = Color.argb(2, 255, 255, 255);
    private static final int PREMUL_STORED_COLOR = Color.argb(2, 2, 2, 2);

    private static final BitmapFactory.Options HARDWARE_OPTIONS = createHardwareBitmapOptions();

    static {
        System.loadLibrary("ctsgraphics_jni");
    }

    private Resources mRes;
    private Bitmap mBitmap;
    private BitmapFactory.Options mOptions;

    @Before
    public void setup() {
        mRes = InstrumentationRegistry.getTargetContext().getResources();
        mOptions = new BitmapFactory.Options();
        mOptions.inScaled = false;
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
    }

    @Test(expected=IllegalStateException.class)
    public void testCompressRecycled() {
        mBitmap.recycle();
        mBitmap.compress(CompressFormat.JPEG, 0, null);
    }

    @Test(expected=NullPointerException.class)
    public void testCompressNullStream() {
        mBitmap.compress(CompressFormat.JPEG, 0, null);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCompressQualityTooLow() {
        mBitmap.compress(CompressFormat.JPEG, -1, new ByteArrayOutputStream());
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCompressQualityTooHigh() {
        mBitmap.compress(CompressFormat.JPEG, 101, new ByteArrayOutputStream());
    }

    @Test
    public void testCompress() {
        assertTrue(mBitmap.compress(CompressFormat.JPEG, 50, new ByteArrayOutputStream()));
    }

    @Test(expected=IllegalStateException.class)
    public void testCopyRecycled() {
        mBitmap.recycle();
        mBitmap.copy(Config.RGB_565, false);
    }

    @Test
    public void testCopy() {
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap = mBitmap.copy(Config.ARGB_8888, false);
        WidgetTestUtils.assertEquals(mBitmap, bitmap);
    }

    @Test
    public void testCopyConfigs() {
        Config[] supportedConfigs = new Config[] {
                Config.ALPHA_8, Config.RGB_565, Config.ARGB_8888, Config.RGBA_F16,
        };
        for (Config src : supportedConfigs) {
            for (Config dst : supportedConfigs) {
                Bitmap srcBitmap = Bitmap.createBitmap(1, 1, src);
                srcBitmap.eraseColor(Color.WHITE);
                Bitmap dstBitmap = srcBitmap.copy(dst, false);
                assertNotNull("Should support copying from " + src + " to " + dst,
                        dstBitmap);
                if (Config.ALPHA_8 == dst || Config.ALPHA_8 == src) {
                    // Color will be opaque but color information will be lost.
                    assertEquals("Color should be black when copying from " + src + " to "
                            + dst, Color.BLACK, dstBitmap.getPixel(0, 0));
                } else {
                    assertEquals("Color should be preserved when copying from " + src + " to "
                            + dst, Color.WHITE, dstBitmap.getPixel(0, 0));
                }
            }
        }
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCopyMutableHwBitmap() {
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        mBitmap.copy(Config.HARDWARE, true);
    }

    @Test(expected=RuntimeException.class)
    public void testCopyPixelsToBufferUnsupportedBufferClass() {
        final int pixSize = mBitmap.getRowBytes() * mBitmap.getHeight();

        mBitmap.copyPixelsToBuffer(CharBuffer.allocate(pixSize));
    }

    @Test(expected=RuntimeException.class)
    public void testCopyPixelsToBufferBufferTooSmall() {
        final int pixSize = mBitmap.getRowBytes() * mBitmap.getHeight();
        final int tooSmall = pixSize / 2;

        mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
    }

    @Test
    public void testCopyPixelsToBuffer() {
        final int pixSize = mBitmap.getRowBytes() * mBitmap.getHeight();

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

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

        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());
        }
    }

    @Test
    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());
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapNegativeX() {
        Bitmap.createBitmap(mBitmap, -100, 50, 50, 200);
    }

    @Test
    public void testCreateBitmap2() {
        // 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));
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapNegativeXY() {
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);

        // abnormal case: x and/or y less than 0
        Bitmap.createBitmap(mBitmap, -1, -1, 10, 10, null, false);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapNegativeWidthHeight() {
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);

        // abnormal case: width and/or height less than 0
        Bitmap.createBitmap(mBitmap, 1, 1, -10, -10, null, false);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapXRegionTooWide() {
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);

        // abnormal case: (x + width) bigger than source bitmap's width
        Bitmap.createBitmap(mBitmap, 10, 10, 95, 50, null, false);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapYRegionTooTall() {
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);

        // abnormal case: (y + height) bigger than source bitmap's height
        Bitmap.createBitmap(mBitmap, 10, 10, 50, 95, null, false);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateMutableBitmapWithHardwareConfig() {
        Bitmap.createBitmap(100, 100, Config.HARDWARE);
    }

    @Test
    public void testCreateBitmap3() {
        // 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));
    }

    @Test
    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());
    }

    private static void verify2x2BitmapContents(int[] expected, Bitmap observed) {
        ColorUtils.verifyColor(expected[0], observed.getPixel(0, 0));
        ColorUtils.verifyColor(expected[1], observed.getPixel(1, 0));
        ColorUtils.verifyColor(expected[2], observed.getPixel(0, 1));
        ColorUtils.verifyColor(expected[3], observed.getPixel(1, 1));
    }

    @Test
    public void testCreateBitmap_matrix() {
        int[] colorArray = new int[] { Color.RED, Color.GREEN, Color.BLUE, Color.BLACK };
        Bitmap src = Bitmap.createBitmap(2, 2, Config.ARGB_8888);
        src.setPixels(colorArray,0, 2, 0, 0, 2, 2);

        // baseline
        verify2x2BitmapContents(colorArray, src);

        // null
        Bitmap dst = Bitmap.createBitmap(src, 0, 0, 2, 2, null, false);
        verify2x2BitmapContents(colorArray, dst);

        // identity matrix
        Matrix matrix = new Matrix();
        dst = Bitmap.createBitmap(src, 0, 0, 2, 2, matrix, false);
        verify2x2BitmapContents(colorArray, dst);

        // big scale - only red visible
        matrix.setScale(10, 10);
        dst = Bitmap.createBitmap(src, 0, 0, 2, 2, matrix, false);
        verify2x2BitmapContents(new int[] { Color.RED, Color.RED, Color.RED, Color.RED }, dst);

        // rotation
        matrix.setRotate(90);
        dst = Bitmap.createBitmap(src, 0, 0, 2, 2, matrix, false);
        verify2x2BitmapContents(
                new int[] { Color.BLUE, Color.RED, Color.BLACK, Color.GREEN }, dst);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapFromColorsNegativeWidthHeight() {
        int[] colors = createColors(100);

        // abnormal case: width and/or height less than 0
        Bitmap.createBitmap(colors, 0, 100, -1, 100, Config.RGB_565);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testCreateBitmapFromColorsIllegalStride() {
        int[] colors = createColors(100);

        // abnormal case: stride less than width and bigger than -width
        Bitmap.createBitmap(colors, 10, 10, 100, 100, Config.RGB_565);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testCreateBitmapFromColorsNegativeOffset() {
        int[] colors = createColors(100);

        // abnormal case: offset less than 0
        Bitmap.createBitmap(colors, -10, 100, 100, 100, Config.RGB_565);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testCreateBitmapFromColorsOffsetTooLarge() {
        int[] colors = createColors(100);

        // abnormal case: (offset + width) bigger than colors' length
        Bitmap.createBitmap(colors, 10, 100, 100, 100, Config.RGB_565);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testCreateBitmapFromColorsScalnlineTooLarge() {
        int[] colors = createColors(100);

        // abnormal case: (lastScanline + width) bigger than colors' length
        Bitmap.createBitmap(colors, 10, 100, 50, 100, Config.RGB_565);
    }

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

        // 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());
    }

    @Test
    public void testCreateBitmap_displayMetrics_mutable() {
        DisplayMetrics metrics =
                InstrumentationRegistry.getTargetContext().getResources().getDisplayMetrics();

        Bitmap bitmap;
        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888);
        assertTrue(bitmap.isMutable());
        assertEquals(metrics.densityDpi, bitmap.getDensity());

        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888);
        assertTrue(bitmap.isMutable());
        assertEquals(metrics.densityDpi, bitmap.getDensity());

        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888, true);
        assertTrue(bitmap.isMutable());
        assertEquals(metrics.densityDpi, bitmap.getDensity());

        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888, true, ColorSpace.get(
                ColorSpace.Named.SRGB));

        assertTrue(bitmap.isMutable());
        assertEquals(metrics.densityDpi, bitmap.getDensity());

        int[] colors = createColors(100);
        assertNotNull(Bitmap.createBitmap(metrics, colors, 0, 10, 10, 10, Config.ARGB_8888));
        assertNotNull(Bitmap.createBitmap(metrics, colors, 10, 10, Config.ARGB_8888));
    }

    @Test
    public void testCreateBitmap_displayMetrics_immutable() {
        DisplayMetrics metrics =
                InstrumentationRegistry.getTargetContext().getResources().getDisplayMetrics();
        int[] colors = createColors(100);

        Bitmap bitmap;
        bitmap = Bitmap.createBitmap(metrics, colors, 0, 10, 10, 10, Config.ARGB_8888);
        assertFalse(bitmap.isMutable());
        assertEquals(metrics.densityDpi, bitmap.getDensity());

        bitmap = Bitmap.createBitmap(metrics, colors, 10, 10, Config.ARGB_8888);
        assertFalse(bitmap.isMutable());
        assertEquals(metrics.densityDpi, bitmap.getDensity());
    }

    @Test
    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());
    }

    @Test
    public void testGenerationId() {
        Bitmap bitmap = Bitmap.createBitmap(10, 10, Config.ARGB_8888);
        int genId = bitmap.getGenerationId();
        assertEquals("not expected to change", genId, bitmap.getGenerationId());
        bitmap.setDensity(bitmap.getDensity() + 4);
        assertEquals("not expected to change", genId, bitmap.getGenerationId());
        bitmap.getPixel(0, 0);
        assertEquals("not expected to change", genId, bitmap.getGenerationId());

        int beforeGenId = bitmap.getGenerationId();
        bitmap.eraseColor(Color.WHITE);
        int afterGenId = bitmap.getGenerationId();
        assertTrue("expected to increase", afterGenId > beforeGenId);

        beforeGenId = bitmap.getGenerationId();
        bitmap.setPixel(4, 4, Color.BLUE);
        afterGenId = bitmap.getGenerationId();
        assertTrue("expected to increase again", afterGenId > beforeGenId);
    }

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

    @Test(expected=IllegalStateException.class)
    public void testEraseColorOnRecycled() {
        mBitmap.recycle();

        mBitmap.eraseColor(0);
    }

    @Test(expected=IllegalStateException.class)
    public void testEraseColorOnImmutable() {
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        //abnormal case: bitmap is immutable
        mBitmap.eraseColor(0);
    }

    @Test
    public void testEraseColor() {
        // 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));
    }

    @Test(expected=IllegalStateException.class)
    public void testExtractAlphaFromRecycled() {
        mBitmap.recycle();

        mBitmap.extractAlpha();
    }

    @Test
    public void testExtractAlpha() {
        // normal case
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        Bitmap ret = mBitmap.extractAlpha();
        assertNotNull(ret);
        int source = mBitmap.getPixel(10, 20);
        int result = ret.getPixel(10, 20);
        assertEquals(Color.alpha(source), Color.alpha(result));
        assertEquals(0xFF, Color.alpha(result));
    }

    @Test(expected=IllegalStateException.class)
    public void testExtractAlphaWithPaintAndOffsetFromRecycled() {
        mBitmap.recycle();

        mBitmap.extractAlpha(new Paint(), new int[]{0, 1});
    }

    @Test
    public void testExtractAlphaWithPaintAndOffset() {
        // normal case
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        Bitmap ret = mBitmap.extractAlpha(new Paint(), new int[]{0, 1});
        assertNotNull(ret);
        int source = mBitmap.getPixel(10, 20);
        int result = ret.getPixel(10, 20);
        assertEquals(Color.alpha(source), Color.alpha(result));
        assertEquals(0xFF, Color.alpha(result));
    }

    @Test
    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);
    }

    @Test
    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());

        // Can't call Bitmap.createBitmap with Bitmap.Config.HARDWARE,
        // because createBitmap creates mutable bitmap and hardware bitmaps are always immutable,
        // so such call will throw an exception.
        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                HARDWARE_OPTIONS);
        assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig());
    }

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

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

    @Test(expected=IllegalStateException.class)
    public void testGetPixelFromRecycled() {
        mBitmap.recycle();

        mBitmap.getPixel(10, 16);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testGetPixelXTooLarge() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        // abnormal case: x bigger than the source bitmap's width
        mBitmap.getPixel(200, 16);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testGetPixelYTooLarge() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        // abnormal case: y bigger than the source bitmap's height
        mBitmap.getPixel(10, 300);
    }

    @Test
    public void testGetPixel() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        // 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(0xFF000000, mBitmap.getPixel(5, 5));
        mBitmap.setPixel(5, 5, 0xA8A8A8A8);
        assertEquals(0xA8000000, mBitmap.getPixel(5, 5));
        mBitmap.setPixel(5, 5, 0x00000000);
        assertEquals(0x00000000, mBitmap.getPixel(5, 5));
        mBitmap.setPixel(5, 5, 0x1F000000);
        assertEquals(0x1F000000, mBitmap.getPixel(5, 5));
    }

    @Test
    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());
    }

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

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

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

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

    @Test
    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(expected=IllegalArgumentException.class)
    public void testReconfigureExpanding() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        mBitmap.reconfigure(101, 201, Bitmap.Config.ARGB_8888);
    }

    @Test(expected=IllegalStateException.class)
    public void testReconfigureMutable() {
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        mBitmap.reconfigure(1, 1, Bitmap.Config.ALPHA_8);
    }

    // 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.
    @Test
    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);

                        verifyAlphaAndPremul(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).
                        verifyAlphaAndPremul(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 verifyAlphaAndPremul(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;
        }
    }

    @Test
    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(expected=IllegalArgumentException.class)
    public void testSetConfigExpanding() {
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
        // test expanding
        mBitmap.setConfig(Bitmap.Config.ARGB_8888);
    }

    @Test(expected=IllegalStateException.class)
    public void testSetConfigMutable() {
        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        mBitmap.setConfig(Bitmap.Config.ALPHA_8);
    }

    @Test
    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(expected=IllegalArgumentException.class)
    public void testSetHeightExpanding() {
        // test expanding
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
        mBitmap.setHeight(201);
    }

    @Test(expected=IllegalStateException.class)
    public void testSetHeightMutable() {
        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
        mBitmap.setHeight(1);
    }

    @Test(expected=IllegalStateException.class)
    public void testSetPixelOnRecycled() {
        int color = 0xff << 24;

        mBitmap.recycle();
        mBitmap.setPixel(10, 16, color);
    }

    @Test(expected=IllegalStateException.class)
    public void testSetPixelOnImmutable() {
        int color = 0xff << 24;
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        mBitmap.setPixel(10, 16, color);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelXIsTooLarge() {
        int color = 0xff << 24;
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        // abnormal case: x bigger than the source bitmap's width
        mBitmap.setPixel(200, 16, color);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelYIsTooLarge() {
        int color = 0xff << 24;
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        // abnormal case: y bigger than the source bitmap's height
        mBitmap.setPixel(10, 300, color);
    }

    @Test
    public void testSetPixel() {
        int color = 0xff << 24;
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);

        // normal case
        mBitmap.setPixel(10, 16, color);
        assertEquals(color, mBitmap.getPixel(10, 16));
    }

    @Test(expected=IllegalStateException.class)
    public void testSetPixelsOnRecycled() {
        int[] colors = createColors(100);

        mBitmap.recycle();
        mBitmap.setPixels(colors, 0, 0, 0, 0, 0, 0);
    }

    @Test(expected=IllegalStateException.class)
    public void testSetPixelsOnImmutable() {
        int[] colors = createColors(100);
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        mBitmap.setPixels(colors, 0, 0, 0, 0, 0, 0);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelsXYNegative() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: x and/or y less than 0
        mBitmap.setPixels(colors, 0, 0, -1, -1, 200, 16);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelsWidthHeightNegative() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: width and/or height less than 0
        mBitmap.setPixels(colors, 0, 0, 0, 0, -1, -1);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelsXTooHigh() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: (x + width) bigger than the source bitmap's width
        mBitmap.setPixels(colors, 0, 0, 10, 10, 95, 50);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelsYTooHigh() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: (y + height) bigger than the source bitmap's height
        mBitmap.setPixels(colors, 0, 0, 10, 10, 50, 95);
    }

    @Test(expected=IllegalArgumentException.class)
    public void testSetPixelsStrideIllegal() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: stride less than width and bigger than -width
        mBitmap.setPixels(colors, 0, 10, 10, 10, 50, 50);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testSetPixelsOffsetNegative() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: offset less than 0
        mBitmap.setPixels(colors, -1, 50, 10, 10, 50, 50);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testSetPixelsOffsetTooBig() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: (offset + width) bigger than the length of colors
        mBitmap.setPixels(colors, 60, 50, 10, 10, 50, 50);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testSetPixelsLastScanlineNegative() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: lastScanline less than 0
        mBitmap.setPixels(colors, 10, -50, 10, 10, 50, 50);
    }

    @Test(expected=ArrayIndexOutOfBoundsException.class)
    public void testSetPixelsLastScanlineTooBig() {
        int[] colors = createColors(100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

        // abnormal case: (lastScanline + width) bigger than the length of colors
        mBitmap.setPixels(colors, 10, 50, 10, 10, 50, 50);
    }

    @Test
    public void testSetPixels() {
        int[] colors = createColors(100 * 100);
        mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        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 verifyPremultipliedBitmapConfig(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());
    }

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

    @Test
    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);
    }

    @Test
    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);
    }

    @Test
    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);
    }

    @Test
    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);
    }

    @Test
    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(expected=IllegalArgumentException.class)
    public void testSetWidthExpanding() {
        // test expanding
        mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);

        mBitmap.setWidth(101);
    }

    @Test(expected=IllegalStateException.class)
    public void testSetWidthMutable() {
        // test mutable
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);

        mBitmap.setWidth(1);
    }

    @Test(expected=IllegalStateException.class)
    public void testWriteToParcelRecycled() {
        mBitmap.recycle();

        mBitmap.writeToParcel(null, 0);
    }

    @Test
    public void testWriteToParcel() {
        // 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){
        }

        p.recycle();
        // normal case
        p = Parcel.obtain();
        mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        mBitmap.writeToParcel(p, 0);
        p.setDataPosition(0);
        assertTrue(mBitmap.sameAs(Bitmap.CREATOR.createFromParcel(p)));

        p.recycle();
    }

    @Test
    public void testWriteHwBitmapToParcel() {
        mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        Parcel p = Parcel.obtain();
        mBitmap.writeToParcel(p, 0);
        p.setDataPosition(0);
        Bitmap expectedBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot);
        assertTrue(expectedBitmap.sameAs(Bitmap.CREATOR.createFromParcel(p)));

        p.recycle();
    }

    @Test
    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));
    }

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

    @Test
    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));
    }

    @Test
    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));
    }

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

    @Test
    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));
    }

    @Test
    public void testSameAs_simpleSuccess() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);
        assertTrue(bitmap1.sameAs(bitmap2));
        assertTrue(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_simpleFail() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);
        bitmap2.setPixel(20, 10, Color.WHITE);
        assertFalse(bitmap1.sameAs(bitmap2));
        assertFalse(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_reconfigure() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(150, 150, Config.ARGB_8888);
        bitmap2.reconfigure(100, 100, Config.ARGB_8888); // now same size, so should be same
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);
        assertTrue(bitmap1.sameAs(bitmap2));
        assertTrue(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_config() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 200, Config.RGB_565);
        Bitmap bitmap2 = Bitmap.createBitmap(100, 200, Config.ARGB_8888);

        // both bitmaps can represent black perfectly
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);

        // but not same due to config
        assertFalse(bitmap1.sameAs(bitmap2));
        assertFalse(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_width() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(101, 100, Config.ARGB_8888);
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);
        assertFalse(bitmap1.sameAs(bitmap2));
        assertFalse(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_height() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(102, 100, Config.ARGB_8888);
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);
        assertFalse(bitmap1.sameAs(bitmap2));
        assertFalse(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_opaque() {
        Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        Bitmap bitmap2 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        bitmap1.eraseColor(Color.BLACK);
        bitmap2.eraseColor(Color.BLACK);
        bitmap1.setHasAlpha(true);
        bitmap2.setHasAlpha(false);
        assertFalse(bitmap1.sameAs(bitmap2));
        assertFalse(bitmap2.sameAs(bitmap1));
    }

    @Test
    public void testSameAs_hardware() {
        Bitmap bitmap1 = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        Bitmap bitmap2 = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        Bitmap bitmap3 = BitmapFactory.decodeResource(mRes, R.drawable.robot);
        Bitmap bitmap4 = BitmapFactory.decodeResource(mRes, R.drawable.start, HARDWARE_OPTIONS);
        assertTrue(bitmap1.sameAs(bitmap2));
        assertTrue(bitmap2.sameAs(bitmap1));
        assertFalse(bitmap1.sameAs(bitmap3));
        assertFalse(bitmap1.sameAs(bitmap4));
    }

    @Test(expected=IllegalStateException.class)
    public void testHardwareGetPixel() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.getPixel(0, 0);
    }

    @Test(expected=IllegalStateException.class)
    public void testHardwareGetPixels() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.getPixels(new int[5], 0, 5, 0, 0, 5, 1);
    }

    @Test
    public void testGetConfigOnRecycled() {
        Bitmap bitmap1 = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap1.recycle();
        assertEquals(Config.HARDWARE, bitmap1.getConfig());
        Bitmap bitmap2 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
        bitmap2.recycle();
        assertEquals(Config.ARGB_8888, bitmap2.getConfig());
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareSetWidth() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.setWidth(30);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareSetHeight() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.setHeight(30);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareSetConfig() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.setConfig(Config.ARGB_8888);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareReconfigure() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.reconfigure(30, 30, Config.ARGB_8888);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareSetPixels() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.setPixels(new int[10], 0, 1, 0, 0, 1, 1);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareSetPixel() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.setPixel(1, 1, 0);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareEraseColor() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
        bitmap.eraseColor(0);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareCopyPixelsToBuffer() {
        Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, HARDWARE_OPTIONS);
        ByteBuffer byteBuf = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
        bitmap.copyPixelsToBuffer(byteBuf);
    }

    @Test(expected = IllegalStateException.class)
    public void testHardwareCopyPixelsFromBuffer() {
        IntBuffer intBuf1 = IntBuffer.allocate(mBitmap.getRowBytes() * mBitmap.getHeight());
        assertEquals(0, intBuf1.position());
        mBitmap.copyPixelsToBuffer(intBuf1);
        Bitmap hwBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, HARDWARE_OPTIONS);
        hwBitmap.copyPixelsFromBuffer(intBuf1);
    }

    @Test
    public void testUseMetadataAfterRecycle() {
        Bitmap bitmap = Bitmap.createBitmap(10, 20, Config.RGB_565);
        bitmap.recycle();
        assertEquals(10, bitmap.getWidth());
        assertEquals(20, bitmap.getHeight());
        assertEquals(Config.RGB_565, bitmap.getConfig());
    }

    @Test
    public void testCopyHWBitmapInStrictMode() {
        strictModeTest(()->{
            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
            hwBitmap.copy(Config.ARGB_8888, false);
        });
    }

    @Test
    public void testCreateScaledFromHWInStrictMode() {
        strictModeTest(()->{
            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
            Bitmap.createScaledBitmap(hwBitmap, 200, 200, false);
        });
    }

    @Test
    public void testExtractAlphaFromHWInStrictMode() {
        strictModeTest(()->{
            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
            hwBitmap.extractAlpha();
        });
    }

    @Test
    public void testCompressInStrictMode() {
        strictModeTest(()->{
            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            bitmap.compress(CompressFormat.JPEG, 90, new ByteArrayOutputStream());
        });
    }

    @Test
    public void testParcelHWInStrictMode() {
        strictModeTest(()->{
            mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            Bitmap hwBitmap = mBitmap.copy(Config.HARDWARE, false);
            hwBitmap.writeToParcel(Parcel.obtain(), 0);
        });
    }

    @Test
    public void testSameAsFirstHWInStrictMode() {
        strictModeTest(()->{
            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
            hwBitmap.sameAs(bitmap);
        });
    }

    @Test
    public void testSameAsSecondHWInStrictMode() {
        strictModeTest(()->{
            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
            bitmap.sameAs(hwBitmap);
        });
    }

    @Test
    public void testNdkAccessAfterRecycle() {
        Bitmap bitmap = Bitmap.createBitmap(10, 20, Config.RGB_565);
        nValidateBitmapInfo(bitmap, 10, 20, true);
        bitmap.recycle();
        nValidateBitmapInfo(bitmap, 10, 20, true);
        nValidateNdkAccessAfterRecycle(bitmap);
    }

    private static void runGcAndFinalizersSync() {
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();

        final CountDownLatch fence = new CountDownLatch(1);
        new Object() {
            @Override
            protected void finalize() throws Throwable {
                try {
                    fence.countDown();
                } finally {
                    super.finalize();
                }
            }
        };
        try {
            do {
                Runtime.getRuntime().gc();
                Runtime.getRuntime().runFinalization();
            } while (!fence.await(100, TimeUnit.MILLISECONDS));
        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }
    }

    private static File sProcSelfFd = new File("/proc/self/fd");
    private static int getFdCount() {
        return sProcSelfFd.listFiles().length;
    }

    private static void assertNotLeaking(int iteration,
            Debug.MemoryInfo start, Debug.MemoryInfo end) {
        Debug.getMemoryInfo(end);
        assertNotEquals(0, start.getTotalPss());
        assertNotEquals(0, end.getTotalPss());
        if (end.getTotalPss() - start.getTotalPss() > 2000 /* kB */) {
            runGcAndFinalizersSync();
            Debug.getMemoryInfo(end);
            if (end.getTotalPss() - start.getTotalPss() > 4000 /* kB */) {
                // Guarded by if so we don't continually generate garbage for the
                // assertion string.
                assertEquals("Memory leaked, iteration=" + iteration,
                        start.getTotalPss(), end.getTotalPss(),
                        4000 /* kb */);
            }
        }
    }

    private static void runNotLeakingTest(Runnable test) {
        Debug.MemoryInfo meminfoStart = new Debug.MemoryInfo();
        Debug.MemoryInfo meminfoEnd = new Debug.MemoryInfo();
        int fdCount = -1;
        // Do a warmup to reach steady-state memory usage
        for (int i = 0; i < 50; i++) {
            test.run();
        }
        runGcAndFinalizersSync();
        Debug.getMemoryInfo(meminfoStart);
        fdCount = getFdCount();
        // Now run the test
        for (int i = 0; i < 2000; i++) {
            if (i % 100 == 5) {
                assertNotLeaking(i, meminfoStart, meminfoEnd);
                final int curFdCount = getFdCount();
                if (curFdCount - fdCount > 10) {
                    fail(String.format("FDs leaked. Expected=%d, current=%d, iteration=%d",
                            fdCount, curFdCount, i));
                }
            }
            test.run();
        }
        assertNotLeaking(2000, meminfoStart, meminfoEnd);
        final int curFdCount = getFdCount();
        if (curFdCount - fdCount > 10) {
            fail(String.format("FDs leaked. Expected=%d, current=%d", fdCount, curFdCount));
        }
    }

    @Test
    @LargeTest
    public void testHardwareBitmapNotLeaking() {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Config.HARDWARE;
        opts.inScaled = false;

        runNotLeakingTest(() -> {
            Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, opts);
            assertNotNull(bitmap);
            // Make sure nothing messed with the bitmap
            assertEquals(128, bitmap.getWidth());
            assertEquals(128, bitmap.getHeight());
            assertEquals(Config.HARDWARE, bitmap.getConfig());
            bitmap.recycle();
        });
    }

    @Test
    @LargeTest
    public void testDrawingHardwareBitmapNotLeaking() {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Config.HARDWARE;
        opts.inScaled = false;
        RenderTarget renderTarget = RenderTarget.create();
        renderTarget.setDefaultSize(128, 128);
        final Surface surface = renderTarget.getSurface();

        runNotLeakingTest(() -> {
            Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, opts);
            assertNotNull(bitmap);
            // Make sure nothing messed with the bitmap
            assertEquals(128, bitmap.getWidth());
            assertEquals(128, bitmap.getHeight());
            assertEquals(Config.HARDWARE, bitmap.getConfig());
            Canvas canvas = surface.lockHardwareCanvas();
            canvas.drawBitmap(bitmap, 0, 0, null);
            surface.unlockCanvasAndPost(canvas);
            bitmap.recycle();
        });
    }

    private void strictModeTest(Runnable runnable) {
        StrictMode.ThreadPolicy originalPolicy = StrictMode.getThreadPolicy();
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectCustomSlowCalls().penaltyDeath().build());
        try {
            runnable.run();
            fail("Shouldn't reach it");
        } catch (RuntimeException expected){
            // expect to receive StrictModeViolation
        } finally {
            StrictMode.setThreadPolicy(originalPolicy);
        }
    }

    private static native void nValidateBitmapInfo(Bitmap bitmap, int width, int height,
            boolean is565);
    private static native void nValidateNdkAccessAfterRecycle(Bitmap bitmap);

    private static 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 static 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;
    }

    private static BitmapFactory.Options createHardwareBitmapOptions() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Config.HARDWARE;
        return options;
    }
}
