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