#android #image #memory-management #heif
#Android #изображение #управление памятью #heif
Вопрос:
Мое приложение для Android «Сравнение фотографий» (https://github.com/sniederb/photocompare ) использует «Представление изображения в масштабе подвыборки» (от Дейва Моррисси) для отображения изображений и позволяет масштабировать и панорамировать. Это почти всегда работает хорошо, но на Android 11 с изображениями HEIC активность падает, как только я увеличиваю масштаб.
Прерывающийся поток
runtime.cc:655] Aborting thread:
runtime.cc:655] "HeifDecode" prio=6 tid=32 Native
runtime.cc:655] | group="" sCount=0 dsCount=0 flags=0 obj=0x12c40020 self=0xe9022210
runtime.cc:655] | sysTid=18958 nice=-2 cgrp=top-app sched=0/0 handle=0xc6e561e0
runtime.cc:655] | state=R schedstat=( 98486663 91130505 137 ) utm=2 stm=7 core=2 HZ=100
runtime.cc:655] | stack=0xc6d5b000-0xc6d5d000 stackSize=1008KB
runtime.cc:655] | held mutexes= "abort lock"
runtime.cc:655] native: #00 pc 00542d9e /apex/com.android.art/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >amp;, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool) 110)
runtime.cc:655] native: #01 pc 006a0897 /apex/com.android.art/lib/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >amp;, bool, BacktraceMap*, bool) const 1015)
runtime.cc:655] native: #02 pc 0069a171 /apex/com.android.art/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >amp;, bool, BacktraceMap*, bool) const 65)
runtime.cc:655] native: #03 pc 006522c5 /apex/com.android.art/lib/libart.so (art::AbortState::DumpThread(std::__1::basic_ostream<char, std::__1::char_traits<char> >amp;, art::Thread*) const 53)
runtime.cc:655] native: #04 pc 00639abb /apex/com.android.art/lib/libart.so (art::Runtime::Abort(char const*) 2587)
runtime.cc:655] native: #05 pc 00025a23 /apex/com.android.art/lib/libartbase.so (std::__1::__function::__func<void (*)(char const*), std::__1::allocator<void (*)(char const*)>, void (char const*)>::operator()(char const*amp;amp;) 35)
runtime.cc:655] native: #06 pc 0001588f /system/lib/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>amp;amp;)::$_3::__invoke(char const*) 79)
runtime.cc:655] native: #07 pc 00006dbd /system/lib/liblog.so (__android_log_assert 285)
runtime.cc:655] native: #08 pc 000102a2 /system/lib/libutils.so (android::RefBase::decStrong(void const*) const 146)
runtime.cc:655] native: #09 pc 00004de4 /system/lib/libheif.so (android::HeifDecoderImpl::decodeAsync() 436)
runtime.cc:655] native: #10 pc 00004c23 /system/lib/libheif.so (android::HeifDecoderImpl::DecodeThread::threadLoop() 35)
runtime.cc:655] native: #11 pc 00015116 /system/lib/libutils.so (android::Thread::_threadLoop(void*) 374)
runtime.cc:655] native: #12 pc 00098fee /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*) 174)
runtime.cc:655] native: #13 pc 000147d9 /system/lib/libutils.so (thread_data_t::trampoline(thread_data_t const*) 457)
runtime.cc:655] native: #14 pc 000e6974 /apex/com.android.runtime/lib/bionic/libc.so (__pthread_start(void*) 100)
runtime.cc:655] native: #15 pc 00078567 /apex/com.android.runtime/lib/bionic/libc.so (__start_thread 71)
runtime.cc:655] (no managed stack frames)
и в отчете о сбое говорится
2021-01-09 14:12:53.736 19089-19089/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2021-01-09 14:12:53.736 19089-19089/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86_arm/generic_x86_arm:11/RSR1.201013.001/6903271:userdebug/dev-keys'
2021-01-09 14:12:53.736 19089-19089/? A/DEBUG: Revision: '0'
2021-01-09 14:12:53.737 19089-19089/? A/DEBUG: ABI: 'x86'
2021-01-09 14:12:53.737 19089-19089/? A/DEBUG: Timestamp: 2021-01-09 14:12:53 0100
2021-01-09 14:12:53.737 19089-19089/? A/DEBUG: pid: 18085, tid: 18958, name: HeifDecode >>> ch.want.imagecompare <<<
2021-01-09 14:12:53.737 19089-19089/? A/DEBUG: uid: 10153
2021-01-09 14:12:53.737 19089-19089/? A/DEBUG: signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
2021-01-09 14:12:53.738 19089-19089/? A/DEBUG: Abort message: 'decStrong() called on 0xc7e43d10 too many times'
2021-01-09 14:12:53.738 19089-19089/? A/DEBUG: eax 00000000 ebx 000046a5 ecx 00004a0e edx 00000006
2021-01-09 14:12:53.738 19089-19089/? A/DEBUG: edi f4a5681e esi c6e559c0
2021-01-09 14:12:53.738 19089-19089/? A/DEBUG: ebp f7517b90 esp c6e55968 eip f7517b99
2021-01-09 14:12:53.744 19089-19089/? A/DEBUG: backtrace:
2021-01-09 14:12:53.745 19089-19089/? A/DEBUG: #00 pc 00000b99 [vdso] (__kernel_vsyscall 9)
2021-01-09 14:12:53.745 19089-19089/? A/DEBUG: #01 pc 0005ad68 /apex/com.android.runtime/lib/bionic/libc.so (syscall 40) (BuildId: 6e3a0180fa6637b68c0d181c343e6806)
2021-01-09 14:12:53.745 19089-19089/? A/DEBUG: #02 pc 00076511 /apex/com.android.runtime/lib/bionic/libc.so (abort 209) (BuildId: 6e3a0180fa6637b68c0d181c343e6806)
2021-01-09 14:12:53.745 19089-19089/? A/DEBUG: #03 pc 00639a4d /apex/com.android.art/lib/libart.so (art::Runtime::Abort(char const*) 2477) (BuildId: 8191579dfafff37a5cbca70f9a73020f)
2021-01-09 14:12:53.745 19089-19089/? A/DEBUG: #04 pc 00025a23 /apex/com.android.art/lib/libartbase.so (std::__1::__function::__func<void (*)(char const*), std::__1::allocator<void (*)(char const*)>, void (char const*)>::operator()(char const*amp;amp;) 35) (BuildId: 41e9e0cbb5db4bb6875333d66af6569f)
2021-01-09 14:12:53.746 19089-19089/? A/DEBUG: #05 pc 0001588f /system/lib/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>amp;amp;)::$_3::__invoke(char const*) 79) (BuildId: 3abc3ce4c3b633a64b14c50cb931a64b)
2021-01-09 14:12:53.746 19089-19089/? A/DEBUG: #06 pc 00006dbd /system/lib/liblog.so (__android_log_assert 285) (BuildId: bbac430fc6349b937996bb914e70c060)
2021-01-09 14:12:53.746 19089-19089/? A/DEBUG: #07 pc 000102a2 /system/lib/libutils.so (android::RefBase::decStrong(void const*) const 146) (BuildId: ab4be013cda31e8c45d48aa23a89d0f8)
2021-01-09 14:12:53.746 19089-19089/? A/DEBUG: #08 pc 00004de4 /system/lib/libheif.so (android::HeifDecoderImpl::decodeAsync() 436) (BuildId: 49a068f457bf8577f622fb97089c3c5d)
2021-01-09 14:12:53.746 19089-19089/? A/DEBUG: #09 pc 00004c23 /system/lib/libheif.so (android::HeifDecoderImpl::DecodeThread::threadLoop() 35) (BuildId: 49a068f457bf8577f622fb97089c3c5d)
2021-01-09 14:12:53.746 19089-19089/? A/DEBUG: #10 pc 00015116 /system/lib/libutils.so (android::Thread::_threadLoop(void*) 374) (BuildId: ab4be013cda31e8c45d48aa23a89d0f8)
2021-01-09 14:12:53.747 19089-19089/? A/DEBUG: #11 pc 00098fee /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*) 174) (BuildId: 588f2cd5873ff4273bb25b25edb82606)
2021-01-09 14:12:53.747 19089-19089/? A/DEBUG: #12 pc 000147d9 /system/lib/libutils.so (thread_data_t::trampoline(thread_data_t const*) 457) (BuildId: ab4be013cda31e8c45d48aa23a89d0f8)
2021-01-09 14:12:53.747 19089-19089/? A/DEBUG: #13 pc 000e6974 /apex/com.android.runtime/lib/bionic/libc.so (__pthread_start(void*) 100) (BuildId: 6e3a0180fa6637b68c0d181c343e6806)
Насколько я понимаю, HeifDecoderImpl запрашивается асинхронное декодирование областей изображения (это то, что делает «Представление изображения с подвыборкой», afaik), и при этом слишком часто пытается освободить ресурс, в результате чего RefBase пытается слишком часто уменьшить количество сильных ссылок.
Как программист приложений, я в тупике и не уверен, могу ли я что-нибудь здесь сделать. И HeifDecoderImpl, и RefBase, похоже, являются основным кодом Android. Нужно ли мне просматривать библиотеку «Представление изображения с подвыборкой»? Приветствуется любой указатель.
Комментарии:
1. Я могу воспроизвести это в Android Studio с помощью эмулятора на API 30. Тот же код с теми же изображениями отлично работает с API 29.
Ответ №1:
Похоже, ошибка возникает из-за Bitmap.Config Bitmap.Config.RGB_565 по умолчанию, используемого SubsamplingScaleImageView (фактически SkiaImageDecoder.java
, часть этого пакета). Переключившись на
SubsamplingScaleImageView.setPreferredBitmapConfig(Bitmap.Config.ARGB_8888);
ошибка исчезает.
Комментарии:
1. Это правильное решение. Я не понимаю почему, потому что я пытался использовать BitmapRegionDecoder в собственном коде, чтобы загрузить часть того же изображения в цикле, включая переработку, и этого не происходит, даже с Bitmap.Config.RGB_565. Для меня это похоже на ошибку Android.
2. Еще лучше, вероятно, использовать Bitmap.Config. АППАРАТНОЕ ОБЕСПЕЧЕНИЕ (начиная с API 26)