1#define LOG_TAG "Bitmap"
2#include "Bitmap.h"
3
4#include "GraphicBuffer.h"
5#include "SkBitmap.h"
6#include "SkPixelRef.h"
7#include "SkImageEncoder.h"
8#include "SkImageInfo.h"
9#include "SkColor.h"
10#include "SkColorPriv.h"
11#include "SkColorSpace.h"
12#include "SkColorSpaceXform.h"
13#include "SkHalf.h"
14#include "SkMatrix44.h"
15#include "SkPM4f.h"
16#include "SkPM4fPriv.h"
17#include "GraphicsJNI.h"
18#include "SkDither.h"
19#include "SkUnPreMultiply.h"
20#include "SkStream.h"
21
22#include <binder/Parcel.h>
23#include "android_os_Parcel.h"
24#include "android_util_Binder.h"
25#include "android_nio_utils.h"
26#include "CreateJavaOutputStreamAdaptor.h"
27#include <hwui/Paint.h>
28#include <hwui/Bitmap.h>
29#include <renderthread/RenderProxy.h>
30
31#include "core_jni_helpers.h"
32
33#include <jni.h>
34#include <string.h>
35#include <memory>
36#include <string>
37
38#define DEBUG_PARCEL 0
39#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
40
41static jclass   gBitmap_class;
42static jfieldID gBitmap_nativePtr;
43static jmethodID gBitmap_constructorMethodID;
44static jmethodID gBitmap_reinitMethodID;
45static jmethodID gBitmap_getAllocationByteCountMethodID;
46
47namespace android {
48
49class BitmapWrapper {
50public:
51    BitmapWrapper(Bitmap* bitmap)
52        : mBitmap(bitmap) { }
53
54    void freePixels() {
55        mInfo = mBitmap->info();
56        mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
57        mAllocationSize = mBitmap->getAllocationByteCount();
58        mRowBytes = mBitmap->rowBytes();
59        mGenerationId = mBitmap->getGenerationID();
60        mIsHardware = mBitmap->isHardware();
61        mBitmap.reset();
62    }
63
64    bool valid() {
65        return mBitmap;
66    }
67
68    Bitmap& bitmap() {
69        assertValid();
70        return *mBitmap;
71    }
72
73    void assertValid() {
74        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
75    }
76
77    void getSkBitmap(SkBitmap* outBitmap) {
78        assertValid();
79        mBitmap->getSkBitmap(outBitmap);
80    }
81
82    bool hasHardwareMipMap() {
83        if (mBitmap) {
84            return mBitmap->hasHardwareMipMap();
85        }
86        return mHasHardwareMipMap;
87    }
88
89    void setHasHardwareMipMap(bool hasMipMap) {
90        assertValid();
91        mBitmap->setHasHardwareMipMap(hasMipMap);
92    }
93
94    void setAlphaType(SkAlphaType alphaType) {
95        assertValid();
96        mBitmap->setAlphaType(alphaType);
97    }
98
99    const SkImageInfo& info() {
100        if (mBitmap) {
101            return mBitmap->info();
102        }
103        return mInfo;
104    }
105
106    size_t getAllocationByteCount() const {
107        if (mBitmap) {
108            return mBitmap->getAllocationByteCount();
109        }
110        return mAllocationSize;
111    }
112
113    size_t rowBytes() const {
114        if (mBitmap) {
115            return mBitmap->rowBytes();
116        }
117        return mRowBytes;
118    }
119
120    uint32_t getGenerationID() const {
121        if (mBitmap) {
122            return mBitmap->getGenerationID();
123        }
124        return mGenerationId;
125    }
126
127    bool isHardware() {
128        if (mBitmap) {
129            return mBitmap->isHardware();
130        }
131        return mIsHardware;
132    }
133
134    ~BitmapWrapper() { }
135
136private:
137    sk_sp<Bitmap> mBitmap;
138    SkImageInfo mInfo;
139    bool mHasHardwareMipMap;
140    size_t mAllocationSize;
141    size_t mRowBytes;
142    uint32_t mGenerationId;
143    bool mIsHardware;
144};
145
146// Convenience class that does not take a global ref on the pixels, relying
147// on the caller already having a local JNI ref
148class LocalScopedBitmap {
149public:
150    explicit LocalScopedBitmap(jlong bitmapHandle)
151            : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
152
153    BitmapWrapper* operator->() {
154        return mBitmapWrapper;
155    }
156
157    void* pixels() {
158        return mBitmapWrapper->bitmap().pixels();
159    }
160
161    bool valid() {
162        return mBitmapWrapper && mBitmapWrapper->valid();
163    }
164
165private:
166    BitmapWrapper* mBitmapWrapper;
167};
168
169namespace bitmap {
170
171// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
172static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
173    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
174    // irrelevant. This just tests to ensure that the SkAlphaType is not
175    // opposite of isPremultiplied.
176    if (isPremultiplied) {
177        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
178    } else {
179        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
180    }
181}
182
183void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
184        bool isPremultiplied)
185{
186    // The caller needs to have already set the alpha type properly, so the
187    // native SkBitmap stays in sync with the Java Bitmap.
188    assert_premultiplied(info, isPremultiplied);
189
190    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
191            info.width(), info.height(), isPremultiplied);
192}
193
194int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
195{
196    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
197}
198
199jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
200        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
201        int density) {
202    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
203    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
204    // The caller needs to have already set the alpha type properly, so the
205    // native SkBitmap stays in sync with the Java Bitmap.
206    assert_premultiplied(bitmap->info(), isPremultiplied);
207    BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
208    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
209            reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
210            isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
211
212    if (env->ExceptionCheck() != 0) {
213        ALOGE("*** Uncaught exception returned from Java call!\n");
214        env->ExceptionDescribe();
215    }
216    return obj;
217}
218
219void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
220    LocalScopedBitmap bitmap(bitmapHandle);
221    bitmap->getSkBitmap(outBitmap);
222}
223
224Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
225    SkASSERT(env);
226    SkASSERT(bitmap);
227    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
228    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
229    LocalScopedBitmap localBitmap(bitmapHandle);
230    return localBitmap->bitmap();
231}
232
233Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
234    SkASSERT(env);
235    LocalScopedBitmap localBitmap(bitmapHandle);
236    return localBitmap->bitmap();
237}
238
239void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
240    SkASSERT(info);
241    SkASSERT(env);
242    SkASSERT(bitmap);
243    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
244    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
245    LocalScopedBitmap localBitmap(bitmapHandle);
246
247    const SkImageInfo& imageInfo = localBitmap->info();
248    info->width = imageInfo.width();
249    info->height = imageInfo.height();
250    info->stride = localBitmap->rowBytes();
251    info->flags = 0;
252    switch (imageInfo.colorType()) {
253        case kN32_SkColorType:
254            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
255            break;
256        case kRGB_565_SkColorType:
257            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
258            break;
259        case kARGB_4444_SkColorType:
260            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
261            break;
262        case kAlpha_8_SkColorType:
263            info->format = ANDROID_BITMAP_FORMAT_A_8;
264            break;
265        default:
266            info->format = ANDROID_BITMAP_FORMAT_NONE;
267            break;
268    }
269}
270
271void* lockPixels(JNIEnv* env, jobject bitmap) {
272    SkASSERT(env);
273    SkASSERT(bitmap);
274    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
275    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
276
277    LocalScopedBitmap localBitmap(bitmapHandle);
278    if (!localBitmap->valid()) return nullptr;
279
280    SkPixelRef& pixelRef = localBitmap->bitmap();
281    pixelRef.lockPixels();
282    if (!pixelRef.pixels()) {
283        pixelRef.unlockPixels();
284        return nullptr;
285    }
286    pixelRef.ref();
287    return pixelRef.pixels();
288}
289
290bool unlockPixels(JNIEnv* env, jobject bitmap) {
291    SkASSERT(env);
292    SkASSERT(bitmap);
293    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
294    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
295
296    LocalScopedBitmap localBitmap(bitmapHandle);
297    if (!localBitmap->valid()) return false;
298
299    SkPixelRef& pixelRef = localBitmap->bitmap();
300    pixelRef.notifyPixelsChanged();
301    pixelRef.unlockPixels();
302    pixelRef.unref();
303    return true;
304}
305
306} // namespace bitmap
307
308} // namespace android
309
310using namespace android;
311using namespace android::bitmap;
312
313///////////////////////////////////////////////////////////////////////////////
314// Conversions to/from SkColor, for get/setPixels, and the create method, which
315// is basically like setPixels
316
317typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
318                              int x, int y);
319
320static void FromColor_F16(void* dst, const SkColor src[], int width,
321                          int, int) {
322    uint64_t* d = (uint64_t*)dst;
323
324    for (int i = 0; i < width; i++) {
325        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
326    }
327}
328
329static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
330                          int, int) {
331    uint64_t* d = (uint64_t*)dst;
332
333    for (int i = 0; i < width; i++) {
334        const float* color = SkColor4f::FromColor(*src++).vec();
335        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
336        for (int i = 0; i < 4; ++i) {
337            scratch[i] = SkFloatToHalf(color[i]);
338        }
339    }
340}
341
342static void FromColor_D32(void* dst, const SkColor src[], int width,
343                          int, int) {
344    SkPMColor* d = (SkPMColor*)dst;
345
346    for (int i = 0; i < width; i++) {
347        *d++ = SkPreMultiplyColor(*src++);
348    }
349}
350
351static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
352                          int, int) {
353    // Needed to thwart the unreachable code detection from clang.
354    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
355
356    // SkColor's ordering may be different from SkPMColor
357    if (sk_color_ne_zero) {
358        memcpy(dst, src, width * sizeof(SkColor));
359        return;
360    }
361
362    // order isn't same, repack each pixel manually
363    SkPMColor* d = (SkPMColor*)dst;
364    for (int i = 0; i < width; i++) {
365        SkColor c = *src++;
366        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
367                                   SkColorGetG(c), SkColorGetB(c));
368    }
369}
370
371static void FromColor_D565(void* dst, const SkColor src[], int width,
372                           int x, int y) {
373    uint16_t* d = (uint16_t*)dst;
374
375    DITHER_565_SCAN(y);
376    for (int stop = x + width; x < stop; x++) {
377        SkColor c = *src++;
378        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
379                                DITHER_VALUE(x));
380    }
381}
382
383static void FromColor_D4444(void* dst, const SkColor src[], int width,
384                            int x, int y) {
385    SkPMColor16* d = (SkPMColor16*)dst;
386
387    DITHER_4444_SCAN(y);
388    for (int stop = x + width; x < stop; x++) {
389        SkPMColor pmc = SkPreMultiplyColor(*src++);
390        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
391//        *d++ = SkPixel32ToPixel4444(pmc);
392    }
393}
394
395static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
396                            int x, int y) {
397    SkPMColor16* d = (SkPMColor16*)dst;
398
399    DITHER_4444_SCAN(y);
400    for (int stop = x + width; x < stop; x++) {
401        SkColor c = *src++;
402
403        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
404        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
405                                            SkColorGetG(c), SkColorGetB(c));
406        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
407//        *d++ = SkPixel32ToPixel4444(pmc);
408    }
409}
410
411static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
412    uint8_t* d = (uint8_t*)dst;
413
414    for (int stop = x + width; x < stop; x++) {
415        *d++ = SkColorGetA(*src++);
416    }
417}
418
419// can return NULL
420static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
421    switch (bitmap.colorType()) {
422        case kN32_SkColorType:
423            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
424        case kARGB_4444_SkColorType:
425            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
426                    FromColor_D4444_Raw;
427        case kRGB_565_SkColorType:
428            return FromColor_D565;
429        case kAlpha_8_SkColorType:
430            return FromColor_DA8;
431        case kRGBA_F16_SkColorType:
432            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
433        default:
434            break;
435    }
436    return NULL;
437}
438
439bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
440        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
441    SkAutoLockPixels alp(dstBitmap);
442    void* dst = dstBitmap.getPixels();
443    FromColorProc proc = ChooseFromColorProc(dstBitmap);
444
445    if (NULL == dst || NULL == proc) {
446        return false;
447    }
448
449    const jint* array = env->GetIntArrayElements(srcColors, NULL);
450    const SkColor* src = (const SkColor*)array + srcOffset;
451
452    // reset to to actual choice from caller
453    dst = dstBitmap.getAddr(x, y);
454
455    SkColorSpace* colorSpace = dstBitmap.colorSpace();
456    if (dstBitmap.colorType() == kRGBA_F16_SkColorType ||
457            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
458        // now copy/convert each scanline
459        for (int y = 0; y < height; y++) {
460            proc(dst, src, width, x, y);
461            src += srcStride;
462            dst = (char*)dst + dstBitmap.rowBytes();
463        }
464    } else {
465        auto sRGB = SkColorSpace::MakeSRGB();
466        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
467
468        std::unique_ptr<SkColor[]> row(new SkColor[width]);
469
470        // now copy/convert each scanline
471        for (int y = 0; y < height; y++) {
472            memcpy(row.get(), src, sizeof(SkColor) * width);
473            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
474                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
475                    SkAlphaType::kUnpremul_SkAlphaType);
476
477            proc(dst, row.get(), width, x, y);
478            src += srcStride;
479            dst = (char*)dst + dstBitmap.rowBytes();
480        }
481    }
482
483    dstBitmap.notifyPixelsChanged();
484
485    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
486    return true;
487}
488
489//////////////////// ToColor procs
490
491typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
492                            SkColorTable*);
493
494static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
495                              SkColorTable*) {
496    SkASSERT(width > 0);
497    uint64_t* s = (uint64_t*)src;
498    do {
499        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
500    } while (--width != 0);
501}
502
503static void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
504                            SkColorTable*) {
505    SkASSERT(width > 0);
506    uint64_t* s = (uint64_t*)src;
507    do {
508        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
509    } while (--width != 0);
510}
511
512static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
513                              SkColorTable*) {
514    SkASSERT(width > 0);
515    const SkPMColor* s = (const SkPMColor*)src;
516    do {
517        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
518    } while (--width != 0);
519}
520
521static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
522                              SkColorTable*) {
523    SkASSERT(width > 0);
524    const SkPMColor* s = (const SkPMColor*)src;
525    do {
526        SkPMColor c = *s++;
527        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
528                                SkGetPackedG32(c), SkGetPackedB32(c));
529    } while (--width != 0);
530}
531
532static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
533                               SkColorTable*) {
534    SkASSERT(width > 0);
535    const SkPMColor* s = (const SkPMColor*)src;
536    do {
537        SkPMColor c = *s++;
538        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
539                               SkGetPackedB32(c));
540    } while (--width != 0);
541}
542
543static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
544                                SkColorTable*) {
545    SkASSERT(width > 0);
546    const SkPMColor16* s = (const SkPMColor16*)src;
547    do {
548        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
549    } while (--width != 0);
550}
551
552static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
553                                SkColorTable*) {
554    SkASSERT(width > 0);
555    const SkPMColor16* s = (const SkPMColor16*)src;
556    do {
557        SkPMColor c = SkPixel4444ToPixel32(*s++);
558        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
559                                SkGetPackedG32(c), SkGetPackedB32(c));
560    } while (--width != 0);
561}
562
563static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
564                                 SkColorTable*) {
565    SkASSERT(width > 0);
566    const SkPMColor16* s = (const SkPMColor16*)src;
567    do {
568        SkPMColor c = SkPixel4444ToPixel32(*s++);
569        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
570                               SkGetPackedB32(c));
571    } while (--width != 0);
572}
573
574static void ToColor_S565(SkColor dst[], const void* src, int width,
575                         SkColorTable*) {
576    SkASSERT(width > 0);
577    const uint16_t* s = (const uint16_t*)src;
578    do {
579        uint16_t c = *s++;
580        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
581                                SkPacked16ToB32(c));
582    } while (--width != 0);
583}
584
585static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
586                              SkColorTable* ctable) {
587    SkASSERT(width > 0);
588    const uint8_t* s = (const uint8_t*)src;
589    const SkPMColor* colors = ctable->readColors();
590    do {
591        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
592    } while (--width != 0);
593}
594
595static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
596                              SkColorTable* ctable) {
597    SkASSERT(width > 0);
598    const uint8_t* s = (const uint8_t*)src;
599    const SkPMColor* colors = ctable->readColors();
600    do {
601        SkPMColor c = colors[*s++];
602        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
603                                SkGetPackedG32(c), SkGetPackedB32(c));
604    } while (--width != 0);
605}
606
607static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
608                               SkColorTable* ctable) {
609    SkASSERT(width > 0);
610    const uint8_t* s = (const uint8_t*)src;
611    const SkPMColor* colors = ctable->readColors();
612    do {
613        SkPMColor c = colors[*s++];
614        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
615                               SkGetPackedB32(c));
616    } while (--width != 0);
617}
618
619static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
620    SkASSERT(width > 0);
621    const uint8_t* s = (const uint8_t*)src;
622    do {
623        uint8_t c = *s++;
624        *dst++ = SkColorSetARGB(c, 0, 0, 0);
625    } while (--width != 0);
626}
627
628// can return NULL
629static ToColorProc ChooseToColorProc(const SkBitmap& src) {
630    switch (src.colorType()) {
631        case kN32_SkColorType:
632            switch (src.alphaType()) {
633                case kOpaque_SkAlphaType:
634                    return ToColor_S32_Opaque;
635                case kPremul_SkAlphaType:
636                    return ToColor_S32_Alpha;
637                case kUnpremul_SkAlphaType:
638                    return ToColor_S32_Raw;
639                default:
640                    return NULL;
641            }
642        case kARGB_4444_SkColorType:
643            switch (src.alphaType()) {
644                case kOpaque_SkAlphaType:
645                    return ToColor_S4444_Opaque;
646                case kPremul_SkAlphaType:
647                    return ToColor_S4444_Alpha;
648                case kUnpremul_SkAlphaType:
649                    return ToColor_S4444_Raw;
650                default:
651                    return NULL;
652            }
653        case kRGB_565_SkColorType:
654            return ToColor_S565;
655        case kIndex_8_SkColorType:
656            if (src.getColorTable() == NULL) {
657                return NULL;
658            }
659            switch (src.alphaType()) {
660                case kOpaque_SkAlphaType:
661                    return ToColor_SI8_Opaque;
662                case kPremul_SkAlphaType:
663                    return ToColor_SI8_Alpha;
664                case kUnpremul_SkAlphaType:
665                    return ToColor_SI8_Raw;
666                default:
667                    return NULL;
668            }
669        case kAlpha_8_SkColorType:
670            return ToColor_SA8;
671        case kRGBA_F16_SkColorType:
672            switch (src.alphaType()) {
673                case kOpaque_SkAlphaType:
674                    return ToColor_F16_Raw;
675                case kPremul_SkAlphaType:
676                    return ToColor_F16_Alpha;
677                case kUnpremul_SkAlphaType:
678                    return ToColor_F16_Raw;
679                default:
680                    return NULL;
681            }
682        default:
683            break;
684    }
685    return NULL;
686}
687
688static void ToF16_SA8(void* dst, const void* src, int width) {
689    SkASSERT(width > 0);
690    uint64_t* d = (uint64_t*)dst;
691    const uint8_t* s = (const uint8_t*)src;
692
693    for (int i = 0; i < width; i++) {
694        uint8_t c = *s++;
695        SkPM4f a;
696        a.fVec[SkPM4f::R] = 0.0f;
697        a.fVec[SkPM4f::G] = 0.0f;
698        a.fVec[SkPM4f::B] = 0.0f;
699        a.fVec[SkPM4f::A] = c / 255.0f;
700        *d++ = a.toF16();
701    }
702}
703
704///////////////////////////////////////////////////////////////////////////////
705///////////////////////////////////////////////////////////////////////////////
706
707static int getPremulBitmapCreateFlags(bool isMutable) {
708    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
709    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
710    return flags;
711}
712
713static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
714                              jint offset, jint stride, jint width, jint height,
715                              jint configHandle, jboolean isMutable,
716                              jfloatArray xyzD50, jobject transferParameters) {
717    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
718    if (NULL != jColors) {
719        size_t n = env->GetArrayLength(jColors);
720        if (n < SkAbs32(stride) * (size_t)height) {
721            doThrowAIOOBE(env);
722            return NULL;
723        }
724    }
725
726    // ARGB_4444 is a deprecated format, convert automatically to 8888
727    if (colorType == kARGB_4444_SkColorType) {
728        colorType = kN32_SkColorType;
729    }
730
731    SkBitmap bitmap;
732    sk_sp<SkColorSpace> colorSpace;
733
734    if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) {
735        colorSpace = GraphicsJNI::colorSpaceForType(colorType);
736    } else {
737        SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
738        SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
739        colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
740    }
741
742    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType, colorSpace));
743
744    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
745    if (!nativeBitmap) {
746        return NULL;
747    }
748
749    if (jColors != NULL) {
750        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
751    }
752
753    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
754}
755
756static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
757        SkBitmap::Allocator* alloc) {
758    // Skia does not support copying from kAlpha8 to types that are not alpha only.
759    // We will handle this case here.
760    if (kAlpha_8_SkColorType == src.colorType() && kAlpha_8_SkColorType != dstCT) {
761        SkAutoPixmapUnlock srcUnlocker;
762        if (!src.requestLock(&srcUnlocker)) {
763            return false;
764        }
765        SkPixmap srcPixmap = srcUnlocker.pixmap();
766
767        SkImageInfo dstInfo = src.info().makeColorType(dstCT);
768        if (dstCT == kRGBA_F16_SkColorType) {
769             dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear());
770        }
771        if (!dst->setInfo(dstInfo)) {
772            return false;
773        }
774        if (!dst->tryAllocPixels(alloc, nullptr)) {
775            return false;
776        }
777
778        switch (dstCT) {
779            case kRGBA_8888_SkColorType:
780            case kBGRA_8888_SkColorType: {
781                for (int y = 0; y < src.height(); y++) {
782                    const uint8_t* srcRow = srcPixmap.addr8(0, y);
783                    uint32_t* dstRow = dst->getAddr32(0, y);
784                    ToColor_SA8(dstRow, srcRow, src.width(), nullptr);
785                }
786                return true;
787            }
788            case kRGB_565_SkColorType: {
789                for (int y = 0; y < src.height(); y++) {
790                    uint16_t* dstRow = dst->getAddr16(0, y);
791                    memset(dstRow, 0, sizeof(uint16_t) * src.width());
792                }
793                return true;
794            }
795            case kRGBA_F16_SkColorType: {
796               for (int y = 0; y < src.height(); y++) {
797                   const uint8_t* srcRow = srcPixmap.addr8(0, y);
798                   void* dstRow = dst->getAddr(0, y);
799                   ToF16_SA8(dstRow, srcRow, src.width());
800               }
801               return true;
802           }
803            default:
804                return false;
805        }
806    }
807
808    return src.copyTo(dst, dstCT, alloc);
809}
810
811static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
812                           jint dstConfigHandle, jboolean isMutable) {
813    SkBitmap src;
814    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
815    if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
816        sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
817        if (!bitmap.get()) {
818            return NULL;
819        }
820        return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
821    }
822
823    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
824    SkBitmap result;
825    HeapAllocator allocator;
826
827    if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
828        return NULL;
829    }
830    auto bitmap = allocator.getStorageObjAndReset();
831    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
832}
833
834static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
835    SkBitmap result;
836
837    AshmemPixelAllocator allocator(env);
838    if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
839        return NULL;
840    }
841    auto bitmap = allocator.getStorageObjAndReset();
842    bitmap->setImmutable();
843    return bitmap;
844}
845
846static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
847    SkBitmap src;
848    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
849    SkColorType dstCT = src.colorType();
850    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
851    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
852    return ret;
853}
854
855static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
856    SkBitmap src;
857    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
858    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
859    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
860    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
861    return ret;
862}
863
864static void Bitmap_destruct(BitmapWrapper* bitmap) {
865    delete bitmap;
866}
867
868static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
869    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
870}
871
872static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
873    LocalScopedBitmap bitmap(bitmapHandle);
874    bitmap->freePixels();
875    return JNI_TRUE;
876}
877
878static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
879        jint width, jint height, jint configHandle, jboolean requestPremul) {
880    LocalScopedBitmap bitmap(bitmapHandle);
881    bitmap->assertValid();
882    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
883
884    // ARGB_4444 is a deprecated format, convert automatically to 8888
885    if (colorType == kARGB_4444_SkColorType) {
886        colorType = kN32_SkColorType;
887    }
888    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
889    if (requestedSize > bitmap->getAllocationByteCount()) {
890        // done in native as there's no way to get BytesPerPixel in Java
891        doThrowIAE(env, "Bitmap not large enough to support new configuration");
892        return;
893    }
894    SkAlphaType alphaType;
895    if (bitmap->info().colorType() != kRGB_565_SkColorType
896            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
897        // If the original bitmap was set to opaque, keep that setting, unless it
898        // was 565, which is required to be opaque.
899        alphaType = kOpaque_SkAlphaType;
900    } else {
901        // Otherwise respect the premultiplied request.
902        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
903    }
904    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
905            sk_ref_sp(bitmap->info().colorSpace())));
906}
907
908// These must match the int values in Bitmap.java
909enum JavaEncodeFormat {
910    kJPEG_JavaEncodeFormat = 0,
911    kPNG_JavaEncodeFormat = 1,
912    kWEBP_JavaEncodeFormat = 2
913};
914
915static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
916                                jint format, jint quality,
917                                jobject jstream, jbyteArray jstorage) {
918    SkEncodedImageFormat fm;
919    switch (format) {
920    case kJPEG_JavaEncodeFormat:
921        fm = SkEncodedImageFormat::kJPEG;
922        break;
923    case kPNG_JavaEncodeFormat:
924        fm = SkEncodedImageFormat::kPNG;
925        break;
926    case kWEBP_JavaEncodeFormat:
927        fm = SkEncodedImageFormat::kWEBP;
928        break;
929    default:
930        return JNI_FALSE;
931    }
932
933    LocalScopedBitmap bitmap(bitmapHandle);
934    if (!bitmap.valid()) {
935        return JNI_FALSE;
936    }
937
938    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
939    if (!strm.get()) {
940        return JNI_FALSE;
941    }
942
943    SkBitmap skbitmap;
944    bitmap->getSkBitmap(&skbitmap);
945    return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
946}
947
948static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
949    LocalScopedBitmap bitmap(bitmapHandle);
950    SkBitmap skBitmap;
951    bitmap->getSkBitmap(&skBitmap);
952    skBitmap.eraseColor(color);
953}
954
955static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
956    LocalScopedBitmap bitmap(bitmapHandle);
957    return static_cast<jint>(bitmap->rowBytes());
958}
959
960static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
961    LocalScopedBitmap bitmap(bitmapHandle);
962    if (bitmap->isHardware()) {
963        return GraphicsJNI::hardwareLegacyBitmapConfig();
964    }
965    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
966}
967
968static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
969    LocalScopedBitmap bitmap(bitmapHandle);
970    return static_cast<jint>(bitmap->getGenerationID());
971}
972
973static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
974    LocalScopedBitmap bitmap(bitmapHandle);
975    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
976        return JNI_TRUE;
977    }
978    return JNI_FALSE;
979}
980
981static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
982    LocalScopedBitmap bitmap(bitmapHandle);
983    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
984}
985
986static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
987        jboolean hasAlpha, jboolean requestPremul) {
988    LocalScopedBitmap bitmap(bitmapHandle);
989    if (hasAlpha) {
990        bitmap->setAlphaType(
991                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
992    } else {
993        bitmap->setAlphaType(kOpaque_SkAlphaType);
994    }
995}
996
997static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
998        jboolean isPremul) {
999    LocalScopedBitmap bitmap(bitmapHandle);
1000    if (!bitmap->info().isOpaque()) {
1001        if (isPremul) {
1002            bitmap->setAlphaType(kPremul_SkAlphaType);
1003        } else {
1004            bitmap->setAlphaType(kUnpremul_SkAlphaType);
1005        }
1006    }
1007}
1008
1009static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
1010    LocalScopedBitmap bitmap(bitmapHandle);
1011    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
1012}
1013
1014static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
1015                                jboolean hasMipMap) {
1016    LocalScopedBitmap bitmap(bitmapHandle);
1017    bitmap->setHasHardwareMipMap(hasMipMap);
1018}
1019
1020///////////////////////////////////////////////////////////////////////////////
1021
1022// This is the maximum possible size because the SkColorSpace must be
1023// representable (and therefore serializable) using a matrix and numerical
1024// transfer function.  If we allow more color space representations in the
1025// framework, we may need to update this maximum size.
1026static constexpr uint32_t kMaxColorSpaceSerializedBytes = 80;
1027
1028static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
1029    if (parcel == NULL) {
1030        SkDebugf("-------- unparcel parcel is NULL\n");
1031        return NULL;
1032    }
1033
1034    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1035
1036    const bool        isMutable = p->readInt32() != 0;
1037    const SkColorType colorType = (SkColorType)p->readInt32();
1038    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
1039    const uint32_t    colorSpaceSize = p->readUint32();
1040    sk_sp<SkColorSpace> colorSpace;
1041    if (kRGBA_F16_SkColorType == colorType) {
1042        colorSpace = SkColorSpace::MakeSRGBLinear();
1043    } else if (colorSpaceSize > 0) {
1044        if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
1045            ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
1046                    "%d bytes\n", colorSpaceSize);
1047        }
1048
1049        const void* data = p->readInplace(colorSpaceSize);
1050        if (data) {
1051            colorSpace = SkColorSpace::Deserialize(data, colorSpaceSize);
1052        } else {
1053            ALOGD("Bitmap_createFromParcel: Unable to read serialized SkColorSpace data\n");
1054        }
1055    }
1056    const int         width = p->readInt32();
1057    const int         height = p->readInt32();
1058    const int         rowBytes = p->readInt32();
1059    const int         density = p->readInt32();
1060
1061    if (kN32_SkColorType != colorType &&
1062            kRGBA_F16_SkColorType != colorType &&
1063            kRGB_565_SkColorType != colorType &&
1064            kARGB_4444_SkColorType != colorType &&
1065            kIndex_8_SkColorType != colorType &&
1066            kAlpha_8_SkColorType != colorType) {
1067        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
1068        return NULL;
1069    }
1070
1071    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
1072    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
1073            rowBytes)) {
1074        return NULL;
1075    }
1076
1077    SkColorTable* ctable = NULL;
1078    if (colorType == kIndex_8_SkColorType) {
1079        int count = p->readInt32();
1080        if (count < 0 || count > 256) {
1081            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
1082            // inclusive.
1083            return NULL;
1084        }
1085        if (count > 0) {
1086            size_t size = count * sizeof(SkPMColor);
1087            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
1088            if (src == NULL) {
1089                return NULL;
1090            }
1091            ctable = new SkColorTable(src, count);
1092        }
1093    }
1094
1095    // Read the bitmap blob.
1096    size_t size = bitmap->getSize();
1097    android::Parcel::ReadableBlob blob;
1098    android::status_t status = p->readBlob(size, &blob);
1099    if (status) {
1100        SkSafeUnref(ctable);
1101        doThrowRE(env, "Could not read bitmap blob.");
1102        return NULL;
1103    }
1104
1105    // Map the bitmap in place from the ashmem region if possible otherwise copy.
1106    sk_sp<Bitmap> nativeBitmap;
1107    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
1108#if DEBUG_PARCEL
1109        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
1110                "(fds %s)",
1111                isMutable ? "mutable" : "immutable",
1112                blob.isMutable() ? "mutable" : "immutable",
1113                p->allowFds() ? "allowed" : "forbidden");
1114#endif
1115        // Dup the file descriptor so we can keep a reference to it after the Parcel
1116        // is disposed.
1117        int dupFd = dup(blob.fd());
1118        if (dupFd < 0) {
1119            ALOGE("Error allocating dup fd. Error:%d", errno);
1120            blob.release();
1121            SkSafeUnref(ctable);
1122            doThrowRE(env, "Could not allocate dup blob fd.");
1123            return NULL;
1124        }
1125
1126        // Map the pixels in place and take ownership of the ashmem region.
1127        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
1128                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
1129        SkSafeUnref(ctable);
1130        if (!nativeBitmap) {
1131            close(dupFd);
1132            blob.release();
1133            doThrowRE(env, "Could not allocate ashmem pixel ref.");
1134            return NULL;
1135        }
1136
1137        // Clear the blob handle, don't release it.
1138        blob.clear();
1139    } else {
1140#if DEBUG_PARCEL
1141        if (blob.fd() >= 0) {
1142            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
1143                    "from immutable blob (fds %s)",
1144                    p->allowFds() ? "allowed" : "forbidden");
1145        } else {
1146            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
1147                    "(fds %s)",
1148                    blob.isMutable() ? "mutable" : "immutable",
1149                    p->allowFds() ? "allowed" : "forbidden");
1150        }
1151#endif
1152
1153        // Copy the pixels into a new buffer.
1154        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
1155        SkSafeUnref(ctable);
1156        if (!nativeBitmap) {
1157            blob.release();
1158            doThrowRE(env, "Could not allocate java pixel ref.");
1159            return NULL;
1160        }
1161        bitmap->lockPixels();
1162        memcpy(bitmap->getPixels(), blob.data(), size);
1163        bitmap->unlockPixels();
1164
1165        // Release the blob handle.
1166        blob.release();
1167    }
1168
1169    return createBitmap(env, nativeBitmap.release(),
1170            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
1171}
1172
1173static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
1174                                     jlong bitmapHandle,
1175                                     jboolean isMutable, jint density,
1176                                     jobject parcel) {
1177    if (parcel == NULL) {
1178        SkDebugf("------- writeToParcel null parcel\n");
1179        return JNI_FALSE;
1180    }
1181
1182    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1183    SkBitmap bitmap;
1184
1185    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
1186    bitmapWrapper->getSkBitmap(&bitmap);
1187
1188    p->writeInt32(isMutable);
1189    p->writeInt32(bitmap.colorType());
1190    p->writeInt32(bitmap.alphaType());
1191    SkColorSpace* colorSpace = bitmap.colorSpace();
1192    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
1193        sk_sp<SkData> data = colorSpace->serialize();
1194        size_t size = data->size();
1195        p->writeUint32(size);
1196        if (size > 0) {
1197            if (size > kMaxColorSpaceSerializedBytes) {
1198                ALOGD("Bitmap_writeToParcel: Serialized SkColorSpace is larger than expected: "
1199                        "%zu bytes\n", size);
1200            }
1201
1202            p->write(data->data(), size);
1203        }
1204    } else {
1205        p->writeUint32(0);
1206    }
1207    p->writeInt32(bitmap.width());
1208    p->writeInt32(bitmap.height());
1209    p->writeInt32(bitmap.rowBytes());
1210    p->writeInt32(density);
1211
1212    if (bitmap.colorType() == kIndex_8_SkColorType) {
1213        // The bitmap needs to be locked to access its color table.
1214        SkAutoLockPixels alp(bitmap);
1215        SkColorTable* ctable = bitmap.getColorTable();
1216        if (ctable != NULL) {
1217            int count = ctable->count();
1218            p->writeInt32(count);
1219            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
1220                   ctable->readColors(), count * sizeof(SkPMColor));
1221        } else {
1222            p->writeInt32(0);   // indicate no ctable
1223        }
1224    }
1225
1226    // Transfer the underlying ashmem region if we have one and it's immutable.
1227    android::status_t status;
1228    int fd = bitmapWrapper->bitmap().getAshmemFd();
1229    if (fd >= 0 && !isMutable && p->allowFds()) {
1230#if DEBUG_PARCEL
1231        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1232                "immutable blob (fds %s)",
1233                p->allowFds() ? "allowed" : "forbidden");
1234#endif
1235
1236        status = p->writeDupImmutableBlobFileDescriptor(fd);
1237        if (status) {
1238            doThrowRE(env, "Could not write bitmap blob file descriptor.");
1239            return JNI_FALSE;
1240        }
1241        return JNI_TRUE;
1242    }
1243
1244    // Copy the bitmap to a new blob.
1245    bool mutableCopy = isMutable;
1246#if DEBUG_PARCEL
1247    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1248            isMutable ? "mutable" : "immutable",
1249            mutableCopy ? "mutable" : "immutable",
1250            p->allowFds() ? "allowed" : "forbidden");
1251#endif
1252
1253    size_t size = bitmap.getSize();
1254    android::Parcel::WritableBlob blob;
1255    status = p->writeBlob(size, mutableCopy, &blob);
1256    if (status) {
1257        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1258        return JNI_FALSE;
1259    }
1260
1261    bitmap.lockPixels();
1262    const void* pSrc =  bitmap.getPixels();
1263    if (pSrc == NULL) {
1264        memset(blob.data(), 0, size);
1265    } else {
1266        memcpy(blob.data(), pSrc, size);
1267    }
1268    bitmap.unlockPixels();
1269
1270    blob.release();
1271    return JNI_TRUE;
1272}
1273
1274static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
1275                                   jlong srcHandle, jlong paintHandle,
1276                                   jintArray offsetXY) {
1277    SkBitmap src;
1278    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
1279    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
1280    SkIPoint  offset;
1281    SkBitmap dst;
1282    HeapAllocator allocator;
1283
1284    src.extractAlpha(&dst, paint, &allocator, &offset);
1285    // If Skia can't allocate pixels for destination bitmap, it resets
1286    // it, that is set its pixels buffer to NULL, and zero width and height.
1287    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
1288        doThrowOOME(env, "failed to allocate pixels for alpha");
1289        return NULL;
1290    }
1291    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1292        int* array = env->GetIntArrayElements(offsetXY, NULL);
1293        array[0] = offset.fX;
1294        array[1] = offset.fY;
1295        env->ReleaseIntArrayElements(offsetXY, array, 0);
1296    }
1297
1298    return createBitmap(env, allocator.getStorageObjAndReset(),
1299            getPremulBitmapCreateFlags(true));
1300}
1301
1302///////////////////////////////////////////////////////////////////////////////
1303
1304static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
1305    LocalScopedBitmap bitmapHolder(bitmapHandle);
1306    if (!bitmapHolder.valid()) return JNI_TRUE;
1307
1308    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1309    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
1310}
1311
1312static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
1313        jfloatArray xyzArray, jfloatArray paramsArray) {
1314
1315    LocalScopedBitmap bitmapHolder(bitmapHandle);
1316    if (!bitmapHolder.valid()) return JNI_FALSE;
1317
1318    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1319    if (colorSpace == nullptr) return JNI_FALSE;
1320
1321    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
1322    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
1323
1324    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
1325    xyz[0] = xyzMatrix.getFloat(0, 0);
1326    xyz[1] = xyzMatrix.getFloat(1, 0);
1327    xyz[2] = xyzMatrix.getFloat(2, 0);
1328    xyz[3] = xyzMatrix.getFloat(0, 1);
1329    xyz[4] = xyzMatrix.getFloat(1, 1);
1330    xyz[5] = xyzMatrix.getFloat(2, 1);
1331    xyz[6] = xyzMatrix.getFloat(0, 2);
1332    xyz[7] = xyzMatrix.getFloat(1, 2);
1333    xyz[8] = xyzMatrix.getFloat(2, 2);
1334    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
1335
1336    SkColorSpaceTransferFn transferParams;
1337    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
1338
1339    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
1340    params[0] = transferParams.fA;
1341    params[1] = transferParams.fB;
1342    params[2] = transferParams.fC;
1343    params[3] = transferParams.fD;
1344    params[4] = transferParams.fE;
1345    params[5] = transferParams.fF;
1346    params[6] = transferParams.fG;
1347    env->ReleaseFloatArrayElements(paramsArray, params, 0);
1348
1349    return JNI_TRUE;
1350}
1351
1352///////////////////////////////////////////////////////////////////////////////
1353
1354static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
1355        jint x, jint y) {
1356    SkBitmap bitmap;
1357    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1358    SkAutoLockPixels alp(bitmap);
1359
1360    ToColorProc proc = ChooseToColorProc(bitmap);
1361    if (NULL == proc) {
1362        return 0;
1363    }
1364    const void* src = bitmap.getAddr(x, y);
1365    if (NULL == src) {
1366        return 0;
1367    }
1368
1369    SkColor dst[1];
1370    proc(dst, src, 1, bitmap.getColorTable());
1371
1372    SkColorSpace* colorSpace = bitmap.colorSpace();
1373    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
1374            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1375        auto sRGB = SkColorSpace::MakeSRGB();
1376        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1377        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
1378                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
1379                SkAlphaType::kUnpremul_SkAlphaType);
1380    }
1381
1382    return static_cast<jint>(dst[0]);
1383}
1384
1385static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1386        jintArray pixelArray, jint offset, jint stride,
1387        jint x, jint y, jint width, jint height) {
1388    SkBitmap bitmap;
1389    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1390    SkAutoLockPixels alp(bitmap);
1391
1392    ToColorProc proc = ChooseToColorProc(bitmap);
1393    if (NULL == proc) {
1394        return;
1395    }
1396    const void* src = bitmap.getAddr(x, y);
1397    if (NULL == src) {
1398        return;
1399    }
1400
1401    SkColorTable* ctable = bitmap.getColorTable();
1402    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1403    SkColor* d = (SkColor*)dst + offset;
1404
1405    SkColorSpace* colorSpace = bitmap.colorSpace();
1406    if (bitmap.colorType() == kRGBA_F16_SkColorType ||
1407            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1408        while (--height >= 0) {
1409            proc(d, src, width, ctable);
1410            d += stride;
1411            src = (void*)((const char*)src + bitmap.rowBytes());
1412        }
1413    } else {
1414        auto sRGB = SkColorSpace::MakeSRGB();
1415        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1416
1417        while (--height >= 0) {
1418            proc(d, src, width, ctable);
1419
1420            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
1421                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
1422                    SkAlphaType::kUnpremul_SkAlphaType);
1423
1424            d += stride;
1425            src = (void*)((const char*)src + bitmap.rowBytes());
1426        }
1427    }
1428
1429    env->ReleaseIntArrayElements(pixelArray, dst, 0);
1430}
1431
1432///////////////////////////////////////////////////////////////////////////////
1433
1434static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
1435        jint x, jint y, jint colorHandle) {
1436    SkBitmap bitmap;
1437    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1438    SkColor color = static_cast<SkColor>(colorHandle);
1439    SkAutoLockPixels alp(bitmap);
1440    if (NULL == bitmap.getPixels()) {
1441        return;
1442    }
1443
1444    FromColorProc proc = ChooseFromColorProc(bitmap);
1445    if (NULL == proc) {
1446        return;
1447    }
1448
1449    SkColorSpace* colorSpace = bitmap.colorSpace();
1450    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
1451            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1452        auto sRGB = SkColorSpace::MakeSRGB();
1453        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
1454        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
1455                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
1456                SkAlphaType::kUnpremul_SkAlphaType);
1457    }
1458
1459    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1460    bitmap.notifyPixelsChanged();
1461}
1462
1463static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1464        jintArray pixelArray, jint offset, jint stride,
1465        jint x, jint y, jint width, jint height) {
1466    SkBitmap bitmap;
1467    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1468    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1469            x, y, width, height, bitmap);
1470}
1471
1472static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1473                                      jlong bitmapHandle, jobject jbuffer) {
1474    SkBitmap bitmap;
1475    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1476    SkAutoLockPixels alp(bitmap);
1477    const void* src = bitmap.getPixels();
1478
1479    if (NULL != src) {
1480        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1481
1482        // the java side has already checked that buffer is large enough
1483        memcpy(abp.pointer(), src, bitmap.getSize());
1484    }
1485}
1486
1487static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1488                                        jlong bitmapHandle, jobject jbuffer) {
1489    SkBitmap bitmap;
1490    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1491    SkAutoLockPixels alp(bitmap);
1492    void* dst = bitmap.getPixels();
1493
1494    if (NULL != dst) {
1495        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1496        // the java side has already checked that buffer is large enough
1497        memcpy(dst, abp.pointer(), bitmap.getSize());
1498        bitmap.notifyPixelsChanged();
1499    }
1500}
1501
1502static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
1503    SkBitmap bm0;
1504    SkBitmap bm1;
1505
1506    LocalScopedBitmap bitmap0(bm0Handle);
1507    LocalScopedBitmap bitmap1(bm1Handle);
1508
1509    // Paying the price for making Hardware Bitmap as Config:
1510    // later check for colorType will pass successfully,
1511    // because Hardware Config internally may be RGBA8888 or smth like that.
1512    if (bitmap0->isHardware() != bitmap1->isHardware()) {
1513        return JNI_FALSE;
1514    }
1515
1516    bitmap0->bitmap().getSkBitmap(&bm0);
1517    bitmap1->bitmap().getSkBitmap(&bm1);
1518    if (bm0.width() != bm1.width()
1519            || bm0.height() != bm1.height()
1520            || bm0.colorType() != bm1.colorType()
1521            || bm0.alphaType() != bm1.alphaType()
1522            || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
1523        return JNI_FALSE;
1524    }
1525
1526    SkAutoLockPixels alp0(bm0);
1527    SkAutoLockPixels alp1(bm1);
1528
1529    // if we can't load the pixels, return false
1530    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
1531        return JNI_FALSE;
1532    }
1533
1534    if (bm0.colorType() == kIndex_8_SkColorType) {
1535        SkColorTable* ct0 = bm0.getColorTable();
1536        SkColorTable* ct1 = bm1.getColorTable();
1537        if (NULL == ct0 || NULL == ct1) {
1538            return JNI_FALSE;
1539        }
1540        if (ct0->count() != ct1->count()) {
1541            return JNI_FALSE;
1542        }
1543
1544        const size_t size = ct0->count() * sizeof(SkPMColor);
1545        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
1546            return JNI_FALSE;
1547        }
1548    }
1549
1550    // now compare each scanline. We can't do the entire buffer at once,
1551    // since we don't care about the pixel values that might extend beyond
1552    // the width (since the scanline might be larger than the logical width)
1553    const int h = bm0.height();
1554    const size_t size = bm0.width() * bm0.bytesPerPixel();
1555    for (int y = 0; y < h; y++) {
1556        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1557        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1558        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1559        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1560        // to warn user those 2 unrecognized config bitmaps may be different.
1561        void *bm0Addr = bm0.getAddr(0, y);
1562        void *bm1Addr = bm1.getAddr(0, y);
1563
1564        if(bm0Addr == NULL || bm1Addr == NULL) {
1565            return JNI_FALSE;
1566        }
1567
1568        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
1569            return JNI_FALSE;
1570        }
1571    }
1572    return JNI_TRUE;
1573}
1574
1575static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1576    LocalScopedBitmap bitmapHandle(bitmapPtr);
1577    if (!bitmapHandle.valid()) return;
1578    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
1579}
1580
1581static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1582    LocalScopedBitmap bitmapHandle(bitmapPtr);
1583    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1584}
1585
1586static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
1587    LocalScopedBitmap bitmapHandle(bitmapPtr);
1588    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1589            "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
1590    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1591    SkBitmap src;
1592    hwuiBitmap.getSkBitmap(&src);
1593
1594    SkBitmap result;
1595    HeapAllocator allocator;
1596    if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
1597        doThrowRE(env, "Could not copy a hardware bitmap.");
1598        return NULL;
1599    }
1600    return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false));
1601}
1602
1603static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
1604    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
1605    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
1606    if (!bitmap.get()) {
1607        ALOGW("failed to create hardware bitmap from graphic buffer");
1608        return NULL;
1609    }
1610    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
1611}
1612
1613static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
1614    LocalScopedBitmap bitmapHandle(bitmapPtr);
1615    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
1616            "Hardware config is only supported config in Bitmap_getGraphicBuffer");
1617
1618    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
1619    sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
1620    return createJavaGraphicBuffer(env, buffer);
1621}
1622
1623static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) {
1624    LocalScopedBitmap srcBitmapHandle(srcBitmapPtr);
1625    LocalScopedBitmap dstBitmapHandle(dstBitmapPtr);
1626
1627    dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace());
1628}
1629
1630///////////////////////////////////////////////////////////////////////////////
1631
1632static const JNINativeMethod gBitmapMethods[] = {
1633    {   "nativeCreate",             "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
1634        (void*)Bitmap_creator },
1635    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
1636        (void*)Bitmap_copy },
1637    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1638        (void*)Bitmap_copyAshmem },
1639    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1640        (void*)Bitmap_copyAshmemConfig },
1641    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
1642    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
1643    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
1644    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
1645        (void*)Bitmap_compress },
1646    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
1647    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
1648    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
1649    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
1650    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
1651    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
1652    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
1653    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
1654    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
1655    {   "nativeCreateFromParcel",
1656        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1657        (void*)Bitmap_createFromParcel },
1658    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
1659        (void*)Bitmap_writeToParcel },
1660    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
1661        (void*)Bitmap_extractAlpha },
1662    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
1663    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
1664    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1665    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
1666    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
1667    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1668                                            (void*)Bitmap_copyPixelsToBuffer },
1669    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1670                                            (void*)Bitmap_copyPixelsFromBuffer },
1671    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
1672    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
1673    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
1674    {   "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
1675        (void*)Bitmap_copyPreserveInternalConfig },
1676    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
1677        (void*) Bitmap_createHardwareBitmap },
1678    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
1679        (void*) Bitmap_createGraphicBufferHandle },
1680    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
1681    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
1682    {   "nativeCopyColorSpace",     "(JJ)V",
1683        (void*)Bitmap_copyColorSpace },
1684};
1685
1686int register_android_graphics_Bitmap(JNIEnv* env)
1687{
1688    gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
1689    gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
1690    gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1691    gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
1692    gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I");
1693    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1694                                         NELEM(gBitmapMethods));
1695}
1696