From 6a82f99ca15c09ca95742cdc9d96bebca832a29e Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 4 Jun 2018 09:24:05 -0700 Subject: [PATCH] Explicitly null MediaPeriod callbacks on release If a MediaPeriod uses a Loadable, then there are typically reference chains of the form: LoadingThread[GCroot]->Loadable->MediaPeriod->Player Where the player is the MediaPeriod callback. When the player is released, this reference chain prevents the player from being GC'd until Loadable cancellation completes, which may not always be fast. This in turn will typically prevent the application's activity from being GC'd, since it'll normally be registered as a listener on the player (directly or indirectly via something like a view). This change mitigates the issue by removing references that the MediaPeriod holds back to the player. The MediaPeriod will still not be eligible for GC, but the player and application activity will be, which in most cases will be most of the leak (in terms of size). Issue: #4249 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=199143646 --- .../android/exoplayer2/source/ExtractorMediaPeriod.java | 3 ++- .../android/exoplayer2/source/dash/DashMediaPeriod.java | 4 +++- .../google/android/exoplayer2/source/hls/HlsMediaPeriod.java | 4 +++- .../exoplayer2/source/smoothstreaming/SsMediaPeriod.java | 4 +++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index d4ea6191aa..63c86c2c96 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -90,7 +90,7 @@ import java.util.Arrays; private final Runnable onContinueLoadingRequestedRunnable; private final Handler handler; - private Callback callback; + private @Nullable Callback callback; private SeekMap seekMap; private SampleQueue[] sampleQueues; private int[] sampleQueueTrackIds; @@ -190,6 +190,7 @@ import java.util.Arrays; } loader.release(this); handler.removeCallbacksAndMessages(null); + callback = null; released = true; eventDispatcher.mediaPeriodReleased(); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index d2982481e0..f80ff89fc1 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.source.dash; import android.support.annotation.IntDef; +import android.support.annotation.Nullable; import android.util.Pair; import android.util.SparseArray; import android.util.SparseIntArray; @@ -72,7 +73,7 @@ import java.util.List; private final IdentityHashMap, PlayerTrackEmsgHandler> trackEmsgHandlerBySampleStream; - private Callback callback; + private @Nullable Callback callback; private ChunkSampleStream[] sampleStreams; private EventSampleStream[] eventSampleStreams; private SequenceableLoader compositeSequenceableLoader; @@ -150,6 +151,7 @@ import java.util.List; for (ChunkSampleStream sampleStream : sampleStreams) { sampleStream.release(this); } + callback = null; eventDispatcher.mediaPeriodReleased(); } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index 1a3f41fffc..b142d38df9 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source.hls; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.SeekParameters; @@ -57,7 +58,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final boolean allowChunklessPreparation; - private Callback callback; + private @Nullable Callback callback; private int pendingPrepareCount; private TrackGroupArray trackGroups; private HlsSampleStreamWrapper[] sampleStreamWrappers; @@ -96,6 +97,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) { sampleStreamWrapper.release(); } + callback = null; eventDispatcher.mediaPeriodReleased(); } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java index 9a0d57ff31..8e7c3e38c9 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source.smoothstreaming; +import android.support.annotation.Nullable; import android.util.Base64; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.SeekParameters; @@ -52,7 +53,7 @@ import java.util.ArrayList; private final TrackEncryptionBox[] trackEncryptionBoxes; private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; - private Callback callback; + private @Nullable Callback callback; private SsManifest manifest; private ChunkSampleStream[] sampleStreams; private SequenceableLoader compositeSequenceableLoader; @@ -98,6 +99,7 @@ import java.util.ArrayList; for (ChunkSampleStream sampleStream : sampleStreams) { sampleStream.release(); } + callback = null; eventDispatcher.mediaPeriodReleased(); }