Skip to content

Commit

Permalink
Fix more cases of downloads not being resumed
Browse files Browse the repository at this point in the history
Issue: #7453
PiperOrigin-RevId: 314710328
  • Loading branch information
ojw28 committed Jun 4, 2020
1 parent a818049 commit 1347a22
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 18 deletions.
5 changes: 4 additions & 1 deletion RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Release notes #

### 2.11.5 (2020-06-03) ###
### 2.11.5 (2020-06-04) ###

* Improve the smoothness of video playback immediately after starting, seeking
or resuming a playback
Expand All @@ -17,6 +17,9 @@
* Fix issue in `AudioTrackPositionTracker` that could cause negative positions
to be reported at the start of playback and immediately after seeking
([#7456](https://github.com/google/ExoPlayer/issues/7456).
* Fix further cases where downloads would sometimes not resume after their
network requirements are met
([#7453](https://github.com/google/ExoPlayer/issues/7453).
* DASH:
* Merge trick play adaptation sets (i.e., adaptation sets marked with
`http://dashif.org/guidelines/trickmode`) into the same `TrackGroup` as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,9 @@ private int getNotMetNetworkRequirements(Context context) {
}

ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = Assertions.checkNotNull(connectivityManager).getActiveNetworkInfo();
if (networkInfo == null
|| !networkInfo.isConnected()
|| !isInternetConnectivityValidated(connectivityManager)) {
(ConnectivityManager)
Assertions.checkNotNull(context.getSystemService(Context.CONNECTIVITY_SERVICE));
if (!isInternetConnectivityValidated(connectivityManager)) {
return requirements & (NETWORK | NETWORK_UNMETERED);
}

Expand All @@ -156,23 +154,28 @@ private boolean isDeviceCharging(Context context) {
}

private boolean isDeviceIdle(Context context) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager powerManager =
(PowerManager) Assertions.checkNotNull(context.getSystemService(Context.POWER_SERVICE));
return Util.SDK_INT >= 23
? powerManager.isDeviceIdleMode()
: Util.SDK_INT >= 20 ? !powerManager.isInteractive() : !powerManager.isScreenOn();
}

private static boolean isInternetConnectivityValidated(ConnectivityManager connectivityManager) {
// It's possible to query NetworkCapabilities from API level 23, but RequirementsWatcher only
// fires an event to update its Requirements when NetworkCapabilities change from API level 24.
// Since Requirements won't be updated, we assume connectivity is validated on API level 23.
// It's possible to check NetworkCapabilities.NET_CAPABILITY_VALIDATED from API level 23, but
// RequirementsWatcher only fires an event to re-check the requirements when NetworkCapabilities
// change from API level 24. We use the legacy path for API level 23 here to keep in sync.
if (Util.SDK_INT < 24) {
return true;
// Legacy path.
@Nullable NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
Network activeNetwork = connectivityManager.getActiveNetwork();

@Nullable Network activeNetwork = connectivityManager.getActiveNetwork();
if (activeNetwork == null) {
return false;
}
@Nullable
NetworkCapabilities networkCapabilities =
connectivityManager.getNetworkCapabilities(activeNetwork);
return networkCapabilities != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,23 @@ private void checkRequirements() {
}
}

/**
* Re-checks the requirements if there are network requirements that are currently not met.
*
* <p>When we receive an event that implies newly established network connectivity, we re-check
* the requirements by calling {@link #checkRequirements()}. This check sometimes sees that there
* is still no active network, meaning that any network requirements will remain not met. By
* calling this method when we receive other events that imply continued network connectivity, we
* can detect that the requirements are met once an active network does exist.
*/
private void recheckNotMetNetworkRequirements() {
if ((notMetRequirements & (Requirements.NETWORK | Requirements.NETWORK_UNMETERED)) == 0) {
// No unmet network requirements to recheck.
return;
}
checkRequirements();
}

private class DeviceStatusChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Expand All @@ -161,17 +178,25 @@ public void onReceive(Context context, Intent intent) {

@RequiresApi(24)
private final class NetworkCallback extends ConnectivityManager.NetworkCallback {
boolean receivedCapabilitiesChange;
boolean networkValidated;

private boolean receivedCapabilitiesChange;
private boolean networkValidated;

@Override
public void onAvailable(Network network) {
onNetworkCallback();
postCheckRequirements();
}

@Override
public void onLost(Network network) {
onNetworkCallback();
postCheckRequirements();
}

@Override
public void onBlockedStatusChanged(Network network, boolean blocked) {
if (!blocked) {
postRecheckNotMetNetworkRequirements();
}
}

@Override
Expand All @@ -181,17 +206,28 @@ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCa
if (!receivedCapabilitiesChange || this.networkValidated != networkValidated) {
receivedCapabilitiesChange = true;
this.networkValidated = networkValidated;
onNetworkCallback();
postCheckRequirements();
} else if (networkValidated) {
postRecheckNotMetNetworkRequirements();
}
}

private void onNetworkCallback() {
private void postCheckRequirements() {
handler.post(
() -> {
if (networkCallback != null) {
checkRequirements();
}
});
}

private void postRecheckNotMetNetworkRequirements() {
handler.post(
() -> {
if (networkCallback != null) {
recheckNotMetNetworkRequirements();
}
});
}
}
}

0 comments on commit 1347a22

Please sign in to comment.