• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "aassetstreamadaptor.h"
18 
19 #include <android/asset_manager.h>
20 #include <android/bitmap.h>
21 #include <android/data_space.h>
22 #include <android/imagedecoder.h>
23 #include <MimeType.h>
24 #include <android/rect.h>
25 #include <hwui/ImageDecoder.h>
26 #include <log/log.h>
27 #include <SkAndroidCodec.h>
28 #include <utils/Color.h>
29 
30 #include <fcntl.h>
31 #include <limits>
32 #include <optional>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 
37 using namespace android;
38 
ResultToErrorCode(SkCodec::Result result)39 int ResultToErrorCode(SkCodec::Result result) {
40     switch (result) {
41         case SkCodec::kIncompleteInput:
42             return ANDROID_IMAGE_DECODER_INCOMPLETE;
43         case SkCodec::kErrorInInput:
44             return ANDROID_IMAGE_DECODER_ERROR;
45         case SkCodec::kInvalidInput:
46             return ANDROID_IMAGE_DECODER_INVALID_INPUT;
47         case SkCodec::kCouldNotRewind:
48             return ANDROID_IMAGE_DECODER_SEEK_ERROR;
49         case SkCodec::kUnimplemented:
50             return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
51         case SkCodec::kInvalidConversion:
52             return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
53         case SkCodec::kInvalidParameters:
54             return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
55         case SkCodec::kSuccess:
56             return ANDROID_IMAGE_DECODER_SUCCESS;
57         case SkCodec::kInvalidScale:
58             return ANDROID_IMAGE_DECODER_INVALID_SCALE;
59         case SkCodec::kInternalError:
60             return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
61     }
62 }
63 
AImageDecoder_resultToString(int result)64 const char* AImageDecoder_resultToString(int result) {
65     switch (result) {
66         case        ANDROID_IMAGE_DECODER_SUCCESS:
67             return "ANDROID_IMAGE_DECODER_SUCCESS";
68         case        ANDROID_IMAGE_DECODER_INCOMPLETE:
69             return "ANDROID_IMAGE_DECODER_INCOMPLETE";
70         case        ANDROID_IMAGE_DECODER_ERROR:
71             return "ANDROID_IMAGE_DECODER_ERROR";
72         case        ANDROID_IMAGE_DECODER_INVALID_CONVERSION:
73             return "ANDROID_IMAGE_DECODER_INVALID_CONVERSION";
74         case        ANDROID_IMAGE_DECODER_INVALID_SCALE:
75             return "ANDROID_IMAGE_DECODER_INVALID_SCALE";
76         case        ANDROID_IMAGE_DECODER_BAD_PARAMETER:
77             return "ANDROID_IMAGE_DECODER_BAD_PARAMETER";
78         case        ANDROID_IMAGE_DECODER_INVALID_INPUT:
79             return "ANDROID_IMAGE_DECODER_INVALID_INPUT";
80         case        ANDROID_IMAGE_DECODER_SEEK_ERROR:
81             return "ANDROID_IMAGE_DECODER_SEEK_ERROR";
82         case        ANDROID_IMAGE_DECODER_INTERNAL_ERROR:
83             return "ANDROID_IMAGE_DECODER_INTERNAL_ERROR";
84         case        ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT:
85             return "ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT";
86         case        ANDROID_IMAGE_DECODER_FINISHED:
87             return "ANDROID_IMAGE_DECODER_FINISHED";
88         case        ANDROID_IMAGE_DECODER_INVALID_STATE:
89             return "ANDROID_IMAGE_DECODER_INVALID_STATE";
90         default:
91             return nullptr;
92     }
93 }
94 
createFromStream(std::unique_ptr<SkStreamRewindable> stream,AImageDecoder ** outDecoder)95 static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
96     SkCodec::Result result;
97     auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
98                                          SkCodec::SelectionPolicy::kPreferAnimation);
99     // These may be swapped due to the SkEncodedOrigin, but we're just checking
100     // them to make sure they fit in int32_t.
101     auto dimensions = codec->dimensions();
102     auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
103     if (!androidCodec) {
104         return ResultToErrorCode(result);
105     }
106 
107     // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
108     // the conversion is safe.
109     if (dimensions.width() > std::numeric_limits<int32_t>::max() ||
110         dimensions.height() > std::numeric_limits<int32_t>::max()) {
111         return ANDROID_IMAGE_DECODER_INVALID_INPUT;
112     }
113 
114     *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
115     return ANDROID_IMAGE_DECODER_SUCCESS;
116 }
117 
AImageDecoder_createFromAAsset(AAsset * asset,AImageDecoder ** outDecoder)118 int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
119     if (!asset || !outDecoder) {
120         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
121     }
122     *outDecoder = nullptr;
123 
124 #ifdef __ANDROID__
125     auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
126     return createFromStream(std::move(stream), outDecoder);
127 #else
128     return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
129 #endif
130 }
131 
isSeekable(int descriptor)132 static bool isSeekable(int descriptor) {
133     return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
134 }
135 
AImageDecoder_createFromFd(int fd,AImageDecoder ** outDecoder)136 int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
137     if (fd <= 0 || !outDecoder) {
138         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
139     }
140 
141     struct stat fdStat;
142     if (fstat(fd, &fdStat) == -1) {
143         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
144     }
145 
146     if (!isSeekable(fd)) {
147         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
148     }
149 
150     // SkFILEStream will close its descriptor. Duplicate it so the client will
151     // still be responsible for closing the original.
152     int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
153     FILE* file = fdopen(dupDescriptor, "r");
154     if (!file) {
155         close(dupDescriptor);
156         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
157     }
158 
159     auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
160     return createFromStream(std::move(stream), outDecoder);
161 }
162 
AImageDecoder_createFromBuffer(const void * buffer,size_t length,AImageDecoder ** outDecoder)163 int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
164                                    AImageDecoder** outDecoder) {
165     if (!buffer || !length  || !outDecoder) {
166         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
167     }
168     *outDecoder = nullptr;
169 
170     // The client is expected to keep the buffer alive as long as the
171     // AImageDecoder, so we do not need to copy the buffer.
172     auto stream = std::unique_ptr<SkStreamRewindable>(
173             new SkMemoryStream(buffer, length, false /* copyData */));
174     return createFromStream(std::move(stream), outDecoder);
175 }
176 
toDecoder(AImageDecoder * d)177 static ImageDecoder* toDecoder(AImageDecoder* d) {
178     return reinterpret_cast<ImageDecoder*>(d);
179 }
180 
toDecoder(const AImageDecoder * d)181 static const ImageDecoder* toDecoder(const AImageDecoder* d) {
182     return reinterpret_cast<const ImageDecoder*>(d);
183 }
184 
185 // Note: This differs from the version in android_bitmap.cpp in that this
186 // version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
187 // allows decoding single channel images to gray, which Android then treats
188 // as A_8/ALPHA_8.
getColorType(AndroidBitmapFormat format)189 static SkColorType getColorType(AndroidBitmapFormat format) {
190     switch (format) {
191         case ANDROID_BITMAP_FORMAT_RGBA_8888:
192             return kN32_SkColorType;
193         case ANDROID_BITMAP_FORMAT_RGB_565:
194             return kRGB_565_SkColorType;
195         case ANDROID_BITMAP_FORMAT_RGBA_4444:
196             return kARGB_4444_SkColorType;
197         case ANDROID_BITMAP_FORMAT_A_8:
198             return kGray_8_SkColorType;
199         case ANDROID_BITMAP_FORMAT_RGBA_F16:
200             return kRGBA_F16_SkColorType;
201         case ANDROID_BITMAP_FORMAT_RGBA_1010102:
202             return kRGBA_1010102_SkColorType;
203         default:
204             return kUnknown_SkColorType;
205     }
206 }
207 
AImageDecoder_setAndroidBitmapFormat(AImageDecoder * decoder,int32_t format)208 int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
209     if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE ||
210         format > ANDROID_BITMAP_FORMAT_RGBA_1010102) {
211         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
212     }
213 
214     auto* imageDecoder = toDecoder(decoder);
215     if (imageDecoder->currentFrame() != 0) {
216         return ANDROID_IMAGE_DECODER_INVALID_STATE;
217     }
218 
219     return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
220             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
221 }
222 
AImageDecoder_setDataSpace(AImageDecoder * decoder,int32_t dataspace)223 int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
224     sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
225     // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
226     if (!decoder || !dataspace || !cs) {
227         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
228     }
229 
230     ImageDecoder* imageDecoder = toDecoder(decoder);
231     if (imageDecoder->currentFrame() != 0) {
232         return ANDROID_IMAGE_DECODER_INVALID_STATE;
233     }
234 
235     imageDecoder->setOutColorSpace(std::move(cs));
236     return ANDROID_IMAGE_DECODER_SUCCESS;
237 }
238 
AImageDecoder_getHeaderInfo(const AImageDecoder * decoder)239 const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
240     return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
241 }
242 
toDecoder(const AImageDecoderHeaderInfo * info)243 static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
244     return reinterpret_cast<const ImageDecoder*>(info);
245 }
246 
AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo * info)247 int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
248     if (!info) {
249         return 0;
250     }
251     return toDecoder(info)->width();
252 }
253 
AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo * info)254 int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
255     if (!info) {
256         return 0;
257     }
258     return toDecoder(info)->height();
259 }
260 
AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo * info)261 const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
262     if (!info) {
263         return nullptr;
264     }
265     return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
266 }
267 
AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo * info)268 int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
269     if (!info) {
270         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
271     }
272 
273     // Note: This recomputes the color type because it's possible the client has
274     // changed the output color type, so we cannot rely on it. Alternatively,
275     // we could store the ADataSpace in the ImageDecoder.
276     const ImageDecoder* imageDecoder = toDecoder(info);
277     SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
278     sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
279     return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
280 }
281 
282 // FIXME: Share with getFormat in android_bitmap.cpp?
getFormat(SkColorType colorType)283 static AndroidBitmapFormat getFormat(SkColorType colorType) {
284     switch (colorType) {
285         case kN32_SkColorType:
286             return ANDROID_BITMAP_FORMAT_RGBA_8888;
287         case kRGB_565_SkColorType:
288             return ANDROID_BITMAP_FORMAT_RGB_565;
289         case kARGB_4444_SkColorType:
290             return ANDROID_BITMAP_FORMAT_RGBA_4444;
291         case kAlpha_8_SkColorType:
292             return ANDROID_BITMAP_FORMAT_A_8;
293         case kRGBA_F16_SkColorType:
294             return ANDROID_BITMAP_FORMAT_RGBA_F16;
295         case kRGBA_1010102_SkColorType:
296             return ANDROID_BITMAP_FORMAT_RGBA_1010102;
297         default:
298             return ANDROID_BITMAP_FORMAT_NONE;
299     }
300 }
301 
AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo * info)302 int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
303     if (!info) {
304         return ANDROID_BITMAP_FORMAT_NONE;
305     }
306     return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
307 }
308 
AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo * info)309 int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
310     if (!info) {
311         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
312     }
313     switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
314         case kUnknown_SkAlphaType:
315             LOG_ALWAYS_FATAL("Invalid alpha type");
316             return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
317         case kUnpremul_SkAlphaType:
318             // fall through. premul is the default.
319         case kPremul_SkAlphaType:
320             return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
321         case kOpaque_SkAlphaType:
322             return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
323     }
324 }
325 
AImageDecoder_setUnpremultipliedRequired(AImageDecoder * decoder,bool required)326 int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
327     if (!decoder) {
328         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
329     }
330 
331     auto* imageDecoder = toDecoder(decoder);
332     if (imageDecoder->currentFrame() != 0) {
333         return ANDROID_IMAGE_DECODER_INVALID_STATE;
334     }
335 
336     return imageDecoder->setUnpremultipliedRequired(required)
337             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
338 }
339 
AImageDecoder_setTargetSize(AImageDecoder * decoder,int32_t width,int32_t height)340 int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
341     if (!decoder) {
342         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
343     }
344 
345     auto* imageDecoder = toDecoder(decoder);
346     if (imageDecoder->currentFrame() != 0) {
347         return ANDROID_IMAGE_DECODER_INVALID_STATE;
348     }
349 
350     return imageDecoder->setTargetSize(width, height)
351             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
352 }
353 
AImageDecoder_computeSampledSize(const AImageDecoder * decoder,int sampleSize,int32_t * width,int32_t * height)354 int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
355                                      int32_t* width, int32_t* height) {
356     if (!decoder || !width || !height || sampleSize < 1) {
357         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
358     }
359 
360     SkISize size = toDecoder(decoder)->getSampledDimensions(sampleSize);
361     *width = size.width();
362     *height = size.height();
363     return ANDROID_IMAGE_DECODER_SUCCESS;
364 }
365 
AImageDecoder_setCrop(AImageDecoder * decoder,ARect crop)366 int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
367     if (!decoder) {
368         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
369     }
370 
371     auto* imageDecoder = toDecoder(decoder);
372     if (imageDecoder->currentFrame() != 0) {
373         return ANDROID_IMAGE_DECODER_INVALID_STATE;
374     }
375 
376     SkIRect cropIRect;
377     cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
378     SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
379     return imageDecoder->setCropRect(cropPtr)
380             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
381 }
382 
383 
AImageDecoder_getMinimumStride(AImageDecoder * decoder)384 size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
385     if (!decoder) {
386         return 0;
387     }
388 
389     SkImageInfo info = toDecoder(decoder)->getOutputInfo();
390     return info.minRowBytes();
391 }
392 
AImageDecoder_decodeImage(AImageDecoder * decoder,void * pixels,size_t stride,size_t size)393 int AImageDecoder_decodeImage(AImageDecoder* decoder,
394                               void* pixels, size_t stride,
395                               size_t size) {
396     if (!decoder || !pixels || !stride) {
397         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
398     }
399 
400     ImageDecoder* imageDecoder = toDecoder(decoder);
401 
402     SkImageInfo info = imageDecoder->getOutputInfo();
403     size_t minSize = info.computeByteSize(stride);
404     if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
405         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
406     }
407 
408     if (imageDecoder->finished()) {
409         return ANDROID_IMAGE_DECODER_FINISHED;
410     }
411 
412     return ResultToErrorCode(imageDecoder->decode(pixels, stride));
413 }
414 
AImageDecoder_delete(AImageDecoder * decoder)415 void AImageDecoder_delete(AImageDecoder* decoder) {
416     delete toDecoder(decoder);
417 }
418 
AImageDecoder_isAnimated(AImageDecoder * decoder)419 bool AImageDecoder_isAnimated(AImageDecoder* decoder) {
420     if (!decoder) return false;
421 
422     ImageDecoder* imageDecoder = toDecoder(decoder);
423     return imageDecoder->isAnimated();
424 }
425 
AImageDecoder_getRepeatCount(AImageDecoder * decoder)426 int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
427     if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
428 
429     ImageDecoder* imageDecoder = toDecoder(decoder);
430     const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
431 
432     // Skia should not report anything out of range, but defensively treat
433     // negative and too big as INFINITE.
434     if (count == SkCodec::kRepetitionCountInfinite || count < 0
435         || count > std::numeric_limits<int32_t>::max()) {
436         return ANDROID_IMAGE_DECODER_INFINITE;
437     }
438     return count;
439 }
440 
AImageDecoder_advanceFrame(AImageDecoder * decoder)441 int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
442     if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
443 
444     ImageDecoder* imageDecoder = toDecoder(decoder);
445     if (!imageDecoder->isAnimated()) {
446         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
447     }
448 
449     const auto colorType = imageDecoder->getOutputInfo().colorType();
450     switch (colorType) {
451         case kN32_SkColorType:
452         case kRGBA_F16_SkColorType:
453             break;
454         default:
455             return ANDROID_IMAGE_DECODER_INVALID_STATE;
456     }
457 
458     if (imageDecoder->advanceFrame()) {
459         return ANDROID_IMAGE_DECODER_SUCCESS;
460     }
461 
462     if (imageDecoder->finished()) {
463         return ANDROID_IMAGE_DECODER_FINISHED;
464     }
465 
466     return ANDROID_IMAGE_DECODER_INCOMPLETE;
467 }
468 
AImageDecoder_rewind(AImageDecoder * decoder)469 int AImageDecoder_rewind(AImageDecoder* decoder) {
470     if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
471 
472     ImageDecoder* imageDecoder = toDecoder(decoder);
473     if (!imageDecoder->isAnimated()) {
474         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
475     }
476 
477     return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
478                                   : ANDROID_IMAGE_DECODER_SEEK_ERROR;
479 }
480 
AImageDecoderFrameInfo_create()481 AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
482     return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
483 }
484 
toFrameInfo(AImageDecoderFrameInfo * info)485 static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
486     return reinterpret_cast<SkCodec::FrameInfo*>(info);
487 }
488 
toFrameInfo(const AImageDecoderFrameInfo * info)489 static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
490     return reinterpret_cast<const SkCodec::FrameInfo*>(info);
491 }
492 
AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo * info)493 void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
494     delete toFrameInfo(info);
495 }
496 
AImageDecoder_getFrameInfo(AImageDecoder * decoder,AImageDecoderFrameInfo * info)497 int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
498         AImageDecoderFrameInfo* info) {
499     if (!decoder || !info) {
500         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
501     }
502 
503     auto* imageDecoder = toDecoder(decoder);
504     if (imageDecoder->finished()) {
505         return ANDROID_IMAGE_DECODER_FINISHED;
506     }
507 
508     *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
509     return ANDROID_IMAGE_DECODER_SUCCESS;
510 }
511 
AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo * info)512 int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
513     if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
514 
515     return toFrameInfo(info)->fDuration * 1'000'000;
516 }
517 
AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo * info)518 ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
519     if (!info) {
520         return { 0, 0, 0, 0};
521     }
522 
523     const SkIRect& r = toFrameInfo(info)->fFrameRect;
524     return { r.left(), r.top(), r.right(), r.bottom() };
525 }
526 
AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo * info)527 bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
528     if (!info) return false;
529 
530     return toFrameInfo(info)->fHasAlphaWithinBounds;
531 }
532 
AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo * info)533 int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
534     if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
535 
536     static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
537                   == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
538     static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
539                   == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
540     static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
541                   == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
542     return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
543 }
544 
AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo * info)545 int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
546     if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
547 
548     switch (toFrameInfo(info)->fBlend) {
549         case SkCodecAnimation::Blend::kSrc:
550             return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
551         case SkCodecAnimation::Blend::kSrcOver:
552             return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
553     }
554 }
555 
AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder * decoder,bool handle)556 void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
557     if (decoder) {
558         toDecoder(decoder)->setHandleRestorePrevious(handle);
559     }
560 }
561