software-mansion / software-mansion/react-native-audio-api
[Android] PlaybackNotification.loadArtwork decodes artwork at full resolution — unbounded memory, no cache, no timeouts
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 839
- Forks
- 92
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 27
Description
Description
PlaybackNotification.loadArtwork (L509-539) downloads and decodes remote artwork at full resolution:
val connection = URL(url).openConnection()
connection.connect()
val inputStream = connection.getInputStream()
val bitmap = BitmapFactory.decodeStream(inputStream)
- Unbounded decode — no
BitmapFactory.Options, so a 4000×4000 artwork allocates ~64 MB inARGB_8888for something rendered at notification-icon size.BitmapFactory.decodeFilein the local branch has the same issue. - No cache — every metadata update re-downloads and re-decodes the same URL.
- No timeouts — default (infinite) connect/read on a bare
Threadthatinterrupt()can't unblock from a socket read. - The result is then passed to
mediaSession.setMetadata(...putBitmap(METADATA_KEY_ART, bitmap))(L288), crossing a Binder transaction at full size.
Google Play Console flags this under App quality insights → "bitmap image optimization":
Decoded in
com.swmansion.audioapi.system.notification.PlaybackNotification.loadArtwork
Downloaded incom.swmansion.audioapi.system.notification.PlaybackNotification.loadArtwork
Suggested fix: two-pass decode (inJustDecodeBounds → inSampleSize against notification_large_icon_width/height or a ~512 px cap), plus connect/read timeouts and a small LRU on the URL. Alternatively delegate to Fresco, already on the classpath in every RN app, via ImageRequestBuilder + ResizeOptions — that gets downsampling, caching and cancellation for free.
Steps to reproduce
AudioManager.setNowPlaying({ ..., artwork: '<url to a 4000×4000 JPEG>' }).- Android Studio Profiler shows the bitmap allocated at source resolution, not icon size. On low-RAM devices this surfaces as
OutOfMemoryErrorinBitmapFactory.decodeStream.
Snack or a link to a repository
None — code-level report, verified against main; source linked above.
React Native Audio API version
0.13.2 (unchanged on main and in 0.13.3)
React Native version
0.86.3
Platforms
Android
Architecture
New architecture
Build type
Release mode
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/react-native-audio-api/android/src/main/java/com/swmansion/audioapi/system/notification/PlaybackNotification.kt, especially loadArtwork at lines 509-539 and the mediaSession metadata call near line 288. Reproduce with a large remote artwork while profiling memory, then verify that artwork decoding is bounded, repeated URLs are cached, and network reads have finite timeouts without causing the reported OutOfMemoryError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin, react-native
- Domain
- mobile, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100