mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +08:00
Replace MutableFlags by immutable class
PiperOrigin-RevId: 362043183
This commit is contained in:
parent
851c915e38
commit
4a6859e5e2
@ -95,7 +95,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
private final SeekResultCallback seekResultCallback;
|
private final SeekResultCallback seekResultCallback;
|
||||||
|
|
||||||
// Listeners and notification.
|
// Listeners and notification.
|
||||||
private final ListenerSet<Player.EventListener, Player.Events> listeners;
|
private final ListenerSet<Player.EventListener> listeners;
|
||||||
@Nullable private SessionAvailabilityListener sessionAvailabilityListener;
|
@Nullable private SessionAvailabilityListener sessionAvailabilityListener;
|
||||||
|
|
||||||
// Internal state.
|
// Internal state.
|
||||||
@ -139,8 +139,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
new ListenerSet<>(
|
new ListenerSet<>(
|
||||||
Looper.getMainLooper(),
|
Looper.getMainLooper(),
|
||||||
Clock.DEFAULT,
|
Clock.DEFAULT,
|
||||||
Player.Events::new,
|
(listener, flags) -> listener.onEvents(/* player= */ this, new Events(flags)));
|
||||||
(listener, eventFlags) -> listener.onEvents(/* player= */ this, eventFlags));
|
|
||||||
|
|
||||||
playWhenReady = new StateHolder<>(false);
|
playWhenReady = new StateHolder<>(false);
|
||||||
repeatMode = new StateHolder<>(REPEAT_MODE_OFF);
|
repeatMode = new StateHolder<>(REPEAT_MODE_OFF);
|
||||||
|
@ -27,7 +27,7 @@ import com.google.android.exoplayer2.util.ListenerSet;
|
|||||||
/** A fake player for testing content/ad playback. */
|
/** A fake player for testing content/ad playback. */
|
||||||
/* package */ final class FakePlayer extends StubExoPlayer {
|
/* package */ final class FakePlayer extends StubExoPlayer {
|
||||||
|
|
||||||
private final ListenerSet<EventListener, Events> listeners;
|
private final ListenerSet<EventListener> listeners;
|
||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
|
|
||||||
private Timeline timeline;
|
private Timeline timeline;
|
||||||
@ -45,8 +45,7 @@ import com.google.android.exoplayer2.util.ListenerSet;
|
|||||||
new ListenerSet<>(
|
new ListenerSet<>(
|
||||||
Looper.getMainLooper(),
|
Looper.getMainLooper(),
|
||||||
Clock.DEFAULT,
|
Clock.DEFAULT,
|
||||||
Player.Events::new,
|
(listener, flags) -> listener.onEvents(/* player= */ this, new Events(flags)));
|
||||||
(listener, eventFlags) -> listener.onEvents(/* player= */ this, eventFlags));
|
|
||||||
period = new Timeline.Period();
|
period = new Timeline.Period();
|
||||||
state = Player.STATE_IDLE;
|
state = Player.STATE_IDLE;
|
||||||
playWhenReady = true;
|
playWhenReady = true;
|
||||||
|
@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.util.Assertions.checkState;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.SparseBooleanArray;
|
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
@ -37,7 +35,7 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
|
|||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.text.TextOutput;
|
import com.google.android.exoplayer2.text.TextOutput;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.util.MutableFlags;
|
import com.google.android.exoplayer2.util.ExoFlags;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
|
import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
|
||||||
import com.google.android.exoplayer2.video.VideoListener;
|
import com.google.android.exoplayer2.video.VideoListener;
|
||||||
@ -664,17 +662,27 @@ public interface Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A set of {@link EventFlags}. */
|
/** A set of {@link EventFlags}. */
|
||||||
final class Events extends MutableFlags {
|
final class Events {
|
||||||
|
|
||||||
|
private final ExoFlags flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance.
|
||||||
|
*
|
||||||
|
* @param flags The {@link ExoFlags} containing the {@link EventFlags} in the set.
|
||||||
|
*/
|
||||||
|
public Events(ExoFlags flags) {
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given event occurred.
|
* Returns whether the given event occurred.
|
||||||
*
|
*
|
||||||
* @param event The {@link EventFlags event}.
|
* @param event The {@link EventFlags event}.
|
||||||
* @return Whether the event occurred.
|
* @return Whether the event occurred.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public boolean contains(@EventFlags int event) {
|
public boolean contains(@EventFlags int event) {
|
||||||
// Overridden to add IntDef compiler enforcement and new JavaDoc.
|
return flags.contains(event);
|
||||||
return super.contains(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -683,10 +691,13 @@ public interface Player {
|
|||||||
* @param events The {@link EventFlags events}.
|
* @param events The {@link EventFlags events}.
|
||||||
* @return Whether any of the events occurred.
|
* @return Whether any of the events occurred.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public boolean containsAny(@EventFlags int... events) {
|
public boolean containsAny(@EventFlags int... events) {
|
||||||
// Overridden to add IntDef compiler enforcement and new JavaDoc.
|
return flags.containsAny(events);
|
||||||
return super.containsAny(events);
|
}
|
||||||
|
|
||||||
|
/** Returns the number of events in the set. */
|
||||||
|
public int size() {
|
||||||
|
return flags.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -698,11 +709,9 @@ public interface Player {
|
|||||||
* @param index The index. Must be between 0 (inclusive) and {@link #size()} (exclusive).
|
* @param index The index. Must be between 0 (inclusive) and {@link #size()} (exclusive).
|
||||||
* @return The {@link EventFlags event} at the given index.
|
* @return The {@link EventFlags event} at the given index.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
@EventFlags
|
@EventFlags
|
||||||
public int get(int index) {
|
public int get(int index) {
|
||||||
// Overridden to add IntDef compiler enforcement and new JavaDoc.
|
return flags.get(index);
|
||||||
return super.get(index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,18 +725,11 @@ public interface Player {
|
|||||||
/** A builder for {@link Commands} instances. */
|
/** A builder for {@link Commands} instances. */
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
|
|
||||||
private final SparseBooleanArray commandsArray;
|
private final ExoFlags.Builder flagsBuilder;
|
||||||
|
|
||||||
private boolean buildCalled;
|
|
||||||
|
|
||||||
/** Creates a builder. */
|
/** Creates a builder. */
|
||||||
public Builder() {
|
public Builder() {
|
||||||
commandsArray = new SparseBooleanArray();
|
flagsBuilder = new ExoFlags.Builder();
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a builder with the values of the provided {@link Commands}. */
|
|
||||||
private Builder(Commands commands) {
|
|
||||||
this.commandsArray = commands.commandsArray.clone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -738,8 +740,7 @@ public interface Player {
|
|||||||
* @throws IllegalStateException If {@link #build()} has already been called.
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
*/
|
*/
|
||||||
public Builder add(@Command int command) {
|
public Builder add(@Command int command) {
|
||||||
checkState(!buildCalled);
|
flagsBuilder.add(command);
|
||||||
commandsArray.append(command, /* value= */ true);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,39 +753,32 @@ public interface Player {
|
|||||||
* @throws IllegalStateException If {@link #build()} has already been called.
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
*/
|
*/
|
||||||
public Builder addIf(@Command int command, boolean condition) {
|
public Builder addIf(@Command int command, boolean condition) {
|
||||||
checkState(!buildCalled);
|
flagsBuilder.addIf(command, condition);
|
||||||
if (condition) {
|
|
||||||
commandsArray.append(command, /* value= */ true);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Builds a {@link Commands} instance. */
|
/**
|
||||||
|
* Builds a {@link Commands} instance.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException If this method has already been called.
|
||||||
|
*/
|
||||||
public Commands build() {
|
public Commands build() {
|
||||||
checkState(!buildCalled);
|
return new Commands(flagsBuilder.build());
|
||||||
buildCalled = true;
|
|
||||||
return new Commands(commandsArray);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An empty set of commands. */
|
/** An empty set of commands. */
|
||||||
public static final Commands EMPTY = new Commands.Builder().build();
|
public static final Commands EMPTY = new Builder().build();
|
||||||
|
|
||||||
// A SparseBooleanArray is used instead of a Set to avoid auto-boxing the Command values.
|
private final ExoFlags flags;
|
||||||
private final SparseBooleanArray commandsArray;
|
|
||||||
|
|
||||||
private Commands(SparseBooleanArray commandsArray) {
|
private Commands(ExoFlags flags) {
|
||||||
this.commandsArray = commandsArray;
|
this.flags = flags;
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a {@link Commands.Builder} initialized with the values of this instance. */
|
|
||||||
public Builder buildUpon() {
|
|
||||||
return new Builder(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the set of commands contains the specified {@link Command}. */
|
/** Returns whether the set of commands contains the specified {@link Command}. */
|
||||||
public boolean contains(@Command int command) {
|
public boolean contains(@Command int command) {
|
||||||
return commandsArray.get(command);
|
return flags.contains(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -796,12 +790,12 @@ public interface Player {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Commands commands = (Commands) obj;
|
Commands commands = (Commands) obj;
|
||||||
return this.commandsArray.equals(commands.commandsArray);
|
return flags.equals(commands.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return commandsArray.hashCode();
|
return flags.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Assertions.checkState;
|
||||||
|
|
||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@ -23,28 +25,68 @@ import androidx.annotation.Nullable;
|
|||||||
*
|
*
|
||||||
* <p>Intended for usages where the number of flags may exceed 32 and can no longer be represented
|
* <p>Intended for usages where the number of flags may exceed 32 and can no longer be represented
|
||||||
* by an IntDef.
|
* by an IntDef.
|
||||||
|
*
|
||||||
|
* <p>Instances are immutable.
|
||||||
*/
|
*/
|
||||||
public class MutableFlags {
|
public final class ExoFlags {
|
||||||
|
|
||||||
|
/** A builder for {@link ExoFlags} instances. */
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
|
private final SparseBooleanArray flags;
|
||||||
|
|
||||||
|
private boolean buildCalled;
|
||||||
|
|
||||||
|
/** Creates a builder. */
|
||||||
|
public Builder() {
|
||||||
|
flags = new SparseBooleanArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a flag.
|
||||||
|
*
|
||||||
|
* @param flag A flag.
|
||||||
|
* @return This builder.
|
||||||
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
|
*/
|
||||||
|
public Builder add(int flag) {
|
||||||
|
checkState(!buildCalled);
|
||||||
|
flags.append(flag, /* value= */ true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a flag if the provided condition is true. Does nothing otherwise.
|
||||||
|
*
|
||||||
|
* @param flag A flag.
|
||||||
|
* @param condition A condition.
|
||||||
|
* @return This builder.
|
||||||
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
|
*/
|
||||||
|
public Builder addIf(int flag, boolean condition) {
|
||||||
|
if (condition) {
|
||||||
|
return add(flag);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an {@link ExoFlags} instance.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException If this method has already been called.
|
||||||
|
*/
|
||||||
|
public ExoFlags build() {
|
||||||
|
checkState(!buildCalled);
|
||||||
|
buildCalled = true;
|
||||||
|
return new ExoFlags(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A SparseBooleanArray is used instead of a Set to avoid auto-boxing the flag values.
|
||||||
private final SparseBooleanArray flags;
|
private final SparseBooleanArray flags;
|
||||||
|
|
||||||
/** Creates the set of flags. */
|
private ExoFlags(SparseBooleanArray flags) {
|
||||||
public MutableFlags() {
|
this.flags = flags;
|
||||||
flags = new SparseBooleanArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clears all previously set flags. */
|
|
||||||
public void clear() {
|
|
||||||
flags.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a flag to the set.
|
|
||||||
*
|
|
||||||
* @param flag The flag to add.
|
|
||||||
*/
|
|
||||||
public void add(int flag) {
|
|
||||||
flags.append(flag, /* value= */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,10 +136,10 @@ public class MutableFlags {
|
|||||||
if (this == o) {
|
if (this == o) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!(o instanceof MutableFlags)) {
|
if (!(o instanceof ExoFlags)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MutableFlags that = (MutableFlags) o;
|
ExoFlags that = (ExoFlags) o;
|
||||||
return flags.equals(that.flags);
|
return flags.equals(that.flags);
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,6 @@ import android.os.Message;
|
|||||||
import androidx.annotation.CheckResult;
|
import androidx.annotation.CheckResult;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -35,9 +34,8 @@ import javax.annotation.Nonnull;
|
|||||||
* was enqueued and haven't been removed since.
|
* was enqueued and haven't been removed since.
|
||||||
*
|
*
|
||||||
* @param <T> The listener type.
|
* @param <T> The listener type.
|
||||||
* @param <E> The {@link MutableFlags} type used to indicate which events occurred.
|
|
||||||
*/
|
*/
|
||||||
public final class ListenerSet<T, E extends MutableFlags> {
|
public final class ListenerSet<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event sent to a listener.
|
* An event sent to a listener.
|
||||||
@ -55,17 +53,17 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
* iteration were handled by the listener.
|
* iteration were handled by the listener.
|
||||||
*
|
*
|
||||||
* @param <T> The listener type.
|
* @param <T> The listener type.
|
||||||
* @param <E> The {@link MutableFlags} type used to indicate which events occurred.
|
|
||||||
*/
|
*/
|
||||||
public interface IterationFinishedEvent<T, E extends MutableFlags> {
|
public interface IterationFinishedEvent<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the iteration finished event.
|
* Invokes the iteration finished event.
|
||||||
*
|
*
|
||||||
* @param listener The listener to invoke the event on.
|
* @param listener The listener to invoke the event on.
|
||||||
* @param eventFlags The combined event flags of all events sent in this iteration.
|
* @param eventFlags The combined event {@link ExoFlags flags} of all events sent in this
|
||||||
|
* iteration.
|
||||||
*/
|
*/
|
||||||
void invoke(T listener, E eventFlags);
|
void invoke(T listener, ExoFlags eventFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int MSG_ITERATION_FINISHED = 0;
|
private static final int MSG_ITERATION_FINISHED = 0;
|
||||||
@ -73,9 +71,8 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
|
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final HandlerWrapper handler;
|
private final HandlerWrapper handler;
|
||||||
private final Supplier<E> eventFlagsSupplier;
|
private final IterationFinishedEvent<T> iterationFinishedEvent;
|
||||||
private final IterationFinishedEvent<T, E> iterationFinishedEvent;
|
private final CopyOnWriteArraySet<ListenerHolder<T>> listeners;
|
||||||
private final CopyOnWriteArraySet<ListenerHolder<T, E>> listeners;
|
|
||||||
private final ArrayDeque<Runnable> flushingEvents;
|
private final ArrayDeque<Runnable> flushingEvents;
|
||||||
private final ArrayDeque<Runnable> queuedEvents;
|
private final ArrayDeque<Runnable> queuedEvents;
|
||||||
|
|
||||||
@ -87,33 +84,24 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
* @param looper A {@link Looper} used to call listeners on. The same {@link Looper} must be used
|
* @param looper A {@link Looper} used to call listeners on. The same {@link Looper} must be used
|
||||||
* to call all other methods of this class.
|
* to call all other methods of this class.
|
||||||
* @param clock A {@link Clock}.
|
* @param clock A {@link Clock}.
|
||||||
* @param eventFlagsSupplier A {@link Supplier} for new instances of {@link E the event flags
|
|
||||||
* type}.
|
|
||||||
* @param iterationFinishedEvent An {@link IterationFinishedEvent} sent when all other events sent
|
* @param iterationFinishedEvent An {@link IterationFinishedEvent} sent when all other events sent
|
||||||
* during one {@link Looper} message queue iteration were handled by the listeners.
|
* during one {@link Looper} message queue iteration were handled by the listeners.
|
||||||
*/
|
*/
|
||||||
public ListenerSet(
|
public ListenerSet(Looper looper, Clock clock, IterationFinishedEvent<T> iterationFinishedEvent) {
|
||||||
Looper looper,
|
|
||||||
Clock clock,
|
|
||||||
Supplier<E> eventFlagsSupplier,
|
|
||||||
IterationFinishedEvent<T, E> iterationFinishedEvent) {
|
|
||||||
this(
|
this(
|
||||||
/* listeners= */ new CopyOnWriteArraySet<>(),
|
/* listeners= */ new CopyOnWriteArraySet<>(),
|
||||||
looper,
|
looper,
|
||||||
clock,
|
clock,
|
||||||
eventFlagsSupplier,
|
|
||||||
iterationFinishedEvent);
|
iterationFinishedEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenerSet(
|
private ListenerSet(
|
||||||
CopyOnWriteArraySet<ListenerHolder<T, E>> listeners,
|
CopyOnWriteArraySet<ListenerHolder<T>> listeners,
|
||||||
Looper looper,
|
Looper looper,
|
||||||
Clock clock,
|
Clock clock,
|
||||||
Supplier<E> eventFlagsSupplier,
|
IterationFinishedEvent<T> iterationFinishedEvent) {
|
||||||
IterationFinishedEvent<T, E> iterationFinishedEvent) {
|
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.listeners = listeners;
|
this.listeners = listeners;
|
||||||
this.eventFlagsSupplier = eventFlagsSupplier;
|
|
||||||
this.iterationFinishedEvent = iterationFinishedEvent;
|
this.iterationFinishedEvent = iterationFinishedEvent;
|
||||||
flushingEvents = new ArrayDeque<>();
|
flushingEvents = new ArrayDeque<>();
|
||||||
queuedEvents = new ArrayDeque<>();
|
queuedEvents = new ArrayDeque<>();
|
||||||
@ -132,9 +120,8 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
* @return The copied listener set.
|
* @return The copied listener set.
|
||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public ListenerSet<T, E> copy(
|
public ListenerSet<T> copy(Looper looper, IterationFinishedEvent<T> iterationFinishedEvent) {
|
||||||
Looper looper, IterationFinishedEvent<T, E> iterationFinishedEvent) {
|
return new ListenerSet<>(listeners, looper, clock, iterationFinishedEvent);
|
||||||
return new ListenerSet<>(listeners, looper, clock, eventFlagsSupplier, iterationFinishedEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +136,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Assertions.checkNotNull(listener);
|
Assertions.checkNotNull(listener);
|
||||||
listeners.add(new ListenerHolder<>(listener, eventFlagsSupplier));
|
listeners.add(new ListenerHolder<>(listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,7 +147,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
* @param listener The listener to be removed.
|
* @param listener The listener to be removed.
|
||||||
*/
|
*/
|
||||||
public void remove(T listener) {
|
public void remove(T listener) {
|
||||||
for (ListenerHolder<T, E> listenerHolder : listeners) {
|
for (ListenerHolder<T> listenerHolder : listeners) {
|
||||||
if (listenerHolder.listener.equals(listener)) {
|
if (listenerHolder.listener.equals(listener)) {
|
||||||
listenerHolder.release(iterationFinishedEvent);
|
listenerHolder.release(iterationFinishedEvent);
|
||||||
listeners.remove(listenerHolder);
|
listeners.remove(listenerHolder);
|
||||||
@ -176,11 +163,10 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
* @param event The event.
|
* @param event The event.
|
||||||
*/
|
*/
|
||||||
public void queueEvent(int eventFlag, Event<T> event) {
|
public void queueEvent(int eventFlag, Event<T> event) {
|
||||||
CopyOnWriteArraySet<ListenerHolder<T, E>> listenerSnapshot =
|
CopyOnWriteArraySet<ListenerHolder<T>> listenerSnapshot = new CopyOnWriteArraySet<>(listeners);
|
||||||
new CopyOnWriteArraySet<>(listeners);
|
|
||||||
queuedEvents.add(
|
queuedEvents.add(
|
||||||
() -> {
|
() -> {
|
||||||
for (ListenerHolder<T, E> holder : listenerSnapshot) {
|
for (ListenerHolder<T> holder : listenerSnapshot) {
|
||||||
holder.invoke(eventFlag, event);
|
holder.invoke(eventFlag, event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -226,7 +212,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
* <p>This will ensure no events are sent to any listener after this method has been called.
|
* <p>This will ensure no events are sent to any listener after this method has been called.
|
||||||
*/
|
*/
|
||||||
public void release() {
|
public void release() {
|
||||||
for (ListenerHolder<T, E> listenerHolder : listeners) {
|
for (ListenerHolder<T> listenerHolder : listeners) {
|
||||||
listenerHolder.release(iterationFinishedEvent);
|
listenerHolder.release(iterationFinishedEvent);
|
||||||
}
|
}
|
||||||
listeners.clear();
|
listeners.clear();
|
||||||
@ -249,8 +235,8 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
|
|
||||||
private boolean handleMessage(Message message) {
|
private boolean handleMessage(Message message) {
|
||||||
if (message.what == MSG_ITERATION_FINISHED) {
|
if (message.what == MSG_ITERATION_FINISHED) {
|
||||||
for (ListenerHolder<T, E> holder : listeners) {
|
for (ListenerHolder<T> holder : listeners) {
|
||||||
holder.iterationFinished(eventFlagsSupplier, iterationFinishedEvent);
|
holder.iterationFinished(iterationFinishedEvent);
|
||||||
if (handler.hasMessages(MSG_ITERATION_FINISHED)) {
|
if (handler.hasMessages(MSG_ITERATION_FINISHED)) {
|
||||||
// The invocation above triggered new events (and thus scheduled a new message). We need
|
// The invocation above triggered new events (and thus scheduled a new message). We need
|
||||||
// to stop here because this new message will take care of informing every listener about
|
// to stop here because this new message will take care of informing every listener about
|
||||||
@ -268,45 +254,44 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ListenerHolder<T, E extends MutableFlags> {
|
private static final class ListenerHolder<T> {
|
||||||
|
|
||||||
@Nonnull public final T listener;
|
@Nonnull public final T listener;
|
||||||
|
|
||||||
private E eventsFlags;
|
private ExoFlags.Builder flagsBuilder;
|
||||||
private boolean needsIterationFinishedEvent;
|
private boolean needsIterationFinishedEvent;
|
||||||
private boolean released;
|
private boolean released;
|
||||||
|
|
||||||
public ListenerHolder(@Nonnull T listener, Supplier<E> eventFlagSupplier) {
|
public ListenerHolder(@Nonnull T listener) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.eventsFlags = eventFlagSupplier.get();
|
this.flagsBuilder = new ExoFlags.Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release(IterationFinishedEvent<T, E> event) {
|
public void release(IterationFinishedEvent<T> event) {
|
||||||
released = true;
|
released = true;
|
||||||
if (needsIterationFinishedEvent) {
|
if (needsIterationFinishedEvent) {
|
||||||
event.invoke(listener, eventsFlags);
|
event.invoke(listener, flagsBuilder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invoke(int eventFlag, Event<T> event) {
|
public void invoke(int eventFlag, Event<T> event) {
|
||||||
if (!released) {
|
if (!released) {
|
||||||
if (eventFlag != C.INDEX_UNSET) {
|
if (eventFlag != C.INDEX_UNSET) {
|
||||||
eventsFlags.add(eventFlag);
|
flagsBuilder.add(eventFlag);
|
||||||
}
|
}
|
||||||
needsIterationFinishedEvent = true;
|
needsIterationFinishedEvent = true;
|
||||||
event.invoke(listener);
|
event.invoke(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void iterationFinished(
|
public void iterationFinished(IterationFinishedEvent<T> event) {
|
||||||
Supplier<E> eventFlagSupplier, IterationFinishedEvent<T, E> event) {
|
|
||||||
if (!released && needsIterationFinishedEvent) {
|
if (!released && needsIterationFinishedEvent) {
|
||||||
// Reset flags before invoking the listener to ensure we keep all new flags that are set by
|
// Reset flags before invoking the listener to ensure we keep all new flags that are set by
|
||||||
// recursive events triggered from this callback.
|
// recursive events triggered from this callback.
|
||||||
E flagToNotify = eventsFlags;
|
ExoFlags flagsToNotify = flagsBuilder.build();
|
||||||
eventsFlags = eventFlagSupplier.get();
|
flagsBuilder = new ExoFlags.Builder();
|
||||||
needsIterationFinishedEvent = false;
|
needsIterationFinishedEvent = false;
|
||||||
event.invoke(listener, flagToNotify);
|
event.invoke(listener, flagsToNotify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +303,7 @@ public final class ListenerSet<T, E extends MutableFlags> {
|
|||||||
if (other == null || getClass() != other.getClass()) {
|
if (other == null || getClass() != other.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return listener.equals(((ListenerHolder<?, ?>) other).listener);
|
return listener.equals(((ListenerHolder<?>) other).listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,13 +24,13 @@ import java.util.List;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
/** Unit test for {@link MutableFlags}. */
|
/** Unit test for {@link ExoFlags}. */
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public final class MutableFlagsTest {
|
public final class ExoFlagsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contains_withoutAdd_returnsFalseForAllValues() {
|
public void contains_withoutAdd_returnsFalseForAllValues() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags = new ExoFlags.Builder().build();
|
||||||
|
|
||||||
assertThat(flags.contains(/* flag= */ -1234)).isFalse();
|
assertThat(flags.contains(/* flag= */ -1234)).isFalse();
|
||||||
assertThat(flags.contains(/* flag= */ 0)).isFalse();
|
assertThat(flags.contains(/* flag= */ 0)).isFalse();
|
||||||
@ -40,12 +40,13 @@ public final class MutableFlagsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contains_afterAdd_returnsTrueForAddedValues() {
|
public void contains_afterAdd_returnsTrueForAddedValues() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags =
|
||||||
|
new ExoFlags.Builder()
|
||||||
flags.add(/* flag= */ -1234);
|
.add(/* flag= */ -1234)
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 2);
|
.add(/* flag= */ 2)
|
||||||
flags.add(/* flag= */ Integer.MAX_VALUE);
|
.add(/* flag= */ Integer.MAX_VALUE)
|
||||||
|
.build();
|
||||||
|
|
||||||
assertThat(flags.contains(/* flag= */ -1235)).isFalse();
|
assertThat(flags.contains(/* flag= */ -1235)).isFalse();
|
||||||
assertThat(flags.contains(/* flag= */ -1234)).isTrue();
|
assertThat(flags.contains(/* flag= */ -1234)).isTrue();
|
||||||
@ -57,79 +58,94 @@ public final class MutableFlagsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void contains_afterClear_returnsFalseForAllValues() {
|
public void contains_afterAddIf_returnsTrueForAddedValues() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags =
|
||||||
flags.add(/* flag= */ -1234);
|
new ExoFlags.Builder()
|
||||||
flags.add(/* flag= */ 0);
|
.addIf(/* flag= */ -1234, /* condition= */ true)
|
||||||
flags.add(/* flag= */ 2);
|
.addIf(/* flag= */ 0, /* condition= */ false)
|
||||||
flags.add(/* flag= */ Integer.MAX_VALUE);
|
.addIf(/* flag= */ 2, /* condition= */ true)
|
||||||
|
.addIf(/* flag= */ Integer.MAX_VALUE, /* condition= */ false)
|
||||||
|
.build();
|
||||||
|
|
||||||
flags.clear();
|
assertThat(flags.contains(/* flag= */ -1235)).isFalse();
|
||||||
|
assertThat(flags.contains(/* flag= */ -1234)).isTrue();
|
||||||
assertThat(flags.contains(/* flag= */ -1234)).isFalse();
|
|
||||||
assertThat(flags.contains(/* flag= */ 0)).isFalse();
|
assertThat(flags.contains(/* flag= */ 0)).isFalse();
|
||||||
assertThat(flags.contains(/* flag= */ 2)).isFalse();
|
assertThat(flags.contains(/* flag= */ 1)).isFalse();
|
||||||
|
assertThat(flags.contains(/* flag= */ 2)).isTrue();
|
||||||
|
assertThat(flags.contains(/* flag= */ Integer.MAX_VALUE - 1)).isFalse();
|
||||||
assertThat(flags.contains(/* flag= */ Integer.MAX_VALUE)).isFalse();
|
assertThat(flags.contains(/* flag= */ Integer.MAX_VALUE)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsAny_withoutAdd_returnsFalseForAllValues() {
|
||||||
|
ExoFlags flags = new ExoFlags.Builder().build();
|
||||||
|
|
||||||
|
assertThat(flags.containsAny(/* flags...= */ -1234, 0, 2, Integer.MAX_VALUE)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsAny_afterAdd_returnsTrueForAddedValues() {
|
||||||
|
ExoFlags flags =
|
||||||
|
new ExoFlags.Builder()
|
||||||
|
.add(/* flag= */ -1234)
|
||||||
|
.add(/* flag= */ 0)
|
||||||
|
.add(/* flag= */ 2)
|
||||||
|
.add(/* flag= */ Integer.MAX_VALUE)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(
|
||||||
|
flags.containsAny(
|
||||||
|
/* flags...= */ -1235, -1234, 0, 1, 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(flags.containsAny(/* flags...= */ -1235, 1, Integer.MAX_VALUE - 1)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void size_withoutAdd_returnsZero() {
|
public void size_withoutAdd_returnsZero() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags = new ExoFlags.Builder().build();
|
||||||
|
|
||||||
assertThat(flags.size()).isEqualTo(0);
|
assertThat(flags.size()).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void size_afterAdd_returnsNumberUniqueOfElements() {
|
public void size_afterAdd_returnsNumberUniqueOfElements() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags =
|
||||||
|
new ExoFlags.Builder()
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 123);
|
.add(/* flag= */ 123)
|
||||||
flags.add(/* flag= */ 123);
|
.add(/* flag= */ 123)
|
||||||
|
.build();
|
||||||
|
|
||||||
assertThat(flags.size()).isEqualTo(2);
|
assertThat(flags.size()).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void size_afterClear_returnsZero() {
|
|
||||||
MutableFlags flags = new MutableFlags();
|
|
||||||
|
|
||||||
flags.add(/* flag= */ 0);
|
|
||||||
flags.add(/* flag= */ 123);
|
|
||||||
flags.clear();
|
|
||||||
|
|
||||||
assertThat(flags.size()).isEqualTo(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void get_withNegativeIndex_throwsIllegalArgumentException() {
|
public void get_withNegativeIndex_throwsIllegalArgumentException() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags = new ExoFlags.Builder().build();
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> flags.get(/* index= */ -1));
|
assertThrows(IllegalArgumentException.class, () -> flags.get(/* index= */ -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void get_withIndexExceedingSize_throwsIllegalArgumentException() {
|
public void get_withIndexExceedingSize_throwsIllegalArgumentException() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags = new ExoFlags.Builder().add(/* flag= */ 0).add(/* flag= */ 123).build();
|
||||||
|
|
||||||
flags.add(/* flag= */ 0);
|
|
||||||
flags.add(/* flag= */ 123);
|
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> flags.get(/* index= */ 2));
|
assertThrows(IllegalArgumentException.class, () -> flags.get(/* index= */ 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void get_afterAdd_returnsAllUniqueValues() {
|
public void get_afterAdd_returnsAllUniqueValues() {
|
||||||
MutableFlags flags = new MutableFlags();
|
ExoFlags flags =
|
||||||
|
new ExoFlags.Builder()
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 0);
|
.add(/* flag= */ 0)
|
||||||
flags.add(/* flag= */ 123);
|
.add(/* flag= */ 123)
|
||||||
flags.add(/* flag= */ 123);
|
.add(/* flag= */ 123)
|
||||||
flags.add(/* flag= */ 456);
|
.add(/* flag= */ 456)
|
||||||
|
.build();
|
||||||
|
|
||||||
List<Integer> values = new ArrayList<>();
|
List<Integer> values = new ArrayList<>();
|
||||||
for (int i = 0; i < flags.size(); i++) {
|
for (int i = 0; i < flags.size(); i++) {
|
@ -42,9 +42,8 @@ public class ListenerSetTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queueEvent_withoutFlush_sendsNoEvents() {
|
public void queueEvent_withoutFlush_sendsNoEvents() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener = mock(TestListener.class);
|
TestListener listener = mock(TestListener.class);
|
||||||
listenerSet.add(listener);
|
listenerSet.add(listener);
|
||||||
|
|
||||||
@ -57,9 +56,8 @@ public class ListenerSetTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flushEvents_sendsPreviouslyQueuedEventsToAllListeners() {
|
public void flushEvents_sendsPreviouslyQueuedEventsToAllListeners() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener1 = mock(TestListener.class);
|
TestListener listener1 = mock(TestListener.class);
|
||||||
TestListener listener2 = mock(TestListener.class);
|
TestListener listener2 = mock(TestListener.class);
|
||||||
listenerSet.add(listener1);
|
listenerSet.add(listener1);
|
||||||
@ -82,9 +80,8 @@ public class ListenerSetTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flushEvents_recursive_sendsEventsInCorrectOrder() {
|
public void flushEvents_recursive_sendsEventsInCorrectOrder() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
// Listener1 sends callback3 recursively when receiving callback1.
|
// Listener1 sends callback3 recursively when receiving callback1.
|
||||||
TestListener listener1 =
|
TestListener listener1 =
|
||||||
spy(
|
spy(
|
||||||
@ -116,9 +113,8 @@ public class ListenerSetTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
flushEvents_withMultipleMessageQueueIterations_sendsIterationFinishedEventPerIteration() {
|
flushEvents_withMultipleMessageQueueIterations_sendsIterationFinishedEventPerIteration() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
// Listener1 sends callback1 recursively when receiving callback3.
|
// Listener1 sends callback1 recursively when receiving callback3.
|
||||||
TestListener listener1 =
|
TestListener listener1 =
|
||||||
spy(
|
spy(
|
||||||
@ -152,30 +148,29 @@ public class ListenerSetTest {
|
|||||||
InOrder inOrder = Mockito.inOrder(listener1, listener2);
|
InOrder inOrder = Mockito.inOrder(listener1, listener2);
|
||||||
inOrder.verify(listener1).callback2();
|
inOrder.verify(listener1).callback2();
|
||||||
inOrder.verify(listener2).callback2();
|
inOrder.verify(listener2).callback2();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_2));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_2));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_2));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2));
|
||||||
inOrder.verify(listener1).callback1();
|
inOrder.verify(listener1).callback1();
|
||||||
inOrder.verify(listener2).callback1();
|
inOrder.verify(listener2).callback1();
|
||||||
inOrder.verify(listener1).callback2();
|
inOrder.verify(listener1).callback2();
|
||||||
inOrder.verify(listener2).callback2();
|
inOrder.verify(listener2).callback2();
|
||||||
inOrder.verify(listener1).callback1();
|
inOrder.verify(listener1).callback1();
|
||||||
inOrder.verify(listener2).callback1();
|
inOrder.verify(listener2).callback1();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_2));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_2));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2));
|
||||||
inOrder.verify(listener1).callback3();
|
inOrder.verify(listener1).callback3();
|
||||||
inOrder.verify(listener2).callback3();
|
inOrder.verify(listener2).callback3();
|
||||||
inOrder.verify(listener1).callback1();
|
inOrder.verify(listener1).callback1();
|
||||||
inOrder.verify(listener2).callback1();
|
inOrder.verify(listener2).callback1();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_3));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_3));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_3));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_3));
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flushEvents_calledFromIterationFinishedCallback_restartsIterationFinishedEvents() {
|
public void flushEvents_calledFromIterationFinishedCallback_restartsIterationFinishedEvents() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
// Listener2 sends callback1 recursively when receiving the iteration finished event.
|
// Listener2 sends callback1 recursively when receiving the iteration finished event.
|
||||||
TestListener listener2 =
|
TestListener listener2 =
|
||||||
spy(
|
spy(
|
||||||
@ -183,7 +178,7 @@ public class ListenerSetTest {
|
|||||||
boolean eventSent;
|
boolean eventSent;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void iterationFinished(Flags flags) {
|
public void iterationFinished(ExoFlags flags) {
|
||||||
if (!eventSent) {
|
if (!eventSent) {
|
||||||
listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1);
|
listenerSet.sendEvent(EVENT_ID_1, TestListener::callback1);
|
||||||
eventSent = true;
|
eventSent = true;
|
||||||
@ -203,22 +198,21 @@ public class ListenerSetTest {
|
|||||||
inOrder.verify(listener1).callback2();
|
inOrder.verify(listener1).callback2();
|
||||||
inOrder.verify(listener2).callback2();
|
inOrder.verify(listener2).callback2();
|
||||||
inOrder.verify(listener3).callback2();
|
inOrder.verify(listener3).callback2();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_2));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_2));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_2));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2));
|
||||||
inOrder.verify(listener1).callback1();
|
inOrder.verify(listener1).callback1();
|
||||||
inOrder.verify(listener2).callback1();
|
inOrder.verify(listener2).callback1();
|
||||||
inOrder.verify(listener3).callback1();
|
inOrder.verify(listener3).callback1();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_1));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_1));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1));
|
||||||
inOrder.verify(listener3).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_2));
|
inOrder.verify(listener3).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2));
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void flushEvents_withUnsetEventFlag_doesNotThrow() {
|
public void flushEvents_withUnsetEventFlag_doesNotThrow() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
|
|
||||||
listenerSet.queueEvent(/* eventFlag= */ C.INDEX_UNSET, TestListener::callback1);
|
listenerSet.queueEvent(/* eventFlag= */ C.INDEX_UNSET, TestListener::callback1);
|
||||||
listenerSet.flushEvents();
|
listenerSet.flushEvents();
|
||||||
@ -229,9 +223,8 @@ public class ListenerSetTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void add_withRecursion_onlyReceivesUpdatesForFutureEvents() {
|
public void add_withRecursion_onlyReceivesUpdatesForFutureEvents() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener2 = mock(TestListener.class);
|
TestListener listener2 = mock(TestListener.class);
|
||||||
// Listener1 adds listener2 recursively.
|
// Listener1 adds listener2 recursively.
|
||||||
TestListener listener1 =
|
TestListener listener1 =
|
||||||
@ -255,16 +248,15 @@ public class ListenerSetTest {
|
|||||||
inOrder.verify(listener1).callback1();
|
inOrder.verify(listener1).callback1();
|
||||||
inOrder.verify(listener1).callback2();
|
inOrder.verify(listener1).callback2();
|
||||||
inOrder.verify(listener2).callback2();
|
inOrder.verify(listener2).callback2();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_2));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_2));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2));
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void add_withQueueing_onlyReceivesUpdatesForFutureEvents() {
|
public void add_withQueueing_onlyReceivesUpdatesForFutureEvents() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener1 = mock(TestListener.class);
|
TestListener listener1 = mock(TestListener.class);
|
||||||
TestListener listener2 = mock(TestListener.class);
|
TestListener listener2 = mock(TestListener.class);
|
||||||
|
|
||||||
@ -281,16 +273,15 @@ public class ListenerSetTest {
|
|||||||
inOrder.verify(listener1).callback1();
|
inOrder.verify(listener1).callback1();
|
||||||
inOrder.verify(listener1).callback2();
|
inOrder.verify(listener1).callback2();
|
||||||
inOrder.verify(listener2).callback2();
|
inOrder.verify(listener2).callback2();
|
||||||
inOrder.verify(listener1).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_2));
|
inOrder.verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_2));
|
||||||
inOrder.verify(listener2).iterationFinished(Flags.create(EVENT_ID_2));
|
inOrder.verify(listener2).iterationFinished(createExoFlags(EVENT_ID_2));
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void remove_withRecursion_stopsReceivingEventsImmediately() {
|
public void remove_withRecursion_stopsReceivingEventsImmediately() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener2 = mock(TestListener.class);
|
TestListener listener2 = mock(TestListener.class);
|
||||||
// Listener1 removes listener2 recursively.
|
// Listener1 removes listener2 recursively.
|
||||||
TestListener listener1 =
|
TestListener listener1 =
|
||||||
@ -311,15 +302,14 @@ public class ListenerSetTest {
|
|||||||
ShadowLooper.runMainLooperToNextTask();
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
|
||||||
verify(listener1).callback1();
|
verify(listener1).callback1();
|
||||||
verify(listener1).iterationFinished(Flags.create(EVENT_ID_1));
|
verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1));
|
||||||
verifyNoMoreInteractions(listener1, listener2);
|
verifyNoMoreInteractions(listener1, listener2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void remove_withQueueing_stopsReceivingEventsImmediately() {
|
public void remove_withQueueing_stopsReceivingEventsImmediately() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener1 = mock(TestListener.class);
|
TestListener listener1 = mock(TestListener.class);
|
||||||
TestListener listener2 = mock(TestListener.class);
|
TestListener listener2 = mock(TestListener.class);
|
||||||
listenerSet.add(listener1);
|
listenerSet.add(listener1);
|
||||||
@ -333,15 +323,14 @@ public class ListenerSetTest {
|
|||||||
ShadowLooper.runMainLooperToNextTask();
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
|
||||||
verify(listener2, times(2)).callback1();
|
verify(listener2, times(2)).callback1();
|
||||||
verify(listener2).iterationFinished(Flags.create(EVENT_ID_1));
|
verify(listener2).iterationFinished(createExoFlags(EVENT_ID_1));
|
||||||
verifyNoMoreInteractions(listener1, listener2);
|
verifyNoMoreInteractions(listener1, listener2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void release_stopsForwardingEventsImmediately() {
|
public void release_stopsForwardingEventsImmediately() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener2 = mock(TestListener.class);
|
TestListener listener2 = mock(TestListener.class);
|
||||||
// Listener1 releases the set from within the callback.
|
// Listener1 releases the set from within the callback.
|
||||||
TestListener listener1 =
|
TestListener listener1 =
|
||||||
@ -361,15 +350,14 @@ public class ListenerSetTest {
|
|||||||
ShadowLooper.runMainLooperToNextTask();
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
|
||||||
verify(listener1).callback1();
|
verify(listener1).callback1();
|
||||||
verify(listener1).iterationFinished(Flags.create(EVENT_ID_1));
|
verify(listener1).iterationFinished(createExoFlags(EVENT_ID_1));
|
||||||
verifyNoMoreInteractions(listener1, listener2);
|
verifyNoMoreInteractions(listener1, listener2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void release_preventsRegisteringNewListeners() {
|
public void release_preventsRegisteringNewListeners() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener = mock(TestListener.class);
|
TestListener listener = mock(TestListener.class);
|
||||||
|
|
||||||
listenerSet.release();
|
listenerSet.release();
|
||||||
@ -381,9 +369,8 @@ public class ListenerSetTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lazyRelease_stopsForwardingEventsFromNewHandlerMessagesAndCallsReleaseCallback() {
|
public void lazyRelease_stopsForwardingEventsFromNewHandlerMessagesAndCallsReleaseCallback() {
|
||||||
ListenerSet<TestListener, Flags> listenerSet =
|
ListenerSet<TestListener> listenerSet =
|
||||||
new ListenerSet<>(
|
new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, TestListener::iterationFinished);
|
||||||
Looper.myLooper(), Clock.DEFAULT, Flags::new, TestListener::iterationFinished);
|
|
||||||
TestListener listener = mock(TestListener.class);
|
TestListener listener = mock(TestListener.class);
|
||||||
listenerSet.add(listener);
|
listenerSet.add(listener);
|
||||||
|
|
||||||
@ -403,8 +390,8 @@ public class ListenerSetTest {
|
|||||||
// lazy release.
|
// lazy release.
|
||||||
verify(listener, times(3)).callback1();
|
verify(listener, times(3)).callback1();
|
||||||
verify(listener).callback3();
|
verify(listener).callback3();
|
||||||
verify(listener).iterationFinished(Flags.create(EVENT_ID_1));
|
verify(listener).iterationFinished(createExoFlags(EVENT_ID_1));
|
||||||
verify(listener).iterationFinished(Flags.create(EVENT_ID_1, EVENT_ID_3));
|
verify(listener).iterationFinished(createExoFlags(EVENT_ID_1, EVENT_ID_3));
|
||||||
verifyNoMoreInteractions(listener);
|
verifyNoMoreInteractions(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,17 +402,14 @@ public class ListenerSetTest {
|
|||||||
|
|
||||||
default void callback3() {}
|
default void callback3() {}
|
||||||
|
|
||||||
default void iterationFinished(Flags flags) {}
|
default void iterationFinished(ExoFlags flags) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Flags extends MutableFlags {
|
private static ExoFlags createExoFlags(int... flagValues) {
|
||||||
|
ExoFlags.Builder flagsBuilder = new ExoFlags.Builder();
|
||||||
public static Flags create(int... flagValues) {
|
for (int value : flagValues) {
|
||||||
Flags flags = new Flags();
|
flagsBuilder.add(value);
|
||||||
for (int value : flagValues) {
|
|
||||||
flags.add(value);
|
|
||||||
}
|
|
||||||
return flags;
|
|
||||||
}
|
}
|
||||||
|
return flagsBuilder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ import java.util.List;
|
|||||||
private final HandlerWrapper playbackInfoUpdateHandler;
|
private final HandlerWrapper playbackInfoUpdateHandler;
|
||||||
private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener;
|
private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener;
|
||||||
private final ExoPlayerImplInternal internalPlayer;
|
private final ExoPlayerImplInternal internalPlayer;
|
||||||
private final ListenerSet<Player.EventListener, Player.Events> listeners;
|
private final ListenerSet<Player.EventListener> listeners;
|
||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
private final List<MediaSourceHolderSnapshot> mediaSourceHolderSnapshots;
|
private final List<MediaSourceHolderSnapshot> mediaSourceHolderSnapshots;
|
||||||
private final boolean useLazyPreparation;
|
private final boolean useLazyPreparation;
|
||||||
@ -165,8 +165,7 @@ import java.util.List;
|
|||||||
new ListenerSet<>(
|
new ListenerSet<>(
|
||||||
applicationLooper,
|
applicationLooper,
|
||||||
clock,
|
clock,
|
||||||
Player.Events::new,
|
(listener, flags) -> listener.onEvents(playerForListeners, new Events(flags)));
|
||||||
(listener, eventFlags) -> listener.onEvents(playerForListeners, eventFlags));
|
|
||||||
mediaSourceHolderSnapshots = new ArrayList<>();
|
mediaSourceHolderSnapshots = new ArrayList<>();
|
||||||
shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0);
|
shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0);
|
||||||
emptyTrackSelectorResult =
|
emptyTrackSelectorResult =
|
||||||
|
@ -78,7 +78,7 @@ public class AnalyticsCollector
|
|||||||
private final MediaPeriodQueueTracker mediaPeriodQueueTracker;
|
private final MediaPeriodQueueTracker mediaPeriodQueueTracker;
|
||||||
private final SparseArray<EventTime> eventTimes;
|
private final SparseArray<EventTime> eventTimes;
|
||||||
|
|
||||||
private ListenerSet<AnalyticsListener, AnalyticsListener.Events> listeners;
|
private ListenerSet<AnalyticsListener> listeners;
|
||||||
private @MonotonicNonNull Player player;
|
private @MonotonicNonNull Player player;
|
||||||
private boolean isSeeking;
|
private boolean isSeeking;
|
||||||
|
|
||||||
@ -89,12 +89,7 @@ public class AnalyticsCollector
|
|||||||
*/
|
*/
|
||||||
public AnalyticsCollector(Clock clock) {
|
public AnalyticsCollector(Clock clock) {
|
||||||
this.clock = checkNotNull(clock);
|
this.clock = checkNotNull(clock);
|
||||||
listeners =
|
listeners = new ListenerSet<>(Util.getCurrentOrMainLooper(), clock, (listener, flags) -> {});
|
||||||
new ListenerSet<>(
|
|
||||||
Util.getCurrentOrMainLooper(),
|
|
||||||
clock,
|
|
||||||
AnalyticsListener.Events::new,
|
|
||||||
(listener, eventFlags) -> {});
|
|
||||||
period = new Period();
|
period = new Period();
|
||||||
window = new Window();
|
window = new Window();
|
||||||
mediaPeriodQueueTracker = new MediaPeriodQueueTracker(period);
|
mediaPeriodQueueTracker = new MediaPeriodQueueTracker(period);
|
||||||
@ -137,10 +132,8 @@ public class AnalyticsCollector
|
|||||||
listeners =
|
listeners =
|
||||||
listeners.copy(
|
listeners.copy(
|
||||||
looper,
|
looper,
|
||||||
(listener, events) -> {
|
(listener, flags) ->
|
||||||
events.setEventTimes(eventTimes);
|
listener.onEvents(player, new AnalyticsListener.Events(flags, eventTimes)));
|
||||||
listener.onEvents(player, events);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +47,7 @@ import com.google.android.exoplayer2.source.MediaLoadData;
|
|||||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.util.MutableFlags;
|
import com.google.android.exoplayer2.util.ExoFlags;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
@ -70,13 +70,27 @@ import java.util.List;
|
|||||||
public interface AnalyticsListener {
|
public interface AnalyticsListener {
|
||||||
|
|
||||||
/** A set of {@link EventFlags}. */
|
/** A set of {@link EventFlags}. */
|
||||||
final class Events extends MutableFlags {
|
final class Events {
|
||||||
|
|
||||||
|
private final ExoFlags flags;
|
||||||
private final SparseArray<EventTime> eventTimes;
|
private final SparseArray<EventTime> eventTimes;
|
||||||
|
|
||||||
/** Creates the set of event flags. */
|
/**
|
||||||
public Events() {
|
* Creates an instance.
|
||||||
eventTimes = new SparseArray<>(/* initialCapacity= */ 0);
|
*
|
||||||
|
* @param flags The {@link ExoFlags} containing the {@link EventFlags} in the set.
|
||||||
|
* @param eventTimes A map from {@link EventFlags} to {@link EventTime}. Must at least contain
|
||||||
|
* all the events recorded in {@code flags}. Events that are not recorded in {@code flags}
|
||||||
|
* are ignored.
|
||||||
|
*/
|
||||||
|
public Events(ExoFlags flags, SparseArray<EventTime> eventTimes) {
|
||||||
|
this.flags = flags;
|
||||||
|
SparseArray<EventTime> flagsToTimes = new SparseArray<>(/* initialCapacity= */ flags.size());
|
||||||
|
for (int i = 0; i < flags.size(); i++) {
|
||||||
|
@EventFlags int eventFlag = flags.get(i);
|
||||||
|
flagsToTimes.append(eventFlag, checkNotNull(eventTimes.get(eventFlag)));
|
||||||
|
}
|
||||||
|
this.eventTimes = flagsToTimes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,30 +103,14 @@ public interface AnalyticsListener {
|
|||||||
return checkNotNull(eventTimes.get(event));
|
return checkNotNull(eventTimes.get(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link EventTime} values for events recorded in this set.
|
|
||||||
*
|
|
||||||
* @param eventTimes A map from {@link EventFlags} to {@link EventTime}. Must at least contain
|
|
||||||
* all the events recorded in this set.
|
|
||||||
*/
|
|
||||||
public void setEventTimes(SparseArray<EventTime> eventTimes) {
|
|
||||||
this.eventTimes.clear();
|
|
||||||
for (int i = 0; i < size(); i++) {
|
|
||||||
@EventFlags int eventFlag = get(i);
|
|
||||||
this.eventTimes.append(eventFlag, checkNotNull(eventTimes.get(eventFlag)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given event occurred.
|
* Returns whether the given event occurred.
|
||||||
*
|
*
|
||||||
* @param event The {@link EventFlags event}.
|
* @param event The {@link EventFlags event}.
|
||||||
* @return Whether the event occurred.
|
* @return Whether the event occurred.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public boolean contains(@EventFlags int event) {
|
public boolean contains(@EventFlags int event) {
|
||||||
// Overridden to add IntDef compiler enforcement and new JavaDoc.
|
return flags.contains(event);
|
||||||
return super.contains(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,10 +119,13 @@ public interface AnalyticsListener {
|
|||||||
* @param events The {@link EventFlags events}.
|
* @param events The {@link EventFlags events}.
|
||||||
* @return Whether any of the events occurred.
|
* @return Whether any of the events occurred.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public boolean containsAny(@EventFlags int... events) {
|
public boolean containsAny(@EventFlags int... events) {
|
||||||
// Overridden to add IntDef compiler enforcement and new JavaDoc.
|
return flags.containsAny(events);
|
||||||
return super.containsAny(events);
|
}
|
||||||
|
|
||||||
|
/** Returns the number of events in the set. */
|
||||||
|
public int size() {
|
||||||
|
return flags.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,11 +137,9 @@ public interface AnalyticsListener {
|
|||||||
* @param index The index. Must be between 0 (inclusive) and {@link #size()} (exclusive).
|
* @param index The index. Must be between 0 (inclusive) and {@link #size()} (exclusive).
|
||||||
* @return The {@link EventFlags event} at the given index.
|
* @return The {@link EventFlags event} at the given index.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
@EventFlags
|
@EventFlags
|
||||||
public int get(int index) {
|
public int get(int index) {
|
||||||
// Overridden to add IntDef compiler enforcement and new JavaDoc.
|
return flags.get(index);
|
||||||
return super.get(index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user