Fix MobileHarness playback tests.

This change fixes various issues:
 - MobileHarness sometimes allocated devices with SDK < 16. As we have no tests running
   on these SDKs, a new dimension filter for the mobile_test target ensures that only
   devices with SDK >= 16 are selected. A similar filter for SDK version is also added
   to the ABR playback tests to ensure no old devices are selected.
 - DRM specific tests are skipped for Api < 18, but were not able to run because the
   DashTestRunner class tried to link to the MediaDrm constructor. Moved the
   constructor to a seperate Builder class to allow execution on Api levels 16 and 17.
 - DashWidevineOfflineTest also tried to access code for Api >= 18 without checking
   the current level.
 - Action implementations which are waiting for events did not ensure that they have a
   nextAction to wait for. This caused NullPointerExceptions when this next action was
   scheduled.
 - DefaultDrmSession always restored the offline keys when a new license was requested,
   even if the keys were already restored. These repeated slow calls to restoreKeys
   resulted in high numbers of dropped buffers.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=171974859
This commit is contained in:
tonihei 2017-10-12 10:12:04 -07:00 committed by Oliver Woodman
parent 333e745e7b
commit b71effb7b0
4 changed files with 64 additions and 33 deletions

View File

@ -296,8 +296,7 @@ import java.util.UUID;
case DefaultDrmSessionManager.MODE_QUERY: case DefaultDrmSessionManager.MODE_QUERY:
if (offlineLicenseKeySetId == null) { if (offlineLicenseKeySetId == null) {
postKeyRequest(ExoMediaDrm.KEY_TYPE_STREAMING, allowRetry); postKeyRequest(ExoMediaDrm.KEY_TYPE_STREAMING, allowRetry);
} else { } else if (state == STATE_OPENED_WITH_KEYS || restoreKeys()) {
if (restoreKeys()) {
long licenseDurationRemainingSec = getLicenseDurationRemainingSec(); long licenseDurationRemainingSec = getLicenseDurationRemainingSec();
if (mode == DefaultDrmSessionManager.MODE_PLAYBACK if (mode == DefaultDrmSessionManager.MODE_PLAYBACK
&& licenseDurationRemainingSec <= MAX_LICENSE_DURATION_TO_RENEW) { && licenseDurationRemainingSec <= MAX_LICENSE_DURATION_TO_RENEW) {
@ -318,7 +317,6 @@ import java.util.UUID;
} }
} }
} }
}
break; break;
case DefaultDrmSessionManager.MODE_DOWNLOAD: case DefaultDrmSessionManager.MODE_DOWNLOAD:
if (offlineLicenseKeySetId == null) { if (offlineLicenseKeySetId == null) {

View File

@ -108,22 +108,24 @@ public final class DashTestRunner {
private String widevineLicenseUrl; private String widevineLicenseUrl;
private DataSource.Factory dataSourceFactory; private DataSource.Factory dataSourceFactory;
@TargetApi(18)
@SuppressWarnings("ResourceType") @SuppressWarnings("ResourceType")
public static boolean isL1WidevineAvailable(String mimeType) { public static boolean isL1WidevineAvailable(String mimeType) {
if (Util.SDK_INT >= 18) {
try { try {
// Force L3 if secure decoder is not available. // Force L3 if secure decoder is not available.
if (MediaCodecUtil.getDecoderInfo(mimeType, true) == null) { if (MediaCodecUtil.getDecoderInfo(mimeType, true) == null) {
return false; return false;
} }
MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); MediaDrm mediaDrm = MediaDrmBuilder.build();
String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY);
mediaDrm.release(); mediaDrm.release();
return WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty); return WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty);
} catch (MediaCodecUtil.DecoderQueryException | UnsupportedSchemeException e) { } catch (MediaCodecUtil.DecoderQueryException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
return false;
}
public DashTestRunner(String tag, HostActivity activity, Instrumentation instrumentation) { public DashTestRunner(String tag, HostActivity activity, Instrumentation instrumentation) {
this.tag = tag; this.tag = tag;
@ -457,4 +459,21 @@ public final class DashTestRunner {
} }
/**
* Creates a new {@code MediaDrm} object. The encapsulation ensures that the tests can be
* executed for API level < 18.
*/
@TargetApi(18)
private static final class MediaDrmBuilder {
public static MediaDrm build () {
try {
return new MediaDrm(WIDEVINE_UUID);
} catch (UnsupportedSchemeException e) {
throw new IllegalStateException(e);
}
}
}
} }

View File

@ -67,9 +67,11 @@ public final class DashWidevineOfflineTest extends ActivityInstrumentationTestCa
boolean useL1Widevine = DashTestRunner.isL1WidevineAvailable(MimeTypes.VIDEO_H264); boolean useL1Widevine = DashTestRunner.isL1WidevineAvailable(MimeTypes.VIDEO_H264);
String widevineLicenseUrl = DashTestData.getWidevineLicenseUrl(true, useL1Widevine); String widevineLicenseUrl = DashTestData.getWidevineLicenseUrl(true, useL1Widevine);
httpDataSourceFactory = new DefaultHttpDataSourceFactory(USER_AGENT); httpDataSourceFactory = new DefaultHttpDataSourceFactory(USER_AGENT);
if (Util.SDK_INT >= 18) {
offlineLicenseHelper = OfflineLicenseHelper.newWidevineInstance(widevineLicenseUrl, offlineLicenseHelper = OfflineLicenseHelper.newWidevineInstance(widevineLicenseUrl,
httpDataSourceFactory); httpDataSourceFactory);
} }
}
@Override @Override
protected void tearDown() throws Exception { protected void tearDown() throws Exception {

View File

@ -322,6 +322,9 @@ public abstract class Action {
protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player,
final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler,
final ActionNode nextAction) { final ActionNode nextAction) {
if (nextAction == null) {
return;
}
Player.EventListener listener = new Player.DefaultEventListener() { Player.EventListener listener = new Player.DefaultEventListener() {
@Override @Override
public void onTimelineChanged(Timeline timeline, Object manifest) { public void onTimelineChanged(Timeline timeline, Object manifest) {
@ -362,6 +365,9 @@ public abstract class Action {
protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player,
final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler,
final ActionNode nextAction) { final ActionNode nextAction) {
if (nextAction == null) {
return;
}
player.addListener(new Player.DefaultEventListener() { player.addListener(new Player.DefaultEventListener() {
@Override @Override
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) { public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
@ -399,6 +405,9 @@ public abstract class Action {
protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player,
final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler,
final ActionNode nextAction) { final ActionNode nextAction) {
if (nextAction == null) {
return;
}
if (targetPlaybackState == player.getPlaybackState()) { if (targetPlaybackState == player.getPlaybackState()) {
nextAction.schedule(player, trackSelector, surface, handler); nextAction.schedule(player, trackSelector, surface, handler);
} else { } else {
@ -438,6 +447,9 @@ public abstract class Action {
protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player,
final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler,
final ActionNode nextAction) { final ActionNode nextAction) {
if (nextAction == null) {
return;
}
player.addListener(new Player.DefaultEventListener() { player.addListener(new Player.DefaultEventListener() {
@Override @Override
public void onSeekProcessed() { public void onSeekProcessed() {