HeifDecoderImpl вызывает «decStrong () вызывается слишком много раз»

#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)