/*
 * 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.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.ColorSpace.Named;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.hardware.HardwareBuffer;
import android.os.Debug;
import android.os.Parcel;
import android.os.StrictMode;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.DisplayMetrics;
import android.view.Surface;

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.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);
        assertFalse(bitmap.isMutable());
        Bitmap ret = Bitmap.createBitmap(bitmap);
        assertNotNull(ret);
        assertFalse(ret.isMutable());
        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);
        assertFalse(mBitmap.isMutable()); // createBitmap w/ colors should be immutable
        Bitmap ret = Bitmap.createBitmap(mBitmap, 0, 0, 100, 100);
        assertNotNull(ret);
        assertFalse(ret.isMutable()); // createBitmap from subset should be immutable
        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);
        assertFalse(ret.isMutable()); // subset should be immutable
        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);
        assertTrue(ret.isMutable());
        assertNotNull(ret);
        assertFalse(mBitmap.equals(ret));
    }

    @Test
    public void testCreateBitmapFromHardwareBitmap() {
        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                HARDWARE_OPTIONS);
        assertEquals(Config.HARDWARE, hardwareBitmap.getConfig());

        Bitmap ret = Bitmap.createBitmap(hardwareBitmap, 0, 0, 100, 100, null, false);
        assertEquals(Config.HARDWARE, ret.getConfig());
        assertFalse(ret.isMutable());
    }

    @Test
    public void testCreateBitmap4() {
        Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
        assertNotNull(ret);
        assertTrue(ret.isMutable());
        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);
        assertTrue(src.isMutable());
        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);
        assertTrue(dst.isMutable());
        verify2x2BitmapContents(colorArray, dst);

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

        // big scale - only red visible
        matrix.setScale(10, 10);
        dst = Bitmap.createBitmap(src, 0, 0, 2, 2, matrix, false);
        assertTrue(dst.isMutable());
        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);
        assertTrue(dst.isMutable());
        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);
        assertFalse(ret.isMutable());
        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);
        bitmap = Bitmap.createBitmap(metrics, colors, 0, 10, 10, 10, Config.ARGB_8888);
        assertNotNull(bitmap);
        assertFalse(bitmap.isMutable());

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

    @Test
    public void testCreateBitmap_noDisplayMetrics_mutable() {
        Bitmap bitmap;
        bitmap = Bitmap.createBitmap(10, 10, Config.ARGB_8888);
        assertTrue(bitmap.isMutable());

        bitmap = Bitmap.createBitmap(10, 10, Config.ARGB_8888, true);
        assertTrue(bitmap.isMutable());

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

    @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 testCreateBitmap_noDisplayMetrics_immutable() {
        int[] colors = createColors(100);
        Bitmap bitmap;
        bitmap = Bitmap.createBitmap(colors, 0, 10, 10, 10, Config.ARGB_8888);
        assertFalse(bitmap.isMutable());

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

    @Test
    public void testCreateBitmap_Picture_immutable() {
        Picture picture = new Picture();
        Canvas canvas = picture.beginRecording(200, 100);

        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        p.setColor(0x88FF0000);
        canvas.drawCircle(50, 50, 40, p);

        p.setColor(Color.GREEN);
        p.setTextSize(30);
        canvas.drawText("Pictures", 60, 60, p);
        picture.endRecording();

        Bitmap bitmap;
        bitmap = Bitmap.createBitmap(picture);
        assertFalse(bitmap.isMutable());

        bitmap = Bitmap.createBitmap(picture, 100, 100, Config.HARDWARE);
        assertFalse(bitmap.isMutable());

        bitmap = Bitmap.createBitmap(picture, 100, 100, Config.ARGB_8888);
        assertFalse(bitmap.isMutable());
    }

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

    @Test
    public void testWrapHardwareBufferSucceeds() {
        try (HardwareBuffer hwBuffer = createTestBuffer(128, 128, false)) {
            Bitmap bitmap = Bitmap.wrapHardwareBuffer(hwBuffer, ColorSpace.get(Named.SRGB));
            assertNotNull(bitmap);
            bitmap.recycle();
        }
    }

    @Test(expected = IllegalArgumentException.class)
    public void testWrapHardwareBufferWithInvalidUsageFails() {
        try (HardwareBuffer hwBuffer = HardwareBuffer.create(512, 512, HardwareBuffer.RGBA_8888, 1,
            HardwareBuffer.USAGE_CPU_WRITE_RARELY)) {
            Bitmap bitmap = Bitmap.wrapHardwareBuffer(hwBuffer, ColorSpace.get(Named.SRGB));
        }
    }

    @Test(expected = IllegalArgumentException.class)
    public void testWrapHardwareBufferWithRgbBufferButNonRgbColorSpaceFails() {
        try (HardwareBuffer hwBuffer = HardwareBuffer.create(512, 512, HardwareBuffer.RGBA_8888, 1,
            HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)) {
            Bitmap bitmap = Bitmap.wrapHardwareBuffer(hwBuffer, ColorSpace.get(Named.CIE_LAB));
        }
    }

    @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
    public void testSameAs_wrappedHardwareBuffer() {
        try (HardwareBuffer hwBufferA = createTestBuffer(512, 512, true);
             HardwareBuffer hwBufferB = createTestBuffer(512, 512, true);
             HardwareBuffer hwBufferC = createTestBuffer(512, 512, true);) {
            // Fill buffer C with generated data
            nFillRgbaHwBuffer(hwBufferC);

            // Create the test bitmaps
            Bitmap bitmap1 = Bitmap.wrapHardwareBuffer(hwBufferA, ColorSpace.get(Named.SRGB));
            Bitmap bitmap2 = Bitmap.wrapHardwareBuffer(hwBufferA, ColorSpace.get(Named.SRGB));
            Bitmap bitmap3 = BitmapFactory.decodeResource(mRes, R.drawable.robot);
            Bitmap bitmap4 = Bitmap.wrapHardwareBuffer(hwBufferB, ColorSpace.get(Named.SRGB));
            Bitmap bitmap5 = Bitmap.wrapHardwareBuffer(hwBufferC, ColorSpace.get(Named.SRGB));

            // Run the compare-a-thon
            assertTrue(bitmap1.sameAs(bitmap2));  // SAME UNDERLYING BUFFER
            assertTrue(bitmap2.sameAs(bitmap1));  // SAME UNDERLYING BUFFER
            assertFalse(bitmap1.sameAs(bitmap3)); // HW vs. NON-HW
            assertTrue(bitmap1.sameAs(bitmap4));  // DIFFERENT BUFFERS, SAME CONTENT
            assertFalse(bitmap1.sameAs(bitmap5)); // DIFFERENT BUFFERS, DIFFERENT CONTENT
        }
    }

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

    @Test
    public void bitmapIsMutable() {
        Bitmap b = Bitmap.createBitmap(10, 10, Config.ARGB_8888);
        assertTrue("CreateBitmap w/ params should be mutable", b.isMutable());
        assertTrue("CreateBitmap from bitmap should be mutable",
                Bitmap.createBitmap(b).isMutable());
    }

    private void runGcAndFinalizersSync() {
        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);
        }
        Runtime.getRuntime().gc();
    }

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

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

        for (int i = 0; i < 2000; i++) {
            if (i == 2) {
                // Not really the "start" but by having done a couple
                // we've fully initialized any state that may be required,
                // so memory usage should be stable now
                runGcAndFinalizersSync();
                Debug.getMemoryInfo(meminfoStart);
            }
            if (i % 100 == 5) {
                assertNotLeaking(i, meminfoStart, meminfoEnd);
            }
            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();
        }

        assertNotLeaking(2000, meminfoStart, meminfoEnd);
    }

    @Test
    @LargeTest
    public void testWrappedHardwareBufferBitmapNotLeaking() {
        Debug.MemoryInfo meminfoStart = new Debug.MemoryInfo();
        Debug.MemoryInfo meminfoEnd = new Debug.MemoryInfo();
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Config.HARDWARE;
        opts.inScaled = false;

        final ColorSpace colorSpace = ColorSpace.get(Named.SRGB);
        try (HardwareBuffer hwBuffer = createTestBuffer(128, 128, false)) {
            for (int i = 0; i < 2000; i++) {
                if (i == 2) {
                    // Not really the "start" but by having done a couple
                    // we've fully initialized any state that may be required,
                    // so memory usage should be stable now
                    runGcAndFinalizersSync();
                    Debug.getMemoryInfo(meminfoStart);
                }
                if (i % 100 == 5) {
                    assertNotLeaking(i, meminfoStart, meminfoEnd);
                }
                Bitmap bitmap = Bitmap.wrapHardwareBuffer(hwBuffer, colorSpace);
                assertNotNull(bitmap);
                // Make sure nothing messed with the bitmap
                assertEquals(128, bitmap.getWidth());
                assertEquals(128, bitmap.getHeight());
                assertEquals(Config.HARDWARE, bitmap.getConfig());
                bitmap.recycle();
            }
        }

        assertNotLeaking(2000, meminfoStart, meminfoEnd);
    }

    @Test
    @LargeTest
    public void testDrawingHardwareBitmapNotLeaking() {
        Debug.MemoryInfo meminfoStart = new Debug.MemoryInfo();
        Debug.MemoryInfo meminfoEnd = new Debug.MemoryInfo();
        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();

        for (int i = 0; i < 2000; i++) {
            if (i == 2) {
                // Not really the "start" but by having done a couple
                // we've fully initialized any state that may be required,
                // so memory usage should be stable now
                runGcAndFinalizersSync();
                Debug.getMemoryInfo(meminfoStart);
            }
            if (i % 100 == 5) {
                assertNotLeaking(i, meminfoStart, meminfoEnd);
            }
            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();
        }

        assertNotLeaking(2000, meminfoStart, meminfoEnd);
    }

    @Test
    public void testWrapHardwareBufferHoldsReference() {
        RenderTarget renderTarget = RenderTarget.create();
        renderTarget.setDefaultSize(128, 128);
        final Surface surface = renderTarget.getSurface();
        Bitmap bitmap = null;

        // Create hardware-buffer and wrap it in a Bitmap
        try (HardwareBuffer hwBuffer = createTestBuffer(128, 128, false)) {
            // Fill buffer with colors (x, y, 42, 255)
            nFillRgbaHwBuffer(hwBuffer);
            bitmap = Bitmap.wrapHardwareBuffer(hwBuffer, ColorSpace.get(Named.SRGB));
        }

        // Buffer is closed at this point. Ensure bitmap still works by drawing it
        assertEquals(128, bitmap.getWidth());
        assertEquals(128, bitmap.getHeight());
        assertEquals(Config.HARDWARE, bitmap.getConfig());

        // Copy bitmap to target bitmap we can read from
        Bitmap dstBitmap = bitmap.copy(Config.ARGB_8888, false);
        bitmap.recycle();

        // Ensure that the bitmap has valid contents
        int pixel = dstBitmap.getPixel(0, 0);
        assertEquals(255 << 24 | 42, pixel);
        dstBitmap.recycle();
    }

    @Test
    public void testWrapHardwareBufferPreservesColors() {
        try (HardwareBuffer hwBuffer = createTestBuffer(128, 128, true)) {
            // Fill buffer with colors (x, y, 42, 255)
            nFillRgbaHwBuffer(hwBuffer);

            // Create HW bitmap from this buffer
            Bitmap srcBitmap = Bitmap.wrapHardwareBuffer(hwBuffer, ColorSpace.get(Named.SRGB));
            assertNotNull(srcBitmap);

            // Copy it to target non-HW bitmap
            Bitmap dstBitmap = srcBitmap.copy(Config.ARGB_8888, false);
            srcBitmap.recycle();

            // Ensure all colors are as expected (matches the nFillRgbaHwBuffer call used above).
            for (int y = 0; y < 128; ++y) {
                for (int x = 0; x < 128; ++x) {
                    int pixel = dstBitmap.getPixel(x, y);
                    short a = 255;
                    short r = (short) (x % 255);
                    short g = (short) (y % 255);
                    short b = 42;
                    assertEquals(a << 24 | r << 16 | g << 8 | b, pixel);
                }
            }
            dstBitmap.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 native void nFillRgbaHwBuffer(HardwareBuffer hwBuffer);

    private static HardwareBuffer createTestBuffer(int width, int height, boolean cpuAccess) {
        long usage = HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE;
        if (cpuAccess) {
            usage |= HardwareBuffer.USAGE_CPU_WRITE_RARELY;
        }
        // We can assume that RGBA_8888 format is supported for every platform.
        HardwareBuffer hwBuffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
                1, usage);
        return hwBuffer;
    }

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