Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
ec77f737
authored
Jan 16, 2019
by
eguven
Committed by
Oliver Woodman
Jan 17, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Make DownloadManager watch requirements directly
PiperOrigin-RevId: 229544734
parent
8adc16a6
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
245 additions
and
145 deletions
demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
library/core/src/main/java/com/google/android/exoplayer2/scheduler/Requirements.java
library/core/src/main/java/com/google/android/exoplayer2/scheduler/RequirementsWatcher.java
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java
demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java
View file @
ec77f737
...
...
@@ -101,10 +101,12 @@ public class DemoApplication extends Application {
new
DownloaderConstructorHelper
(
getDownloadCache
(),
buildHttpDataSourceFactory
());
downloadManager
=
new
DownloadManager
(
this
,
new
File
(
getDownloadDirectory
(),
DOWNLOAD_ACTION_FILE
),
new
DefaultDownloaderFactory
(
downloaderConstructorHelper
),
MAX_SIMULTANEOUS_DOWNLOADS
,
DownloadManager
.
DEFAULT_MIN_RETRY_COUNT
);
DownloadManager
.
DEFAULT_MIN_RETRY_COUNT
,
DownloadManager
.
DEFAULT_REQUIREMENTS
);
downloadTracker
=
new
DownloadTracker
(
/* context= */
this
,
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
View file @
ec77f737
...
...
@@ -41,6 +41,7 @@ import com.google.android.exoplayer2.offline.DownloadService;
import
com.google.android.exoplayer2.offline.DownloadState
;
import
com.google.android.exoplayer2.offline.ProgressiveDownloadHelper
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.dash.offline.DashDownloadHelper
;
import
com.google.android.exoplayer2.source.hls.offline.HlsDownloadHelper
;
...
...
@@ -159,6 +160,14 @@ public class DownloadTracker implements DownloadManager.Listener {
// Do nothing.
}
@Override
public
void
onRequirementsStateChanged
(
DownloadManager
downloadManager
,
Requirements
requirements
,
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
// Do nothing.
}
// Internal methods
private
void
loadTrackedActions
()
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
View file @
ec77f737
...
...
@@ -28,12 +28,15 @@ import static com.google.android.exoplayer2.offline.DownloadState.STATE_STOPPED;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadState
.
STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY
;
import
static
com
.
google
.
android
.
exoplayer2
.
offline
.
DownloadState
.
STOP_FLAG_STOPPED
;
import
android.content.Context
;
import
android.os.ConditionVariable
;
import
android.os.Handler
;
import
android.os.HandlerThread
;
import
android.os.Looper
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.RequirementsWatcher
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Log
;
import
java.io.File
;
...
...
@@ -74,18 +77,35 @@ public final class DownloadManager {
* @param downloadManager The reporting instance.
*/
void
onIdle
(
DownloadManager
downloadManager
);
/**
* Called when the download requirements state changed.
*
* @param downloadManager The reporting instance.
* @param requirements Requirements needed to be met to start downloads.
* @param notMetRequirements {@link Requirements.RequirementFlags RequirementFlags} that are not
* met, or 0.
*/
void
onRequirementsStateChanged
(
DownloadManager
downloadManager
,
Requirements
requirements
,
@Requirements
.
RequirementFlags
int
notMetRequirements
);
}
/** The default maximum number of simultaneous downloads. */
public
static
final
int
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
=
1
;
/** The default minimum number of times a download must be retried before failing. */
public
static
final
int
DEFAULT_MIN_RETRY_COUNT
=
5
;
/** The default requirement is that the device has network connectivity. */
public
static
final
Requirements
DEFAULT_REQUIREMENTS
=
new
Requirements
(
Requirements
.
NETWORK_TYPE_ANY
,
false
,
false
);
private
static
final
String
TAG
=
"DownloadManager"
;
private
static
final
boolean
DEBUG
=
false
;
private
final
int
maxActiveDownloads
;
private
final
int
minRetryCount
;
private
final
Context
context
;
private
final
ActionFile
actionFile
;
private
final
DownloaderFactory
downloaderFactory
;
private
final
ArrayList
<
Download
>
downloads
;
...
...
@@ -99,31 +119,43 @@ public final class DownloadManager {
private
boolean
initialized
;
private
boolean
released
;
@DownloadState
.
StopFlags
private
int
stickyStopFlags
;
private
RequirementsWatcher
requirementsWatcher
;
/**
* Constructs a {@link DownloadManager}.
*
* @param context Any context.
* @param actionFile The file in which active actions are saved.
* @param downloaderFactory A factory for creating {@link Downloader}s.
*/
public
DownloadManager
(
File
actionFile
,
DownloaderFactory
downloaderFactory
)
{
public
DownloadManager
(
Context
context
,
File
actionFile
,
DownloaderFactory
downloaderFactory
)
{
this
(
actionFile
,
downloaderFactory
,
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
,
DEFAULT_MIN_RETRY_COUNT
);
context
,
actionFile
,
downloaderFactory
,
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
,
DEFAULT_MIN_RETRY_COUNT
,
DEFAULT_REQUIREMENTS
);
}
/**
* Constructs a {@link DownloadManager}.
*
* @param context Any context.
* @param actionFile The file in which active actions are saved.
* @param downloaderFactory A factory for creating {@link Downloader}s.
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a download must be retried before failing.
* @param requirements The requirements needed to be met to start downloads.
*/
public
DownloadManager
(
Context
context
,
File
actionFile
,
DownloaderFactory
downloaderFactory
,
int
maxSimultaneousDownloads
,
int
minRetryCount
)
{
int
minRetryCount
,
Requirements
requirements
)
{
this
.
context
=
context
.
getApplicationContext
();
this
.
actionFile
=
new
ActionFile
(
actionFile
);
this
.
downloaderFactory
=
downloaderFactory
;
this
.
maxActiveDownloads
=
maxSimultaneousDownloads
;
...
...
@@ -146,11 +178,31 @@ public final class DownloadManager {
listeners
=
new
CopyOnWriteArraySet
<>();
actionQueue
=
new
ArrayDeque
<>();
watchRequirements
(
requirements
);
loadActions
();
logd
(
"Created"
);
}
/**
* Sets the requirements needed to be met to start downloads.
*
* @param requirements Need to be met to start downloads.
*/
public
void
setRequirements
(
Requirements
requirements
)
{
Assertions
.
checkState
(!
released
);
if
(
requirements
.
equals
(
requirementsWatcher
.
getRequirements
()))
{
return
;
}
requirementsWatcher
.
stop
();
notifyListenersRequirementsStateChange
(
watchRequirements
(
requirements
));
}
/** Returns the requirements needed to be met to start downloads. */
public
Requirements
getRequirements
()
{
return
requirementsWatcher
.
getRequirements
();
}
/**
* Adds a {@link Listener}.
*
* @param listener The listener to be added.
...
...
@@ -278,6 +330,9 @@ public final class DownloadManager {
}
setStopFlags
(
STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY
);
released
=
true
;
if
(
requirementsWatcher
!=
null
)
{
requirementsWatcher
.
stop
();
}
final
ConditionVariable
fileIOFinishedCondition
=
new
ConditionVariable
();
fileIOHandler
.
post
(
fileIOFinishedCondition:
:
open
);
fileIOFinishedCondition
.
block
();
...
...
@@ -346,6 +401,15 @@ public final class DownloadManager {
}
}
private
void
notifyListenersRequirementsStateChange
(
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
logdFlags
(
"Not met requirements are changed"
,
notMetRequirements
);
for
(
Listener
listener
:
listeners
)
{
listener
.
onRequirementsStateChanged
(
DownloadManager
.
this
,
requirementsWatcher
.
getRequirements
(),
notMetRequirements
);
}
}
private
void
loadActions
()
{
fileIOHandler
.
post
(
()
->
{
...
...
@@ -420,6 +484,18 @@ public final class DownloadManager {
}
}
@Requirements
.
RequirementFlags
private
int
watchRequirements
(
Requirements
requirements
)
{
requirementsWatcher
=
new
RequirementsWatcher
(
context
,
new
RequirementListener
(),
requirements
);
@Requirements
.
RequirementFlags
int
notMetRequirements
=
requirementsWatcher
.
start
();
if
(
notMetRequirements
==
0
)
{
startDownloads
();
}
else
{
stopDownloads
();
}
return
notMetRequirements
;
}
private
static
final
class
Download
{
private
final
String
id
;
...
...
@@ -693,4 +769,20 @@ public final class DownloadManager {
return
Math
.
min
((
errorCount
-
1
)
*
1000
,
5000
);
}
}
private
class
RequirementListener
implements
RequirementsWatcher
.
Listener
{
@Override
public
void
requirementsMet
(
RequirementsWatcher
requirementsWatcher
)
{
startDownloads
();
notifyListenersRequirementsStateChange
(
0
);
}
@Override
public
void
requirementsNotMet
(
RequirementsWatcher
requirementsWatcher
,
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
stopDownloads
();
notifyListenersRequirementsStateChange
(
notMetRequirements
);
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
View file @
ec77f737
...
...
@@ -25,8 +25,8 @@ import android.os.Looper;
import
android.support.annotation.Nullable
;
import
android.support.annotation.StringRes
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.RequirementsWatcher
;
import
com.google.android.exoplayer2.scheduler.Scheduler
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.NotificationUtil
;
import
com.google.android.exoplayer2.util.Util
;
...
...
@@ -43,10 +43,6 @@ public abstract class DownloadService extends Service {
/** Starts a download service, adding a new {@link DownloadAction} to be executed. */
public
static
final
String
ACTION_ADD
=
"com.google.android.exoplayer.downloadService.action.ADD"
;
/** Reloads the download requirements. */
public
static
final
String
ACTION_RELOAD_REQUIREMENTS
=
"com.google.android.exoplayer.downloadService.action.RELOAD_REQUIREMENTS"
;
/** Like {@link #ACTION_INIT}, but with {@link #KEY_FOREGROUND} implicitly set to true. */
private
static
final
String
ACTION_RESTART
=
"com.google.android.exoplayer.downloadService.action.RESTART"
;
...
...
@@ -70,20 +66,16 @@ public abstract class DownloadService extends Service {
private
static
final
String
TAG
=
"DownloadService"
;
private
static
final
boolean
DEBUG
=
false
;
// Keep the requirements helper for each DownloadService as long as there are downloads (and the
// process is running). This allows downloads to resume when there's no scheduler. It may also
// allow downloads the resume more quickly than when relying on the scheduler alone.
private
static
final
HashMap
<
Class
<?
extends
DownloadService
>,
RequirementsHelper
>
requirementsHelpers
=
new
HashMap
<>();
private
static
final
Requirements
DEFAULT_REQUIREMENTS
=
new
Requirements
(
Requirements
.
NETWORK_TYPE_ANY
,
false
,
false
);
// Keep DownloadManagerListeners for each DownloadService as long as there are downloads (and the
// process is running). This allows DownloadService to restart when there's no scheduler.
private
static
final
HashMap
<
Class
<?
extends
DownloadService
>,
DownloadManagerHelper
>
downloadManagerListeners
=
new
HashMap
<>();
private
final
@Nullable
ForegroundNotificationUpdater
foregroundNotificationUpdater
;
private
final
@Nullable
String
channelId
;
private
final
@StringRes
int
channelName
;
private
DownloadManager
downloadManager
;
private
DownloadManagerListener
downloadManagerListener
;
private
int
lastStartId
;
private
boolean
startedInForeground
;
private
boolean
taskRemoved
;
...
...
@@ -227,9 +219,16 @@ public abstract class DownloadService extends Service {
NotificationUtil
.
createNotificationChannel
(
this
,
channelId
,
channelName
,
NotificationUtil
.
IMPORTANCE_LOW
);
}
downloadManager
=
getDownloadManager
();
downloadManagerListener
=
new
DownloadManagerListener
();
downloadManager
.
addListener
(
downloadManagerListener
);
Class
<?
extends
DownloadService
>
clazz
=
getClass
();
DownloadManagerHelper
downloadManagerHelper
=
downloadManagerListeners
.
get
(
clazz
);
if
(
downloadManagerHelper
==
null
)
{
downloadManagerHelper
=
new
DownloadManagerHelper
(
getApplicationContext
(),
getDownloadManager
(),
getScheduler
(),
clazz
);
downloadManagerListeners
.
put
(
clazz
,
downloadManagerHelper
);
}
downloadManager
=
downloadManagerHelper
.
downloadManager
;
downloadManagerHelper
.
attachService
(
this
);
}
@Override
...
...
@@ -264,22 +263,11 @@ public abstract class DownloadService extends Service {
}
}
break
;
case
ACTION_RELOAD_REQUIREMENTS:
stopWatchingRequirements
();
break
;
default
:
Log
.
e
(
TAG
,
"Ignoring unrecognized action: "
+
intentAction
);
break
;
}
Requirements
requirements
=
getRequirements
();
if
(
requirements
.
checkRequirements
(
this
))
{
downloadManager
.
startDownloads
();
}
else
{
downloadManager
.
stopDownloads
();
}
maybeStartWatchingRequirements
(
requirements
);
if
(
downloadManager
.
isIdle
())
{
stop
();
}
...
...
@@ -295,11 +283,12 @@ public abstract class DownloadService extends Service {
@Override
public
void
onDestroy
()
{
logd
(
"onDestroy"
);
DownloadManagerHelper
downloadManagerHelper
=
downloadManagerListeners
.
get
(
getClass
());
boolean
unschedule
=
downloadManager
.
getDownloadCount
()
<=
0
;
downloadManagerHelper
.
detachService
(
this
,
unschedule
);
if
(
foregroundNotificationUpdater
!=
null
)
{
foregroundNotificationUpdater
.
stopPeriodicUpdates
();
}
downloadManager
.
removeListener
(
downloadManagerListener
);
maybeStopWatchingRequirements
();
}
/** DownloadService isn't designed to be bound. */
...
...
@@ -311,9 +300,7 @@ public abstract class DownloadService extends Service {
/**
* Returns a {@link DownloadManager} to be used to downloaded content. Called only once in the
* life cycle of the service. The service will call {@link DownloadManager#startDownloads()} and
* {@link DownloadManager#stopDownloads} as necessary when requirements returned by {@link
* #getRequirements()} are met or stop being met.
* life cycle of the process.
*/
protected
abstract
DownloadManager
getDownloadManager
();
...
...
@@ -325,14 +312,6 @@ public abstract class DownloadService extends Service {
protected
abstract
@Nullable
Scheduler
getScheduler
();
/**
* Returns requirements for downloads to take place. By default the only requirement is that the
* device has network connectivity.
*/
protected
Requirements
getRequirements
()
{
return
DEFAULT_REQUIREMENTS
;
}
/**
* Should be overridden in the subclass if the service will be run in the foreground.
*
* <p>Returns a notification to be displayed when this service running in the foreground.
...
...
@@ -363,32 +342,16 @@ public abstract class DownloadService extends Service {
// Do nothing.
}
private
void
maybeStartWatchingRequirements
(
Requirements
requirements
)
{
if
(
downloadManager
.
getDownloadCount
()
==
0
)
{
return
;
}
Class
<?
extends
DownloadService
>
clazz
=
getClass
();
RequirementsHelper
requirementsHelper
=
requirementsHelpers
.
get
(
clazz
);
if
(
requirementsHelper
==
null
)
{
requirementsHelper
=
new
RequirementsHelper
(
this
,
requirements
,
getScheduler
(),
clazz
);
requirementsHelpers
.
put
(
clazz
,
requirementsHelper
);
requirementsHelper
.
start
();
logd
(
"started watching requirements"
);
}
}
private
void
maybeStopWatchingRequirements
()
{
if
(
downloadManager
.
getDownloadCount
()
>
0
)
{
return
;
}
stopWatchingRequirements
();
}
private
void
stopWatchingRequirements
()
{
RequirementsHelper
requirementsHelper
=
requirementsHelpers
.
remove
(
getClass
());
if
(
requirementsHelper
!=
null
)
{
requirementsHelper
.
stop
();
logd
(
"stopped watching requirements"
);
private
void
notifyDownloadStateChange
(
DownloadState
downloadState
)
{
onDownloadStateChanged
(
downloadState
);
if
(
foregroundNotificationUpdater
!=
null
)
{
if
(
downloadState
.
state
==
DownloadState
.
STATE_DOWNLOADING
||
downloadState
.
state
==
DownloadState
.
STATE_REMOVING
||
downloadState
.
state
==
DownloadState
.
STATE_RESTARTING
)
{
foregroundNotificationUpdater
.
startPeriodicUpdates
();
}
else
{
foregroundNotificationUpdater
.
update
();
}
}
}
...
...
@@ -420,33 +383,6 @@ public abstract class DownloadService extends Service {
return
new
Intent
(
context
,
clazz
).
setAction
(
action
);
}
private
final
class
DownloadManagerListener
implements
DownloadManager
.
Listener
{
@Override
public
void
onInitialized
(
DownloadManager
downloadManager
)
{
maybeStartWatchingRequirements
(
getRequirements
());
}
@Override
public
void
onDownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
downloadState
)
{
DownloadService
.
this
.
onDownloadStateChanged
(
downloadState
);
if
(
foregroundNotificationUpdater
!=
null
)
{
if
(
downloadState
.
state
==
DownloadState
.
STATE_DOWNLOADING
||
downloadState
.
state
==
DownloadState
.
STATE_REMOVING
||
downloadState
.
state
==
DownloadState
.
STATE_RESTARTING
)
{
foregroundNotificationUpdater
.
startPeriodicUpdates
();
}
else
{
foregroundNotificationUpdater
.
update
();
}
}
}
@Override
public
final
void
onIdle
(
DownloadManager
downloadManager
)
{
stop
();
}
}
private
final
class
ForegroundNotificationUpdater
implements
Runnable
{
private
final
int
notificationId
;
...
...
@@ -494,58 +430,87 @@ public abstract class DownloadService extends Service {
}
}
private
static
final
class
RequirementsHelper
implements
RequirementsWatch
er
.
Listener
{
private
static
final
class
DownloadManagerHelper
implements
DownloadManag
er
.
Listener
{
private
final
Context
context
;
private
final
Requirements
requirements
;
private
final
@Nullable
Scheduler
scheduler
;
private
final
DownloadManager
downloadManager
;
@Nullable
private
final
Scheduler
scheduler
;
private
final
Class
<?
extends
DownloadService
>
serviceClass
;
private
final
RequirementsWatcher
requirementsWatcher
;
@Nullable
private
DownloadService
downloadService
;
private
Requirements
Helper
(
private
DownloadManager
Helper
(
Context
context
,
Requirements
requirements
,
DownloadManager
downloadManager
,
@Nullable
Scheduler
scheduler
,
Class
<?
extends
DownloadService
>
serviceClass
)
{
this
.
context
=
context
;
this
.
requirements
=
requirements
;
this
.
downloadManager
=
downloadManager
;
this
.
scheduler
=
scheduler
;
this
.
serviceClass
=
serviceClass
;
requirementsWatcher
=
new
RequirementsWatcher
(
context
,
this
,
requirements
);
downloadManager
.
addListener
(
this
);
if
(
scheduler
!=
null
)
{
Requirements
requirements
=
downloadManager
.
getRequirements
();
setSchedulerEnabled
(
/* enabled= */
!
requirements
.
checkRequirements
(
context
),
requirements
);
}
}
public
void
start
()
{
requirementsWatcher
.
start
();
public
void
attachService
(
DownloadService
downloadService
)
{
Assertions
.
checkState
(
this
.
downloadService
==
null
);
this
.
downloadService
=
downloadService
;
}
public
void
stop
()
{
requirementsWatcher
.
stop
();
if
(
scheduler
!=
null
)
{
public
void
detachService
(
DownloadService
downloadService
,
boolean
unschedule
)
{
Assertions
.
checkState
(
this
.
downloadService
==
downloadService
);
this
.
downloadService
=
null
;
if
(
unschedule
)
{
scheduler
.
cancel
();
}
}
@Override
public
void
requirementsMet
(
RequirementsWatcher
requirementsWatcher
)
{
try
{
notifyService
();
}
catch
(
Exception
e
)
{
/* If we can't notify the service, don't stop the scheduler. */
return
;
public
void
onInitialized
(
DownloadManager
downloadManager
)
{
// Do nothing.
}
@Override
public
void
onDownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
downloadState
)
{
if
(
downloadService
!=
null
)
{
downloadService
.
notifyDownloadStateChange
(
downloadState
);
}
if
(
scheduler
!=
null
)
{
scheduler
.
cancel
();
}
@Override
public
final
void
onIdle
(
DownloadManager
downloadManager
)
{
if
(
downloadService
!=
null
)
{
downloadService
.
stop
();
}
}
@Override
public
void
requirementsNotMet
(
RequirementsWatcher
requirementsWatcher
)
{
try
{
notifyService
();
}
catch
(
Exception
e
)
{
/* Do nothing. The service isn't running anyway. */
public
void
onRequirementsStateChanged
(
DownloadManager
downloadManager
,
Requirements
requirements
,
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
boolean
requirementsMet
=
notMetRequirements
==
0
;
if
(
downloadService
==
null
&&
requirementsMet
)
{
try
{
Intent
intent
=
getIntent
(
context
,
serviceClass
,
DownloadService
.
ACTION_INIT
);
context
.
startService
(
intent
);
}
catch
(
IllegalStateException
e
)
{
/* startService fails if the app is in the background then don't stop the scheduler. */
return
;
}
}
if
(
scheduler
!=
null
)
{
setSchedulerEnabled
(
/* enabled= */
!
requirementsMet
,
requirements
);
}
}
private
void
setSchedulerEnabled
(
boolean
enabled
,
Requirements
requirements
)
{
if
(!
enabled
)
{
scheduler
.
cancel
();
}
else
{
String
servicePackage
=
context
.
getPackageName
();
boolean
success
=
scheduler
.
schedule
(
requirements
,
servicePackage
,
ACTION_RESTART
);
if
(!
success
)
{
...
...
@@ -553,15 +518,5 @@ public abstract class DownloadService extends Service {
}
}
}
private
void
notifyService
()
throws
Exception
{
Intent
intent
=
getIntent
(
context
,
serviceClass
,
DownloadService
.
ACTION_INIT
);
try
{
context
.
startService
(
intent
);
}
catch
(
IllegalStateException
e
)
{
/* startService will fail if the app is in the background and the service isn't running. */
throw
new
Exception
(
e
);
}
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/scheduler/Requirements.java
View file @
ec77f737
...
...
@@ -155,16 +155,14 @@ public final class Requirements {
* @return Whether the requirements are met.
*/
public
boolean
checkRequirements
(
Context
context
)
{
return
checkNetworkRequirements
(
context
)
&&
checkChargingRequirement
(
context
)
&&
checkIdleRequirement
(
context
);
return
getNotMetRequirements
(
context
)
==
0
;
}
/**
* Returns
the requirement flags
that are not met, or 0.
* Returns
{@link RequirementFlags}
that are not met, or 0.
*
* @param context Any context.
* @return
The requirement f
lags that are not met, or 0.
* @return
RequirementF
lags that are not met, or 0.
*/
@RequirementFlags
public
int
getNotMetRequirements
(
Context
context
)
{
...
...
@@ -285,4 +283,20 @@ public final class Requirements {
+
(
isIdleRequired
()
?
",idle"
:
""
)
+
'}'
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
return
true
;
}
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
{
return
false
;
}
return
requirements
==
((
Requirements
)
o
).
requirements
;
}
@Override
public
int
hashCode
()
{
return
requirements
;
}
}
library/core/src/main/java/com/google/android/exoplayer2/scheduler/RequirementsWatcher.java
View file @
ec77f737
...
...
@@ -55,8 +55,12 @@ public final class RequirementsWatcher {
* requirements are not met.
*
* @param requirementsWatcher Calling instance.
* @param notMetRequirements {@link Requirements.RequirementFlags RequirementFlags} that are not
* met, or 0.
*/
void
requirementsNotMet
(
RequirementsWatcher
requirementsWatcher
);
void
requirementsNotMet
(
RequirementsWatcher
requirementsWatcher
,
@Requirements
.
RequirementFlags
int
notMetRequirements
);
}
private
static
final
String
TAG
=
"RequirementsWatcher"
;
...
...
@@ -66,7 +70,7 @@ public final class RequirementsWatcher {
private
final
Requirements
requirements
;
private
DeviceStatusChangeReceiver
receiver
;
private
int
notMetRequirements
;
@Requirements
.
RequirementFlags
private
int
notMetRequirements
;
private
CapabilityValidatedCallback
networkCallback
;
private
Handler
handler
;
...
...
@@ -85,8 +89,11 @@ public final class RequirementsWatcher {
/**
* Starts watching for changes. Must be called from a thread that has an associated {@link
* Looper}. Listener methods are called on the caller thread.
*
* @return Initial {@link Requirements.RequirementFlags RequirementFlags} that are not met, or 0.
*/
public
void
start
()
{
@Requirements
.
RequirementFlags
public
int
start
()
{
Assertions
.
checkNotNull
(
Looper
.
myLooper
());
handler
=
new
Handler
();
...
...
@@ -115,6 +122,7 @@ public final class RequirementsWatcher {
receiver
=
new
DeviceStatusChangeReceiver
();
context
.
registerReceiver
(
receiver
,
filter
,
null
,
handler
);
logd
(
this
+
" started"
);
return
notMetRequirements
;
}
/** Stops watching for changes. */
...
...
@@ -162,6 +170,7 @@ public final class RequirementsWatcher {
}
private
void
checkRequirements
()
{
@Requirements
.
RequirementFlags
int
notMetRequirements
=
requirements
.
getNotMetRequirements
(
context
);
if
(
this
.
notMetRequirements
==
notMetRequirements
)
{
logd
(
"notMetRequirements hasn't changed: "
+
notMetRequirements
);
...
...
@@ -173,7 +182,7 @@ public final class RequirementsWatcher {
listener
.
requirementsMet
(
this
);
}
else
{
logd
(
"stop job"
);
listener
.
requirementsNotMet
(
this
);
listener
.
requirementsNotMet
(
this
,
notMetRequirements
);
}
}
...
...
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
View file @
ec77f737
...
...
@@ -21,6 +21,7 @@ import static org.junit.Assert.fail;
import
android.net.Uri
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.offline.DownloadState.State
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.RobolectricUtil
;
import
com.google.android.exoplayer2.testutil.TestDownloadManagerListener
;
...
...
@@ -426,7 +427,12 @@ public class DownloadManagerTest {
()
->
{
downloadManager
=
new
DownloadManager
(
actionFile
,
downloaderFactory
,
maxActiveDownloadTasks
,
MIN_RETRY_COUNT
);
RuntimeEnvironment
.
application
,
actionFile
,
downloaderFactory
,
maxActiveDownloadTasks
,
MIN_RETRY_COUNT
,
new
Requirements
(
0
));
downloadManagerListener
=
new
TestDownloadManagerListener
(
downloadManager
,
dummyMainThread
);
downloadManager
.
startDownloads
();
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
View file @
ec77f737
...
...
@@ -30,6 +30,7 @@ import com.google.android.exoplayer2.offline.DownloadAction;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloaderConstructorHelper
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.FakeDataSet
;
import
com.google.android.exoplayer2.testutil.FakeDataSource
;
...
...
@@ -241,11 +242,13 @@ public class DownloadManagerDashTest {
Factory
fakeDataSourceFactory
=
new
FakeDataSource
.
Factory
().
setFakeDataSet
(
fakeDataSet
);
downloadManager
=
new
DownloadManager
(
RuntimeEnvironment
.
application
,
actionFile
,
new
DefaultDownloaderFactory
(
new
DownloaderConstructorHelper
(
cache
,
fakeDataSourceFactory
)),
/* maxSimultaneousDownloads= */
1
,
/* minRetryCount= */
3
);
/* minRetryCount= */
3
,
new
Requirements
(
0
));
downloadManagerListener
=
new
TestDownloadManagerListener
(
downloadManager
,
dummyMainThread
);
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
View file @
ec77f737
...
...
@@ -30,6 +30,7 @@ import com.google.android.exoplayer2.offline.DownloadManager;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.offline.DownloaderConstructorHelper
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.Scheduler
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.FakeDataSet
;
...
...
@@ -117,11 +118,13 @@ public class DownloadServiceDashTest {
actionFile
.
delete
();
final
DownloadManager
dashDownloadManager
=
new
DownloadManager
(
RuntimeEnvironment
.
application
,
actionFile
,
new
DefaultDownloaderFactory
(
new
DownloaderConstructorHelper
(
cache
,
fakeDataSourceFactory
)),
/* maxSimultaneousDownloads= */
1
,
/* minRetryCount= */
3
);
/* minRetryCount= */
3
,
new
Requirements
(
0
));
downloadManagerListener
=
new
TestDownloadManagerListener
(
dashDownloadManager
,
dummyMainThread
);
dashDownloadManager
.
startDownloads
();
...
...
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java
View file @
ec77f737
...
...
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import
android.os.ConditionVariable
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadState
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
java.util.HashMap
;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.CountDownLatch
;
...
...
@@ -82,6 +83,12 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
}
}
@Override
public
void
onRequirementsStateChanged
(
DownloadManager
downloadManager
,
Requirements
requirements
,
int
notMetRequirements
)
{
// Do nothing.
}
/**
* Blocks until all remove and download tasks are complete and throws an exception if there was an
* error.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment