Commit 199b9d16 by olly Committed by marcbaechinger

Convergence: Continue decoupling UI from Core

Move AdsLoader inner classes that are also required by
the UI module into common.

PiperOrigin-RevId: 367414679
parent 53166e9a
......@@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.net.Uri;
import android.view.Surface;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
......@@ -38,8 +37,6 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.testutil.ActionSchedule;
import com.google.android.exoplayer2.testutil.ExoHostedTest;
......@@ -51,7 +48,6 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
......@@ -251,18 +247,7 @@ public final class ImaPlaybackTest {
/* adsId= */ adTagDataSpec.uri,
new DefaultMediaSourceFactory(dataSourceFactory),
Assertions.checkNotNull(imaAdsLoader),
new AdViewProvider() {
@Override
public ViewGroup getAdViewGroup() {
return overlayFrameLayout;
}
@Override
public ImmutableList<AdsLoader.OverlayInfo> getAdOverlayInfos() {
return ImmutableList.of();
}
});
() -> overlayFrameLayout);
}
@Override
......
......@@ -55,12 +55,12 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
import com.google.android.exoplayer2.source.ads.AdsLoader.OverlayInfo;
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
import com.google.android.exoplayer2.ui.AdOverlayInfo;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
......@@ -318,7 +318,7 @@ import java.util.Map;
new AdPlaybackState(adsId, getAdGroupTimesUsForCuePoints(adsManager.getAdCuePoints()));
updateAdPlaybackState();
}
for (OverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
for (AdOverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
adDisplayContainer.registerFriendlyObstruction(
imaFactory.createFriendlyObstruction(
overlayInfo.view,
......
......@@ -48,6 +48,7 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
......
......@@ -36,7 +36,7 @@ import com.google.ads.interactivemedia.v3.api.UiElement;
import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer;
import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.source.ads.AdsLoader.OverlayInfo;
import com.google.android.exoplayer2.ui.AdOverlayInfo;
import com.google.android.exoplayer2.upstream.DataSchemeDataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Util;
......@@ -138,18 +138,18 @@ import java.util.Set;
/**
* Returns the IMA {@link FriendlyObstructionPurpose} corresponding to the given {@link
* OverlayInfo#purpose}.
* AdOverlayInfo#purpose}.
*/
public static FriendlyObstructionPurpose getFriendlyObstructionPurpose(
@OverlayInfo.Purpose int purpose) {
@AdOverlayInfo.Purpose int purpose) {
switch (purpose) {
case OverlayInfo.PURPOSE_CONTROLS:
case AdOverlayInfo.PURPOSE_CONTROLS:
return FriendlyObstructionPurpose.VIDEO_CONTROLS;
case OverlayInfo.PURPOSE_CLOSE_AD:
case AdOverlayInfo.PURPOSE_CLOSE_AD:
return FriendlyObstructionPurpose.CLOSE_AD;
case OverlayInfo.PURPOSE_NOT_VISIBLE:
case AdOverlayInfo.PURPOSE_NOT_VISIBLE:
return FriendlyObstructionPurpose.NOT_VISIBLE;
case OverlayInfo.PURPOSE_OTHER:
case AdOverlayInfo.PURPOSE_OTHER:
default:
return FriendlyObstructionPurpose.OTHER;
}
......
......@@ -68,6 +68,8 @@ import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
import com.google.android.exoplayer2.testutil.FakeMediaSource;
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
import com.google.android.exoplayer2.ui.AdOverlayInfo;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
......@@ -129,8 +131,8 @@ public final class ImaAdsLoaderTest {
private TimelineWindowDefinition[] timelineWindowDefinitions;
private AdsMediaSource adsMediaSource;
private ViewGroup adViewGroup;
private AdsLoader.AdViewProvider adViewProvider;
private AdsLoader.AdViewProvider audioAdsAdViewProvider;
private AdViewProvider adViewProvider;
private AdViewProvider audioAdsAdViewProvider;
private AdEvent.AdEventListener adEventListener;
private ContentProgressProvider contentProgressProvider;
private VideoAdPlayer videoAdPlayer;
......@@ -145,30 +147,19 @@ public final class ImaAdsLoaderTest {
adViewGroup = new FrameLayout(getApplicationContext());
View adOverlayView = new View(getApplicationContext());
adViewProvider =
new AdsLoader.AdViewProvider() {
new AdViewProvider() {
@Override
public ViewGroup getAdViewGroup() {
return adViewGroup;
}
@Override
public ImmutableList<AdsLoader.OverlayInfo> getAdOverlayInfos() {
public ImmutableList<AdOverlayInfo> getAdOverlayInfos() {
return ImmutableList.of(
new AdsLoader.OverlayInfo(adOverlayView, AdsLoader.OverlayInfo.PURPOSE_CLOSE_AD));
}
};
audioAdsAdViewProvider =
new AdsLoader.AdViewProvider() {
@Override
public ViewGroup getAdViewGroup() {
return null;
}
@Override
public ImmutableList<AdsLoader.OverlayInfo> getAdOverlayInfos() {
return ImmutableList.of();
new AdOverlayInfo(adOverlayView, AdOverlayInfo.PURPOSE_CLOSE_AD));
}
};
audioAdsAdViewProvider = () -> null;
imaAdsLoader =
new ImaAdsLoader.Builder(getApplicationContext())
.setImaFactory(mockImaFactory)
......
/*
* Copyright (C) 2021 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.ui;
import android.view.View;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** Provides information about an overlay view shown on top of an ad view group. */
public final class AdOverlayInfo {
/**
* The purpose of the overlay. One of {@link #PURPOSE_CONTROLS}, {@link #PURPOSE_CLOSE_AD}, {@link
* #PURPOSE_OTHER} or {@link #PURPOSE_NOT_VISIBLE}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({PURPOSE_CONTROLS, PURPOSE_CLOSE_AD, PURPOSE_OTHER, PURPOSE_NOT_VISIBLE})
public @interface Purpose {}
/** Purpose for playback controls overlaying the player. */
public static final int PURPOSE_CONTROLS = 0;
/** Purpose for ad close buttons overlaying the player. */
public static final int PURPOSE_CLOSE_AD = 1;
/** Purpose for other overlays. */
public static final int PURPOSE_OTHER = 2;
/** Purpose for overlays that are not visible. */
public static final int PURPOSE_NOT_VISIBLE = 3;
/** The overlay view. */
public final View view;
/** The purpose of the overlay view. */
@Purpose public final int purpose;
/** An optional, detailed reason that the overlay view is needed. */
@Nullable public final String reasonDetail;
/**
* Creates a new overlay info.
*
* @param view The view that is overlaying the player.
* @param purpose The purpose of the view.
*/
public AdOverlayInfo(View view, @Purpose int purpose) {
this(view, purpose, /* detailedReason= */ null);
}
/**
* Creates a new overlay info.
*
* @param view The view that is overlaying the player.
* @param purpose The purpose of the view.
* @param detailedReason An optional, detailed reason that the view is on top of the player.
*/
public AdOverlayInfo(View view, @Purpose int purpose, @Nullable String detailedReason) {
this.view = view;
this.purpose = purpose;
this.reasonDetail = detailedReason;
}
}
/*
* Copyright (C) 2021 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.ui;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import java.util.List;
/** Provides information about views for the ad playback UI. */
public interface AdViewProvider {
/**
* Returns the {@link ViewGroup} on top of the player that will show any ad UI, or {@code null} if
* playing audio-only ads. Any views on top of the returned view group must be described by {@link
* AdOverlayInfo AdOverlayInfos} returned by {@link #getAdOverlayInfos()}, for accurate
* viewability measurement.
*/
@Nullable
ViewGroup getAdViewGroup();
/**
* Returns a list of {@link AdOverlayInfo} instances describing views that are on top of the ad
* view group, but that are essential for controlling playback and should be excluded from ad
* viewability measurements.
*
* <p>Each view must be either a fully transparent overlay (for capturing touch events), or a
* small piece of transient UI that is essential to the user experience of playback (such as a
* button to pause/resume playback or a transient full-screen or cast button). For more
* information see the documentation for your ads loader.
*/
default List<AdOverlayInfo> getAdOverlayInfos() {
return ImmutableList.of();
}
}
......@@ -29,8 +29,8 @@ import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
......
......@@ -15,20 +15,13 @@
*/
package com.google.android.exoplayer2.source.ads;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* Interface for loaders of ads, which can be used with {@link AdsMediaSource}.
......@@ -78,94 +71,6 @@ public interface AdsLoader {
default void onAdTapped() {}
}
/** Provides information about views for the ad playback UI. */
interface AdViewProvider {
/**
* Returns the {@link ViewGroup} on top of the player that will show any ad UI, or {@code null}
* if playing audio-only ads. Any views on top of the returned view group must be described by
* {@link OverlayInfo OverlayInfos} returned by {@link #getAdOverlayInfos()}, for accurate
* viewability measurement.
*/
@Nullable
ViewGroup getAdViewGroup();
/** @deprecated Use {@link #getAdOverlayInfos()} instead. */
@Deprecated
default View[] getAdOverlayViews() {
return new View[0];
}
/**
* Returns a list of {@link OverlayInfo} instances describing views that are on top of the ad
* view group, but that are essential for controlling playback and should be excluded from ad
* viewability measurements by the {@link AdsLoader} (if it supports this).
*
* <p>Each view must be either a fully transparent overlay (for capturing touch events), or a
* small piece of transient UI that is essential to the user experience of playback (such as a
* button to pause/resume playback or a transient full-screen or cast button). For more
* information see the documentation for your ads loader.
*/
@SuppressWarnings("deprecation")
default List<OverlayInfo> getAdOverlayInfos() {
ImmutableList.Builder<OverlayInfo> listBuilder = new ImmutableList.Builder<>();
// Call through to deprecated version.
for (View view : getAdOverlayViews()) {
listBuilder.add(new OverlayInfo(view, OverlayInfo.PURPOSE_CONTROLS));
}
return listBuilder.build();
}
}
/** Provides information about an overlay view shown on top of an ad view group. */
final class OverlayInfo {
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({PURPOSE_CONTROLS, PURPOSE_CLOSE_AD, PURPOSE_OTHER, PURPOSE_NOT_VISIBLE})
public @interface Purpose {}
/** Purpose for playback controls overlaying the player. */
public static final int PURPOSE_CONTROLS = 0;
/** Purpose for ad close buttons overlaying the player. */
public static final int PURPOSE_CLOSE_AD = 1;
/** Purpose for other overlays. */
public static final int PURPOSE_OTHER = 2;
/** Purpose for overlays that are not visible. */
public static final int PURPOSE_NOT_VISIBLE = 3;
/** The overlay view. */
public final View view;
/** The purpose of the overlay view. */
@Purpose public final int purpose;
/** An optional, detailed reason that the overlay view is needed. */
@Nullable public final String reasonDetail;
/**
* Creates a new overlay info.
*
* @param view The view that is overlaying the player.
* @param purpose The purpose of the view.
*/
public OverlayInfo(View view, @Purpose int purpose) {
this(view, purpose, /* detailedReason= */ null);
}
/**
* Creates a new overlay info.
*
* @param view The view that is overlaying the player.
* @param purpose The purpose of the view.
* @param detailedReason An optional, detailed reason that the view is on top of the player. See
* the documentation for the {@link AdsLoader} implementation for more information on this
* string's formatting.
*/
public OverlayInfo(View view, @Purpose int purpose, @Nullable String detailedReason) {
this.view = view;
this.purpose = purpose;
this.reasonDetail = detailedReason;
}
}
// Methods called by the application.
/**
......
......@@ -36,6 +36,7 @@ import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
......@@ -128,7 +129,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
private final MediaSource contentMediaSource;
private final MediaSourceFactory adMediaSourceFactory;
private final AdsLoader adsLoader;
private final AdsLoader.AdViewProvider adViewProvider;
private final AdViewProvider adViewProvider;
private final DataSpec adTagDataSpec;
private final Object adsId;
private final Handler mainHandler;
......@@ -160,7 +161,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
Object adsId,
MediaSourceFactory adMediaSourceFactory,
AdsLoader adsLoader,
AdsLoader.AdViewProvider adViewProvider) {
AdViewProvider adViewProvider) {
this.contentMediaSource = contentMediaSource;
this.adMediaSourceFactory = adMediaSourceFactory;
this.adsLoader = adsLoader;
......
......@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Arrays;
import java.util.Collections;
......@@ -205,7 +206,7 @@ public final class DefaultMediaSourceFactoryTest {
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext())
.setAdsLoaderProvider(ignoredAdsConfiguration -> mock(AdsLoader.class))
.setAdViewProvider(mock(AdsLoader.AdViewProvider.class));
.setAdViewProvider(mock(AdViewProvider.class));
MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem);
......
......@@ -34,9 +34,9 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
import com.google.android.exoplayer2.testutil.FakeMediaSource;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSpec;
import org.junit.Before;
......
......@@ -54,7 +54,6 @@ import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.flac.PictureFrame;
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
......@@ -264,7 +263,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* PlayerView. This will cause the specified layout to be inflated instead of {@code
* exo_player_view.xml} for only the instance on which the attribute is set.
*/
public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider {
public class PlayerView extends FrameLayout implements AdViewProvider {
// LINT.IfChange
/**
......@@ -1233,18 +1232,17 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
}
@Override
public List<AdsLoader.OverlayInfo> getAdOverlayInfos() {
List<AdsLoader.OverlayInfo> overlayViews = new ArrayList<>();
public List<AdOverlayInfo> getAdOverlayInfos() {
List<AdOverlayInfo> overlayViews = new ArrayList<>();
if (overlayFrameLayout != null) {
overlayViews.add(
new AdsLoader.OverlayInfo(
new AdOverlayInfo(
overlayFrameLayout,
AdsLoader.OverlayInfo.PURPOSE_NOT_VISIBLE,
AdOverlayInfo.PURPOSE_NOT_VISIBLE,
/* detailedReason= */ "Transparent overlay does not impact viewability"));
}
if (controller != null) {
overlayViews.add(
new AdsLoader.OverlayInfo(controller, AdsLoader.OverlayInfo.PURPOSE_CONTROLS));
overlayViews.add(new AdOverlayInfo(controller, AdOverlayInfo.PURPOSE_CONTROLS));
}
return ImmutableList.copyOf(overlayViews);
}
......
......@@ -56,7 +56,6 @@ import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.flac.PictureFrame;
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
......@@ -266,7 +265,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* attribute on a StyledPlayerView. This will cause the specified layout to be inflated instead of
* {@code exo_styled_player_view.xml} for only the instance on which the attribute is set.
*/
public class StyledPlayerView extends FrameLayout implements AdsLoader.AdViewProvider {
public class StyledPlayerView extends FrameLayout implements AdViewProvider {
// LINT.IfChange
/**
......@@ -1251,18 +1250,17 @@ public class StyledPlayerView extends FrameLayout implements AdsLoader.AdViewPro
}
@Override
public List<AdsLoader.OverlayInfo> getAdOverlayInfos() {
List<AdsLoader.OverlayInfo> overlayViews = new ArrayList<>();
public List<AdOverlayInfo> getAdOverlayInfos() {
List<AdOverlayInfo> overlayViews = new ArrayList<>();
if (overlayFrameLayout != null) {
overlayViews.add(
new AdsLoader.OverlayInfo(
new AdOverlayInfo(
overlayFrameLayout,
AdsLoader.OverlayInfo.PURPOSE_NOT_VISIBLE,
AdOverlayInfo.PURPOSE_NOT_VISIBLE,
/* detailedReason= */ "Transparent overlay does not impact viewability"));
}
if (controller != null) {
overlayViews.add(
new AdsLoader.OverlayInfo(controller, AdsLoader.OverlayInfo.PURPOSE_CONTROLS));
overlayViews.add(new AdOverlayInfo(controller, AdOverlayInfo.PURPOSE_CONTROLS));
}
return ImmutableList.copyOf(overlayViews);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment