#android #leakcanary #android-mediasession
#Android #утечка #android-медиасессия
Вопрос:
Я обнаружил странную утечку в своем аудиоприложении, когда звук Service
просачивается, если мы удаляем приложение с экрана обзора приложения (квадратная кнопка или проведите пальцем вверх в зависимости от устройства). После закрытия приложения повторное открытие этого же приложения быстро приведет к тому же сеансу, который мы только что пытались закрыть, наполовину сорвав и пропустив аудио Service
в виде AudioPlayerService
. Вот отчет об утечке в соответствии с утечкой:
2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: ==================================== 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: HEAP ANALYSIS RESULT 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: ==================================== 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: 1 APPLICATION LEAKS 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: References underlined with "~~~" are likely causes. 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: Learn more at https://squ.re/leaks. 2021-11-30 17:43:12.696 com.mixhalo.mixhaloclient.debug D/LeakCanary: 9966 bytes retained by leaking objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Signature: c66398a2a91f6817ce902cdec3748a8398a58154 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ┬─── 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ GC Root: Input or output parameters in native code 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ okio.AsyncTimeout class 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: NO (PathClassLoader↓ is not leaking and a class is never leaking) 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ static AsyncTimeout.$class$classLoader 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ dalvik.system.PathClassLoader instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: NO (AppModuleKt↓ is not leaking and A ClassLoader is never leaking) 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ ClassLoader.runtimeInternalObjects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ java.lang.Object[] array 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: NO (AppModuleKt↓ is not leaking) 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ Object[].[2671] 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ com.mixhalo.client.di.AppModuleKt class 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: NO (a class is never leaking) 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ static AppModuleKt.AppModule 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ org.koin.core.module.Module instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 118 B in 4 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ Module.definitions 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ java.util.ArrayList instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 80 B in 2 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ ArrayList.elementData 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ java.lang.Object[] array 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 60 B in 1 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ Object[].[2] 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ org.koin.core.definition.BeanDefinition instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 15.2 kB in 166 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ BeanDefinition.instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ org.koin.core.instance.SingleDefinitionInstance instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 15.1 kB in 161 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ SingleDefinitionInstance.value 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ com.mixhalo.client.repositories.MediaControllerRepository instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 15.1 kB in 160 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ MediaControllerRepository.controllerChannel 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~~~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ kotlinx.coroutines.channels.ConflatedBroadcastChannel instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 15.1 kB in 159 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ ConflatedBroadcastChannel._state 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ kotlinx.coroutines.channels.ConflatedBroadcastChannel$State instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 15.0 kB in 158 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ ConflatedBroadcastChannel$State.value 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ android.support.v4.media.session.MediaControllerCompat instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 15.0 kB in 157 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ MediaControllerCompat.mToken 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ android.support.v4.media.session.MediaSessionCompat$Token instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 13.0 kB in 139 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ MediaSessionCompat$Token.mExtraBinder 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi21$ExtraSession instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 13.0 kB in 137 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ MediaSessionCompat$MediaSessionImplApi21$ExtraSession.this$0 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi29 instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 12.4 kB in 136 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ MediaSessionCompat$MediaSessionImplApi21.mCallback 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ├─ com.mixhalo.client.service.AudioPlayerService$SessionCallback instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Leaking: UNKNOWN 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ Retaining 96 B in 4 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ this$0 instance of com.mixhalo.client.service.AudioPlayerService 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ↓ AudioPlayerService$SessionCallback.this$0 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: │ ~~~~~~ 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ╰→ com.mixhalo.client.service.AudioPlayerService instance 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Leaking: YES (ObjectWatcher was watching this because com.mixhalo.client.service.AudioPlayerService received 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Service#onDestroy() callback and Service not held by ActivityThread) 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Retaining 10.0 kB in 101 objects 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: key = 357606dd-731d-402e-a7f6-adb6ba37aabb 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: watchDurationMillis = 6719 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: retainedDurationMillis = 1719 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: mApplication instance of com.mixhalo.client.App 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: mBase instance of android.app.ContextImpl 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ==================================== 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: 0 LIBRARY LEAKS 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over. 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: See https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ==================================== 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: 0 UNREACHABLE OBJECTS 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: An unreachable object is still in memory but LeakCanary could not find a strong reference path 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: from GC roots. 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ==================================== 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: METADATA 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Please include this in bug reports and Stack Overflow questions. 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Build.VERSION.SDK_INT: 31 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Build.MANUFACTURER: Google 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: LeakCanary version: 2.7 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: App process name: com.mixhalo.mixhaloclient.debug 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Stats: LruCache[maxSize=3000,hits=1437,misses=110886,hitRate=1%] 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: RandomAccess[bytes=5834063,reads=110886,travel=56164491159,range=31391064,size=38866865] 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Heap dump reason: user request 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Analysis duration: 4946 ms 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Heap dump file path: /storage/emulated/0/Download/leakcanary-com.mixhalo.mixhaloclient.debug/2021-11-30_17-41-24_788. 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: hprof 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Heap dump timestamp: 1638322892418 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: Heap dump duration: 2263 ms 2021-11-30 17:43:12.697 com.mixhalo.mixhaloclient.debug D/LeakCanary: ====================================
Самое смешное/странное в этой утечке то, что, если я не открою приложение сразу, сбой неизбежно произойдет в фоновом режиме беззвучно с помощью LeakCanary, но это видно только через мою реализацию Crashlytics. Вот трассировка стека этого:
Fatal Exception: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service com.mixhalo.mixhaloclient.debug/leakcanary.internal.HeapAnalyzerService at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54) at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50) at android.os.Parcel.readParcelable(Parcel.java:3333) at android.os.Parcel.createExceptionOrNull(Parcel.java:2420) at android.os.Parcel.createException(Parcel.java:2409) at android.os.Parcel.readException(Parcel.java:2392) at android.os.Parcel.readException(Parcel.java:2334) at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:5971) at java.lang.reflect.Method.invoke(Method.java) at leakcanary.ServiceWatcher$install$4$2.invoke(ServiceWatcher.kt:85) at java.lang.reflect.Proxy.invoke(Proxy.java:1006) at $Proxy3.startService() at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1847) at android.app.ContextImpl.startForegroundService(ContextImpl.java:1823) at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779) at leakcanary.internal.HeapAnalyzerService$Companion.startForegroundService(HeapAnalyzerService.kt:149) at leakcanary.internal.HeapAnalyzerService$Companion.runAnalysis(HeapAnalyzerService.kt:141) at leakcanary.internal.HeapDumpTrigger.dumpHeap(HeapDumpTrigger.kt:186) at leakcanary.internal.HeapDumpTrigger.checkRetainedObjects(HeapDumpTrigger.kt:150) at leakcanary.internal.HeapDumpTrigger.access$checkRetainedObjects(HeapDumpTrigger.kt:29) at leakcanary.internal.HeapDumpTrigger$scheduleRetainedObjectCheck$1.run(HeapDumpTrigger.kt:334) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.os.HandlerThread.run(HandlerThread.java:67)