diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java index 853a9af526..8fefb50a96 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java @@ -17,6 +17,8 @@ package com.google.android.exoplayer2.upstream; import android.os.Handler; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.util.Assertions; +import java.util.concurrent.CopyOnWriteArrayList; /** * Provides estimates of the currently available bandwidth. @@ -42,6 +44,62 @@ public interface BandwidthMeter { * @param bitrateEstimate The estimated bitrate in bits/sec. */ void onBandwidthSample(int elapsedMs, long bytesTransferred, long bitrateEstimate); + + /** Event dispatcher which allows listener registration. */ + final class EventDispatcher { + + private final CopyOnWriteArrayList listeners; + + /** Creates an event dispatcher. */ + public EventDispatcher() { + listeners = new CopyOnWriteArrayList<>(); + } + + /** Adds a listener to the event dispatcher. */ + public void addListener(Handler handler, BandwidthMeter.EventListener eventListener) { + Assertions.checkArgument(handler != null && eventListener != null); + removeListener(eventListener); + listeners.add(new HandlerAndListener(handler, eventListener)); + } + + /** Removes a listener from the event dispatcher. */ + public void removeListener(BandwidthMeter.EventListener eventListener) { + for (HandlerAndListener handlerAndListener : listeners) { + if (handlerAndListener.listener == eventListener) { + handlerAndListener.release(); + listeners.remove(handlerAndListener); + } + } + } + + public void bandwidthSample(int elapsedMs, long bytesTransferred, long bitrateEstimate) { + for (HandlerAndListener handlerAndListener : listeners) { + if (!handlerAndListener.released) { + handlerAndListener.handler.post( + () -> + handlerAndListener.listener.onBandwidthSample( + elapsedMs, bytesTransferred, bitrateEstimate)); + } + } + } + + private static final class HandlerAndListener { + + private final Handler handler; + private final BandwidthMeter.EventListener listener; + + private boolean released; + + public HandlerAndListener(Handler handler, BandwidthMeter.EventListener eventListener) { + this.handler = handler; + this.listener = eventListener; + } + + public void release() { + released = true; + } + } + } } /** Returns the estimated bitrate. */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java index 143a2469ab..66aec96e89 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java @@ -25,9 +25,9 @@ import android.os.Looper; import android.util.SparseArray; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener.EventDispatcher; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; -import com.google.android.exoplayer2.util.EventDispatcher; import com.google.android.exoplayer2.util.SlidingPercentile; import com.google.android.exoplayer2.util.Util; import java.lang.ref.WeakReference; @@ -256,7 +256,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList @Nullable private final Context context; private final SparseArray initialBitrateEstimates; - private final EventDispatcher eventDispatcher; + private final EventDispatcher eventDispatcher; private final SlidingPercentile slidingPercentile; private final Clock clock; @@ -292,7 +292,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList boolean resetOnNetworkTypeChange) { this.context = context == null ? null : context.getApplicationContext(); this.initialBitrateEstimates = initialBitrateEstimates; - this.eventDispatcher = new EventDispatcher<>(); + this.eventDispatcher = new EventDispatcher(); this.slidingPercentile = new SlidingPercentile(maxWeight); this.clock = clock; // Set the initial network type and bitrate estimate @@ -427,8 +427,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList return; } lastReportedBitrateEstimate = bitrateEstimate; - eventDispatcher.dispatch( - listener -> listener.onBandwidthSample(elapsedMs, bytesTransferred, bitrateEstimate)); + eventDispatcher.bandwidthSample(elapsedMs, bytesTransferred, bitrateEstimate); } private long getInitialBitrateEstimateForNetworkType(@C.NetworkType int networkType) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java deleted file mode 100644 index 07f278c808..0000000000 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EventDispatcher.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer2.util; - -import android.os.Handler; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * Event dispatcher which allows listener registration. - * - * @param The type of listener. - */ -public final class EventDispatcher { - - /** Functional interface to send an event. */ - public interface Event { - - /** - * Sends the event to a listener. - * - * @param listener The listener to send the event to. - */ - void sendTo(T listener); - } - - /** The list of listeners and handlers. */ - private final CopyOnWriteArrayList> listeners; - - /** Creates an event dispatcher. */ - public EventDispatcher() { - listeners = new CopyOnWriteArrayList<>(); - } - - /** Adds a listener to the event dispatcher. */ - public void addListener(Handler handler, T eventListener) { - Assertions.checkArgument(handler != null && eventListener != null); - removeListener(eventListener); - listeners.add(new HandlerAndListener<>(handler, eventListener)); - } - - /** Removes a listener from the event dispatcher. */ - public void removeListener(T eventListener) { - for (HandlerAndListener handlerAndListener : listeners) { - if (handlerAndListener.listener == eventListener) { - handlerAndListener.release(); - listeners.remove(handlerAndListener); - } - } - } - - /** - * Dispatches an event to all registered listeners. - * - * @param event The {@link Event}. - */ - public void dispatch(Event event) { - for (HandlerAndListener handlerAndListener : listeners) { - handlerAndListener.dispatch(event); - } - } - - private static final class HandlerAndListener { - - private final Handler handler; - private final T listener; - - private boolean released; - - public HandlerAndListener(Handler handler, T eventListener) { - this.handler = handler; - this.listener = eventListener; - } - - public void release() { - released = true; - } - - public void dispatch(Event event) { - handler.post( - () -> { - if (!released) { - event.sendTo(listener); - } - }); - } - } -}