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,26 +296,24 @@ import java.util.UUID;
case DefaultDrmSessionManager.MODE_QUERY:
if (offlineLicenseKeySetId == null) {
postKeyRequest(ExoMediaDrm.KEY_TYPE_STREAMING, allowRetry);
} else {
if (restoreKeys()) {
long licenseDurationRemainingSec = getLicenseDurationRemainingSec();
if (mode == DefaultDrmSessionManager.MODE_PLAYBACK
&& licenseDurationRemainingSec <= MAX_LICENSE_DURATION_TO_RENEW) {
Log.d(TAG, "Offline license has expired or will expire soon. "
+ "Remaining seconds: " + licenseDurationRemainingSec);
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
} else if (licenseDurationRemainingSec <= 0) {
onError(new KeysExpiredException());
} else {
state = STATE_OPENED_WITH_KEYS;
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onDrmKeysRestored();
}
});
}
} else if (state == STATE_OPENED_WITH_KEYS || restoreKeys()) {
long licenseDurationRemainingSec = getLicenseDurationRemainingSec();
if (mode == DefaultDrmSessionManager.MODE_PLAYBACK
&& licenseDurationRemainingSec <= MAX_LICENSE_DURATION_TO_RENEW) {
Log.d(TAG, "Offline license has expired or will expire soon. "
+ "Remaining seconds: " + licenseDurationRemainingSec);
postKeyRequest(ExoMediaDrm.KEY_TYPE_OFFLINE, allowRetry);
} else if (licenseDurationRemainingSec <= 0) {
onError(new KeysExpiredException());
} else {
state = STATE_OPENED_WITH_KEYS;
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onDrmKeysRestored();
}
});
}
}
}

View File

@ -108,21 +108,23 @@ public final class DashTestRunner {
private String widevineLicenseUrl;
private DataSource.Factory dataSourceFactory;
@TargetApi(18)
@SuppressWarnings("ResourceType")
public static boolean isL1WidevineAvailable(String mimeType) {
try {
// Force L3 if secure decoder is not available.
if (MediaCodecUtil.getDecoderInfo(mimeType, true) == null) {
return false;
if (Util.SDK_INT >= 18) {
try {
// Force L3 if secure decoder is not available.
if (MediaCodecUtil.getDecoderInfo(mimeType, true) == null) {
return false;
}
MediaDrm mediaDrm = MediaDrmBuilder.build();
String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY);
mediaDrm.release();
return WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty);
} catch (MediaCodecUtil.DecoderQueryException e) {
throw new IllegalStateException(e);
}
MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID);
String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY);
mediaDrm.release();
return WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty);
} catch (MediaCodecUtil.DecoderQueryException | UnsupportedSchemeException e) {
throw new IllegalStateException(e);
}
return false;
}
public DashTestRunner(String tag, HostActivity activity, Instrumentation instrumentation) {
@ -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,8 +67,10 @@ public final class DashWidevineOfflineTest extends ActivityInstrumentationTestCa
boolean useL1Widevine = DashTestRunner.isL1WidevineAvailable(MimeTypes.VIDEO_H264);
String widevineLicenseUrl = DashTestData.getWidevineLicenseUrl(true, useL1Widevine);
httpDataSourceFactory = new DefaultHttpDataSourceFactory(USER_AGENT);
offlineLicenseHelper = OfflineLicenseHelper.newWidevineInstance(widevineLicenseUrl,
httpDataSourceFactory);
if (Util.SDK_INT >= 18) {
offlineLicenseHelper = OfflineLicenseHelper.newWidevineInstance(widevineLicenseUrl,
httpDataSourceFactory);
}
}
@Override

View File

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