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 default:
202 return kUnknown_SkColorType;
203 }
204 }
205
AImageDecoder_setAndroidBitmapFormat(AImageDecoder * decoder,int32_t format)206 int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
207 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
208 || format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
209 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
210 }
211
212 auto* imageDecoder = toDecoder(decoder);
213 if (imageDecoder->currentFrame() != 0) {
214 return ANDROID_IMAGE_DECODER_INVALID_STATE;
215 }
216
217 return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
218 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
219 }
220
AImageDecoder_setDataSpace(AImageDecoder * decoder,int32_t dataspace)221 int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
222 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
223 // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
224 if (!decoder || !dataspace || !cs) {
225 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
226 }
227
228 ImageDecoder* imageDecoder = toDecoder(decoder);
229 if (imageDecoder->currentFrame() != 0) {
230 return ANDROID_IMAGE_DECODER_INVALID_STATE;
231 }
232
233 imageDecoder->setOutColorSpace(std::move(cs));
234 return ANDROID_IMAGE_DECODER_SUCCESS;
235 }
236
AImageDecoder_getHeaderInfo(const AImageDecoder * decoder)237 const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
238 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
239 }
240
toDecoder(const AImageDecoderHeaderInfo * info)241 static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
242 return reinterpret_cast<const ImageDecoder*>(info);
243 }
244
AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo * info)245 int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
246 if (!info) {
247 return 0;
248 }
249 return toDecoder(info)->width();
250 }
251
AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo * info)252 int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
253 if (!info) {
254 return 0;
255 }
256 return toDecoder(info)->height();
257 }
258
AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo * info)259 const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
260 if (!info) {
261 return nullptr;
262 }
263 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
264 }
265
AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo * info)266 int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
267 if (!info) {
268 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
269 }
270
271 // Note: This recomputes the color type because it's possible the client has
272 // changed the output color type, so we cannot rely on it. Alternatively,
273 // we could store the ADataSpace in the ImageDecoder.
274 const ImageDecoder* imageDecoder = toDecoder(info);
275 SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
276 sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
277 return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
278 }
279
280 // FIXME: Share with getFormat in android_bitmap.cpp?
getFormat(SkColorType colorType)281 static AndroidBitmapFormat getFormat(SkColorType colorType) {
282 switch (colorType) {
283 case kN32_SkColorType:
284 return ANDROID_BITMAP_FORMAT_RGBA_8888;
285 case kRGB_565_SkColorType:
286 return ANDROID_BITMAP_FORMAT_RGB_565;
287 case kARGB_4444_SkColorType:
288 return ANDROID_BITMAP_FORMAT_RGBA_4444;
289 case kAlpha_8_SkColorType:
290 return ANDROID_BITMAP_FORMAT_A_8;
291 case kRGBA_F16_SkColorType:
292 return ANDROID_BITMAP_FORMAT_RGBA_F16;
293 default:
294 return ANDROID_BITMAP_FORMAT_NONE;
295 }
296 }
297
AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo * info)298 int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
299 if (!info) {
300 return ANDROID_BITMAP_FORMAT_NONE;
301 }
302 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
303 }
304
AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo * info)305 int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
306 if (!info) {
307 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
308 }
309 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
310 case kUnknown_SkAlphaType:
311 LOG_ALWAYS_FATAL("Invalid alpha type");
312 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
313 case kUnpremul_SkAlphaType:
314 // fall through. premul is the default.
315 case kPremul_SkAlphaType:
316 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
317 case kOpaque_SkAlphaType:
318 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
319 }
320 }
321
AImageDecoder_setUnpremultipliedRequired(AImageDecoder * decoder,bool required)322 int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
323 if (!decoder) {
324 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
325 }
326
327 auto* imageDecoder = toDecoder(decoder);
328 if (imageDecoder->currentFrame() != 0) {
329 return ANDROID_IMAGE_DECODER_INVALID_STATE;
330 }
331
332 return imageDecoder->setUnpremultipliedRequired(required)
333 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
334 }
335
AImageDecoder_setTargetSize(AImageDecoder * decoder,int32_t width,int32_t height)336 int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
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->setTargetSize(width, height)
347 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
348 }
349
AImageDecoder_computeSampledSize(const AImageDecoder * decoder,int sampleSize,int32_t * width,int32_t * height)350 int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
351 int32_t* width, int32_t* height) {
352 if (!decoder || !width || !height || sampleSize < 1) {
353 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
354 }
355
356 SkISize size = toDecoder(decoder)->getSampledDimensions(sampleSize);
357 *width = size.width();
358 *height = size.height();
359 return ANDROID_IMAGE_DECODER_SUCCESS;
360 }
361
AImageDecoder_setCrop(AImageDecoder * decoder,ARect crop)362 int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
363 if (!decoder) {
364 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
365 }
366
367 auto* imageDecoder = toDecoder(decoder);
368 if (imageDecoder->currentFrame() != 0) {
369 return ANDROID_IMAGE_DECODER_INVALID_STATE;
370 }
371
372 SkIRect cropIRect;
373 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
374 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
375 return imageDecoder->setCropRect(cropPtr)
376 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
377 }
378
379
AImageDecoder_getMinimumStride(AImageDecoder * decoder)380 size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
381 if (!decoder) {
382 return 0;
383 }
384
385 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
386 return info.minRowBytes();
387 }
388
AImageDecoder_decodeImage(AImageDecoder * decoder,void * pixels,size_t stride,size_t size)389 int AImageDecoder_decodeImage(AImageDecoder* decoder,
390 void* pixels, size_t stride,
391 size_t size) {
392 if (!decoder || !pixels || !stride) {
393 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
394 }
395
396 ImageDecoder* imageDecoder = toDecoder(decoder);
397
398 SkImageInfo info = imageDecoder->getOutputInfo();
399 size_t minSize = info.computeByteSize(stride);
400 if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
401 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
402 }
403
404 if (imageDecoder->finished()) {
405 return ANDROID_IMAGE_DECODER_FINISHED;
406 }
407
408 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
409 }
410
AImageDecoder_delete(AImageDecoder * decoder)411 void AImageDecoder_delete(AImageDecoder* decoder) {
412 delete toDecoder(decoder);
413 }
414
AImageDecoder_isAnimated(AImageDecoder * decoder)415 bool AImageDecoder_isAnimated(AImageDecoder* decoder) {
416 if (!decoder) return false;
417
418 ImageDecoder* imageDecoder = toDecoder(decoder);
419 return imageDecoder->isAnimated();
420 }
421
AImageDecoder_getRepeatCount(AImageDecoder * decoder)422 int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
423 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
424
425 ImageDecoder* imageDecoder = toDecoder(decoder);
426 const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
427
428 // Skia should not report anything out of range, but defensively treat
429 // negative and too big as INFINITE.
430 if (count == SkCodec::kRepetitionCountInfinite || count < 0
431 || count > std::numeric_limits<int32_t>::max()) {
432 return ANDROID_IMAGE_DECODER_INFINITE;
433 }
434 return count;
435 }
436
AImageDecoder_advanceFrame(AImageDecoder * decoder)437 int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
438 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
439
440 ImageDecoder* imageDecoder = toDecoder(decoder);
441 if (!imageDecoder->isAnimated()) {
442 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
443 }
444
445 const auto colorType = imageDecoder->getOutputInfo().colorType();
446 switch (colorType) {
447 case kN32_SkColorType:
448 case kRGBA_F16_SkColorType:
449 break;
450 default:
451 return ANDROID_IMAGE_DECODER_INVALID_STATE;
452 }
453
454 if (imageDecoder->advanceFrame()) {
455 return ANDROID_IMAGE_DECODER_SUCCESS;
456 }
457
458 if (imageDecoder->finished()) {
459 return ANDROID_IMAGE_DECODER_FINISHED;
460 }
461
462 return ANDROID_IMAGE_DECODER_INCOMPLETE;
463 }
464
AImageDecoder_rewind(AImageDecoder * decoder)465 int AImageDecoder_rewind(AImageDecoder* decoder) {
466 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
467
468 ImageDecoder* imageDecoder = toDecoder(decoder);
469 if (!imageDecoder->isAnimated()) {
470 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
471 }
472
473 return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
474 : ANDROID_IMAGE_DECODER_SEEK_ERROR;
475 }
476
AImageDecoderFrameInfo_create()477 AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
478 return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
479 }
480
toFrameInfo(AImageDecoderFrameInfo * info)481 static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
482 return reinterpret_cast<SkCodec::FrameInfo*>(info);
483 }
484
toFrameInfo(const AImageDecoderFrameInfo * info)485 static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
486 return reinterpret_cast<const SkCodec::FrameInfo*>(info);
487 }
488
AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo * info)489 void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
490 delete toFrameInfo(info);
491 }
492
AImageDecoder_getFrameInfo(AImageDecoder * decoder,AImageDecoderFrameInfo * info)493 int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
494 AImageDecoderFrameInfo* info) {
495 if (!decoder || !info) {
496 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
497 }
498
499 auto* imageDecoder = toDecoder(decoder);
500 if (imageDecoder->finished()) {
501 return ANDROID_IMAGE_DECODER_FINISHED;
502 }
503
504 *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
505 return ANDROID_IMAGE_DECODER_SUCCESS;
506 }
507
AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo * info)508 int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
509 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
510
511 return toFrameInfo(info)->fDuration * 1'000'000;
512 }
513
AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo * info)514 ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
515 if (!info) {
516 return { 0, 0, 0, 0};
517 }
518
519 const SkIRect& r = toFrameInfo(info)->fFrameRect;
520 return { r.left(), r.top(), r.right(), r.bottom() };
521 }
522
AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo * info)523 bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
524 if (!info) return false;
525
526 return toFrameInfo(info)->fHasAlphaWithinBounds;
527 }
528
AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo * info)529 int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
530 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
531
532 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
533 == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
534 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
535 == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
536 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
537 == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
538 return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
539 }
540
AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo * info)541 int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
542 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
543
544 switch (toFrameInfo(info)->fBlend) {
545 case SkCodecAnimation::Blend::kSrc:
546 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
547 case SkCodecAnimation::Blend::kSrcOver:
548 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
549 }
550 }
551
AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder * decoder,bool handle)552 void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
553 if (decoder) {
554 toDecoder(decoder)->setHandleRestorePrevious(handle);
555 }
556 }
557