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
3919f384
authored
Mar 26, 2019
by
eguven
Committed by
Oliver Woodman
Mar 26, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Make DownloadManager use DownloadIndex
PiperOrigin-RevId: 240320220
parent
e4b49477
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
284 additions
and
219 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/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/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java
demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java
View file @
3919f384
...
@@ -114,21 +114,14 @@ public class DemoApplication extends Application {
...
@@ -114,21 +114,14 @@ public class DemoApplication extends Application {
private
synchronized
void
initDownloadManager
()
{
private
synchronized
void
initDownloadManager
()
{
if
(
downloadManager
==
null
)
{
if
(
downloadManager
==
null
)
{
DefaultDownloadIndex
downloadIndex
=
new
DefaultDownloadIndex
(
new
ExoDatabaseProvider
(
this
));
DefaultDownloadIndex
downloadIndex
=
new
DefaultDownloadIndex
(
new
ExoDatabaseProvider
(
this
));
File
actionFile
=
new
File
(
getDownloadDirectory
(),
DOWNLOAD_TRACKER_ACTION_FILE
);
upgradeActionFile
(
DOWNLOAD_TRACKER_ACTION_FILE
,
downloadIndex
);
if
(
actionFile
.
exists
())
{
upgradeActionFile
(
DOWNLOAD_ACTION_FILE
,
downloadIndex
);
try
{
DownloadIndexUtil
.
upgradeActionFile
(
new
ActionFile
(
actionFile
),
downloadIndex
,
null
);
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
"Upgrading action file failed"
,
e
);
}
actionFile
.
delete
();
}
DownloaderConstructorHelper
downloaderConstructorHelper
=
DownloaderConstructorHelper
downloaderConstructorHelper
=
new
DownloaderConstructorHelper
(
getDownloadCache
(),
buildHttpDataSourceFactory
());
new
DownloaderConstructorHelper
(
getDownloadCache
(),
buildHttpDataSourceFactory
());
downloadManager
=
downloadManager
=
new
DownloadManager
(
new
DownloadManager
(
this
,
this
,
new
File
(
getDownloadDirectory
(),
DOWNLOAD_ACTION_FILE
)
,
downloadIndex
,
new
DefaultDownloaderFactory
(
downloaderConstructorHelper
),
new
DefaultDownloaderFactory
(
downloaderConstructorHelper
),
MAX_SIMULTANEOUS_DOWNLOADS
,
MAX_SIMULTANEOUS_DOWNLOADS
,
DownloadManager
.
DEFAULT_MIN_RETRY_COUNT
,
DownloadManager
.
DEFAULT_MIN_RETRY_COUNT
,
...
@@ -139,6 +132,18 @@ public class DemoApplication extends Application {
...
@@ -139,6 +132,18 @@ public class DemoApplication extends Application {
}
}
}
}
private
void
upgradeActionFile
(
String
file
,
DefaultDownloadIndex
downloadIndex
)
{
ActionFile
actionFile
=
new
ActionFile
(
new
File
(
getDownloadDirectory
(),
file
));
if
(
actionFile
.
exists
())
{
try
{
DownloadIndexUtil
.
upgradeActionFile
(
actionFile
,
downloadIndex
,
null
);
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
"Upgrading action file failed"
,
e
);
}
actionFile
.
delete
();
}
}
private
File
getDownloadDirectory
()
{
private
File
getDownloadDirectory
()
{
if
(
downloadDirectory
==
null
)
{
if
(
downloadDirectory
==
null
)
{
downloadDirectory
=
getExternalFilesDir
(
null
);
downloadDirectory
=
getExternalFilesDir
(
null
);
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
View file @
3919f384
...
@@ -18,8 +18,6 @@ package com.google.android.exoplayer2.demo;
...
@@ -18,8 +18,6 @@ package com.google.android.exoplayer2.demo;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.DialogInterface
;
import
android.content.DialogInterface
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.HandlerThread
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
androidx.fragment.app.FragmentManager
;
import
androidx.fragment.app.FragmentManager
;
import
android.widget.Toast
;
import
android.widget.Toast
;
...
@@ -66,9 +64,8 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -66,9 +64,8 @@ public class DownloadTracker implements DownloadManager.Listener {
private
final
Context
context
;
private
final
Context
context
;
private
final
DataSource
.
Factory
dataSourceFactory
;
private
final
DataSource
.
Factory
dataSourceFactory
;
private
final
CopyOnWriteArraySet
<
Listener
>
listeners
;
private
final
CopyOnWriteArraySet
<
Listener
>
listeners
;
private
final
HashMap
<
Uri
,
DownloadState
>
trackedD
ownloadStates
;
private
final
HashMap
<
Uri
,
DownloadState
>
d
ownloadStates
;
private
final
DefaultDownloadIndex
downloadIndex
;
private
final
DefaultDownloadIndex
downloadIndex
;
private
final
Handler
indexHandler
;
@Nullable
private
StartDownloadDialogHelper
startDownloadDialogHelper
;
@Nullable
private
StartDownloadDialogHelper
startDownloadDialogHelper
;
...
@@ -78,11 +75,8 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -78,11 +75,8 @@ public class DownloadTracker implements DownloadManager.Listener {
this
.
dataSourceFactory
=
dataSourceFactory
;
this
.
dataSourceFactory
=
dataSourceFactory
;
this
.
downloadIndex
=
downloadIndex
;
this
.
downloadIndex
=
downloadIndex
;
listeners
=
new
CopyOnWriteArraySet
<>();
listeners
=
new
CopyOnWriteArraySet
<>();
trackedDownloadStates
=
new
HashMap
<>();
downloadStates
=
new
HashMap
<>();
HandlerThread
indexThread
=
new
HandlerThread
(
"DownloadTracker"
);
loadDownloads
();
indexThread
.
start
();
indexHandler
=
new
Handler
(
indexThread
.
getLooper
());
loadTrackedActions
();
}
}
public
void
addListener
(
Listener
listener
)
{
public
void
addListener
(
Listener
listener
)
{
...
@@ -94,15 +88,16 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -94,15 +88,16 @@ public class DownloadTracker implements DownloadManager.Listener {
}
}
public
boolean
isDownloaded
(
Uri
uri
)
{
public
boolean
isDownloaded
(
Uri
uri
)
{
return
trackedDownloadStates
.
containsKey
(
uri
);
DownloadState
downloadState
=
downloadStates
.
get
(
uri
);
return
downloadState
!=
null
&&
downloadState
.
state
!=
DownloadState
.
STATE_FAILED
;
}
}
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
public
List
<
StreamKey
>
getOfflineStreamKeys
(
Uri
uri
)
{
public
List
<
StreamKey
>
getOfflineStreamKeys
(
Uri
uri
)
{
if
(!
trackedDownloadStates
.
containsKey
(
uri
))
{
DownloadState
downloadState
=
downloadStates
.
get
(
uri
);
return
Collections
.
emptyList
();
return
downloadState
!=
null
&&
downloadState
.
state
!=
DownloadState
.
STATE_FAILED
}
?
Arrays
.
asList
(
downloadState
.
streamKeys
)
return
Arrays
.
asList
(
trackedDownloadStates
.
get
(
uri
).
streamKeys
);
:
Collections
.
emptyList
(
);
}
}
public
void
toggleDownload
(
public
void
toggleDownload
(
...
@@ -129,59 +124,34 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -129,59 +124,34 @@ public class DownloadTracker implements DownloadManager.Listener {
@Override
@Override
public
void
onDownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
downloadState
)
{
public
void
onDownloadStateChanged
(
DownloadManager
downloadManager
,
DownloadState
downloadState
)
{
if
(
downloadState
.
state
==
DownloadState
.
STATE_REMOVED
boolean
downloaded
=
isDownloaded
(
downloadState
.
uri
);
||
downloadState
.
state
==
DownloadState
.
STATE_FAILED
)
{
if
(
downloadState
.
state
==
DownloadState
.
STATE_REMOVED
)
{
// A download has been removed, or has failed. Stop tracking it.
downloadStates
.
remove
(
downloadState
.
uri
);
if
(
trackedDownloadStates
.
remove
(
downloadState
.
uri
)
!=
null
)
{
}
else
{
handleTrackedDownloadStateChanged
(
downloadState
);
downloadStates
.
put
(
downloadState
.
uri
,
downloadState
);
}
if
(
downloaded
!=
isDownloaded
(
downloadState
.
uri
))
{
for
(
Listener
listener
:
listeners
)
{
listener
.
onDownloadsChanged
();
}
}
}
}
}
}
// Internal methods
// Internal methods
private
void
load
TrackedAction
s
()
{
private
void
load
Download
s
()
{
try
{
try
{
DownloadStateCursor
d
ownloadStates
=
downloadIndex
.
getDownloadStates
();
DownloadStateCursor
loadedD
ownloadStates
=
downloadIndex
.
getDownloadStates
();
while
(
d
ownloadStates
.
moveToNext
())
{
while
(
loadedD
ownloadStates
.
moveToNext
())
{
DownloadState
downloadState
=
d
ownloadStates
.
getDownloadState
();
DownloadState
downloadState
=
loadedD
ownloadStates
.
getDownloadState
();
trackedD
ownloadStates
.
put
(
downloadState
.
uri
,
downloadState
);
d
ownloadStates
.
put
(
downloadState
.
uri
,
downloadState
);
}
}
d
ownloadStates
.
close
();
loadedD
ownloadStates
.
close
();
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
Log
.
w
(
TAG
,
"Failed to query download states"
,
e
);
Log
.
w
(
TAG
,
"Failed to query download states"
,
e
);
}
}
}
}
private
void
handleTrackedDownloadStateChanged
(
DownloadState
downloadState
)
{
for
(
Listener
listener
:
listeners
)
{
listener
.
onDownloadsChanged
();
}
indexHandler
.
post
(
()
->
{
try
{
if
(
downloadState
.
state
==
DownloadState
.
STATE_REMOVED
)
{
downloadIndex
.
removeDownloadState
(
downloadState
.
id
);
}
else
{
downloadIndex
.
putDownloadState
(
downloadState
);
}
}
catch
(
IOException
e
)
{
// TODO: This whole method is going away in cr/232854678.
}
});
}
private
void
startDownload
(
DownloadAction
action
)
{
if
(
trackedDownloadStates
.
containsKey
(
action
.
uri
))
{
// This content is already being downloaded. Do nothing.
return
;
}
DownloadState
downloadState
=
new
DownloadState
(
action
);
trackedDownloadStates
.
put
(
downloadState
.
uri
,
downloadState
);
handleTrackedDownloadStateChanged
(
downloadState
);
startServiceWithAction
(
action
);
}
private
void
startServiceWithAction
(
DownloadAction
action
)
{
private
void
startServiceWithAction
(
DownloadAction
action
)
{
DownloadService
.
startWithAction
(
context
,
DemoDownloadService
.
class
,
action
,
false
);
DownloadService
.
startWithAction
(
context
,
DemoDownloadService
.
class
,
action
,
false
);
}
}
...
@@ -238,7 +208,7 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -238,7 +208,7 @@ public class DownloadTracker implements DownloadManager.Listener {
if
(
helper
.
getPeriodCount
()
==
0
)
{
if
(
helper
.
getPeriodCount
()
==
0
)
{
Log
.
d
(
TAG
,
"No periods found. Downloading entire stream."
);
Log
.
d
(
TAG
,
"No periods found. Downloading entire stream."
);
DownloadAction
downloadAction
=
downloadHelper
.
getDownloadAction
(
Util
.
getUtf8Bytes
(
name
));
DownloadAction
downloadAction
=
downloadHelper
.
getDownloadAction
(
Util
.
getUtf8Bytes
(
name
));
start
Download
(
downloadAction
);
start
ServiceWithAction
(
downloadAction
);
downloadHelper
.
release
();
downloadHelper
.
release
();
return
;
return
;
}
}
...
@@ -280,7 +250,7 @@ public class DownloadTracker implements DownloadManager.Listener {
...
@@ -280,7 +250,7 @@ public class DownloadTracker implements DownloadManager.Listener {
}
}
}
}
DownloadAction
downloadAction
=
downloadHelper
.
getDownloadAction
(
Util
.
getUtf8Bytes
(
name
));
DownloadAction
downloadAction
=
downloadHelper
.
getDownloadAction
(
Util
.
getUtf8Bytes
(
name
));
start
Download
(
downloadAction
);
start
ServiceWithAction
(
downloadAction
);
}
}
// DialogInterface.OnDismissListener implementation.
// DialogInterface.OnDismissListener implementation.
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
View file @
3919f384
...
@@ -36,11 +36,12 @@ import android.os.Looper;
...
@@ -36,11 +36,12 @@ import android.os.Looper;
import
androidx.annotation.IntDef
;
import
androidx.annotation.IntDef
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.database.DatabaseIOException
;
import
com.google.android.exoplayer2.database.DatabaseProvider
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.RequirementsWatcher
;
import
com.google.android.exoplayer2.scheduler.RequirementsWatcher
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.RetentionPolicy
;
...
@@ -48,7 +49,6 @@ import java.util.ArrayDeque;
...
@@ -48,7 +49,6 @@ import java.util.ArrayDeque;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.concurrent.CopyOnWriteArraySet
;
import
java.util.concurrent.CopyOnWriteArraySet
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
...
@@ -130,7 +130,7 @@ public final class DownloadManager {
...
@@ -130,7 +130,7 @@ public final class DownloadManager {
private
final
int
maxSimultaneousDownloads
;
private
final
int
maxSimultaneousDownloads
;
private
final
int
minRetryCount
;
private
final
int
minRetryCount
;
private
final
Context
context
;
private
final
Context
context
;
private
final
ActionFile
actionFile
;
private
final
DefaultDownloadIndex
downloadIndex
;
private
final
DownloaderFactory
downloaderFactory
;
private
final
DownloaderFactory
downloaderFactory
;
private
final
ArrayList
<
Download
>
downloads
;
private
final
ArrayList
<
Download
>
downloads
;
private
final
HashMap
<
Download
,
DownloadThread
>
activeDownloads
;
private
final
HashMap
<
Download
,
DownloadThread
>
activeDownloads
;
...
@@ -146,18 +146,20 @@ public final class DownloadManager {
...
@@ -146,18 +146,20 @@ public final class DownloadManager {
private
int
manualStopReason
;
private
int
manualStopReason
;
private
RequirementsWatcher
requirementsWatcher
;
private
RequirementsWatcher
requirementsWatcher
;
private
int
simultaneousDownloads
;
private
int
simultaneousDownloads
;
private
boolean
loadingDownload
;
/**
/**
* Constructs a {@link DownloadManager}.
* Constructs a {@link DownloadManager}.
*
*
* @param context Any context.
* @param context Any context.
* @param
actionFile The file in which active actions are saved
.
* @param
databaseProvider Used to create a {@link DownloadIndex} which holds download states
.
* @param downloaderFactory A factory for creating {@link Downloader}s.
* @param downloaderFactory A factory for creating {@link Downloader}s.
*/
*/
public
DownloadManager
(
Context
context
,
File
actionFile
,
DownloaderFactory
downloaderFactory
)
{
public
DownloadManager
(
Context
context
,
DatabaseProvider
databaseProvider
,
DownloaderFactory
downloaderFactory
)
{
this
(
this
(
context
,
context
,
actionFile
,
databaseProvider
,
downloaderFactory
,
downloaderFactory
,
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
,
DEFAULT_MAX_SIMULTANEOUS_DOWNLOADS
,
DEFAULT_MIN_RETRY_COUNT
,
DEFAULT_MIN_RETRY_COUNT
,
...
@@ -168,7 +170,33 @@ public final class DownloadManager {
...
@@ -168,7 +170,33 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}.
* Constructs a {@link DownloadManager}.
*
*
* @param context Any context.
* @param context Any context.
* @param actionFile The file in which active actions are saved.
* @param databaseProvider Used to create a {@link DownloadIndex} which holds download states.
* @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
,
DatabaseProvider
databaseProvider
,
DownloaderFactory
downloaderFactory
,
int
maxSimultaneousDownloads
,
int
minRetryCount
,
Requirements
requirements
)
{
this
(
context
,
new
DefaultDownloadIndex
(
databaseProvider
),
downloaderFactory
,
maxSimultaneousDownloads
,
minRetryCount
,
requirements
);
}
/**
* Constructs a {@link DownloadManager}.
*
* @param context Any context.
* @param downloadIndex The {@link DefaultDownloadIndex} which holds download states.
* @param downloaderFactory A factory for creating {@link Downloader}s.
* @param downloaderFactory A factory for creating {@link Downloader}s.
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a download must be retried before failing.
* @param minRetryCount The minimum number of times a download must be retried before failing.
...
@@ -176,13 +204,13 @@ public final class DownloadManager {
...
@@ -176,13 +204,13 @@ public final class DownloadManager {
*/
*/
public
DownloadManager
(
public
DownloadManager
(
Context
context
,
Context
context
,
File
actionFile
,
DefaultDownloadIndex
downloadIndex
,
DownloaderFactory
downloaderFactory
,
DownloaderFactory
downloaderFactory
,
int
maxSimultaneousDownloads
,
int
maxSimultaneousDownloads
,
int
minRetryCount
,
int
minRetryCount
,
Requirements
requirements
)
{
Requirements
requirements
)
{
this
.
context
=
context
.
getApplicationContext
();
this
.
context
=
context
.
getApplicationContext
();
this
.
actionFile
=
new
ActionFile
(
actionFile
)
;
this
.
downloadIndex
=
downloadIndex
;
this
.
downloaderFactory
=
downloaderFactory
;
this
.
downloaderFactory
=
downloaderFactory
;
this
.
maxSimultaneousDownloads
=
maxSimultaneousDownloads
;
this
.
maxSimultaneousDownloads
=
maxSimultaneousDownloads
;
this
.
minRetryCount
=
minRetryCount
;
this
.
minRetryCount
=
minRetryCount
;
...
@@ -204,11 +232,16 @@ public final class DownloadManager {
...
@@ -204,11 +232,16 @@ public final class DownloadManager {
listeners
=
new
CopyOnWriteArraySet
<>();
listeners
=
new
CopyOnWriteArraySet
<>();
actionQueue
=
new
ArrayDeque
<>();
actionQueue
=
new
ArrayDeque
<>();
notMetRequirements
=
watchRequirements
(
requirements
);
setNotMetRequirements
(
watchRequirements
(
requirements
)
);
load
Action
s
();
load
Download
s
();
logd
(
"Created"
);
logd
(
"Created"
);
}
}
/** Returns the used {@link DownloadIndex}. */
public
DownloadIndex
getDownloadIndex
()
{
return
downloadIndex
;
}
/**
/**
* Sets the requirements needed to be met to start downloads.
* Sets the requirements needed to be met to start downloads.
*
*
...
@@ -251,10 +284,7 @@ public final class DownloadManager {
...
@@ -251,10 +284,7 @@ public final class DownloadManager {
*/
*/
public
void
startDownloads
()
{
public
void
startDownloads
()
{
logd
(
"manual stop is cancelled"
);
logd
(
"manual stop is cancelled"
);
manualStopReason
=
MANUAL_STOP_REASON_NONE
;
setManualStopReason
(
/* id= */
null
,
MANUAL_STOP_REASON_NONE
);
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
downloads
.
get
(
i
).
setManualStopReason
(
MANUAL_STOP_REASON_NONE
);
}
}
}
/** Signals all downloads to stop. Call {@link #startDownloads()} to let them to be started. */
/** Signals all downloads to stop. Call {@link #startDownloads()} to let them to be started. */
...
@@ -273,10 +303,7 @@ public final class DownloadManager {
...
@@ -273,10 +303,7 @@ public final class DownloadManager {
public
void
stopDownloads
(
int
manualStopReason
)
{
public
void
stopDownloads
(
int
manualStopReason
)
{
Assertions
.
checkArgument
(
manualStopReason
!=
MANUAL_STOP_REASON_NONE
);
Assertions
.
checkArgument
(
manualStopReason
!=
MANUAL_STOP_REASON_NONE
);
logd
(
"downloads are stopped manually"
);
logd
(
"downloads are stopped manually"
);
this
.
manualStopReason
=
manualStopReason
;
setManualStopReason
(
/* id= */
null
,
manualStopReason
);
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
downloads
.
get
(
i
).
setManualStopReason
(
this
.
manualStopReason
);
}
}
}
/**
/**
...
@@ -286,11 +313,7 @@ public final class DownloadManager {
...
@@ -286,11 +313,7 @@ public final class DownloadManager {
* @param id The unique content id of the download to be started.
* @param id The unique content id of the download to be started.
*/
*/
public
void
startDownload
(
String
id
)
{
public
void
startDownload
(
String
id
)
{
Download
download
=
getDownload
(
id
);
setManualStopReason
(
id
,
MANUAL_STOP_REASON_NONE
);
if
(
download
!=
null
)
{
logd
(
"manual stop is cancelled"
,
download
);
download
.
setManualStopReason
(
MANUAL_STOP_REASON_NONE
);
}
}
}
/**
/**
...
@@ -315,11 +338,7 @@ public final class DownloadManager {
...
@@ -315,11 +338,7 @@ public final class DownloadManager {
*/
*/
public
void
stopDownload
(
String
id
,
int
manualStopReason
)
{
public
void
stopDownload
(
String
id
,
int
manualStopReason
)
{
Assertions
.
checkArgument
(
manualStopReason
!=
MANUAL_STOP_REASON_NONE
);
Assertions
.
checkArgument
(
manualStopReason
!=
MANUAL_STOP_REASON_NONE
);
Download
download
=
getDownload
(
id
);
setManualStopReason
(
id
,
manualStopReason
);
if
(
download
!=
null
)
{
logd
(
"download is stopped manually"
,
download
);
download
.
setManualStopReason
(
manualStopReason
);
}
}
}
/**
/**
...
@@ -329,11 +348,9 @@ public final class DownloadManager {
...
@@ -329,11 +348,9 @@ public final class DownloadManager {
*/
*/
public
void
handleAction
(
DownloadAction
action
)
{
public
void
handleAction
(
DownloadAction
action
)
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
actionQueue
.
add
(
action
);
if
(
initialized
)
{
if
(
initialized
)
{
addDownloadForAction
(
action
);
processActionQueue
();
saveActions
();
}
else
{
actionQueue
.
add
(
action
);
}
}
}
}
...
@@ -343,25 +360,12 @@ public final class DownloadManager {
...
@@ -343,25 +360,12 @@ public final class DownloadManager {
return
downloads
.
size
();
return
downloads
.
size
();
}
}
/**
* Returns {@link DownloadState} for the given content id, or null if no such download exists.
*
* @param id The unique content id.
* @return DownloadState for the given content id, or null if no such download exists.
*/
@Nullable
public
DownloadState
getDownloadState
(
String
id
)
{
Assertions
.
checkState
(!
released
);
Download
download
=
getDownload
(
id
);
return
download
!=
null
?
download
.
getDownloadState
()
:
null
;
}
/** Returns the states of all current downloads. */
/** Returns the states of all current downloads. */
public
DownloadState
[]
getAllDownloadStates
()
{
public
DownloadState
[]
getAllDownloadStates
()
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
DownloadState
[]
states
=
new
DownloadState
[
downloads
.
size
()];
DownloadState
[]
states
=
new
DownloadState
[
downloads
.
size
()];
for
(
int
i
=
0
;
i
<
states
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
states
.
length
;
i
++)
{
states
[
i
]
=
downloads
.
get
(
i
).
getDownloadState
();
states
[
i
]
=
downloads
.
get
(
i
).
get
Updated
DownloadState
();
}
}
return
states
;
return
states
;
}
}
...
@@ -375,7 +379,7 @@ public final class DownloadManager {
...
@@ -375,7 +379,7 @@ public final class DownloadManager {
/** Returns whether there are no active downloads. */
/** Returns whether there are no active downloads. */
public
boolean
isIdle
()
{
public
boolean
isIdle
()
{
Assertions
.
checkState
(!
released
);
Assertions
.
checkState
(!
released
);
return
initialized
&&
activeDownloads
.
isEmpty
();
return
initialized
&&
activeDownloads
.
isEmpty
()
&&
actionQueue
.
isEmpty
()
&&
!
loadingDownload
;
}
}
/**
/**
...
@@ -399,17 +403,32 @@ public final class DownloadManager {
...
@@ -399,17 +403,32 @@ public final class DownloadManager {
logd
(
"Released"
);
logd
(
"Released"
);
}
}
private
void
addDownloadForAction
(
DownloadAction
action
)
{
private
void
setManualStopReason
(
@Nullable
String
id
,
int
manualStopReason
)
{
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
if
(
id
!=
null
)
{
Download
download
=
downloads
.
get
(
i
);
Download
download
=
getDownload
(
id
);
if
(
download
.
addAction
(
action
))
{
if
(
download
!=
null
)
{
logd
(
"Action is added to existing download"
,
download
);
logd
(
"download manual stop reason is set to : "
+
manualStopReason
,
download
);
download
.
setManualStopReason
(
manualStopReason
);
return
;
return
;
}
}
}
else
{
this
.
manualStopReason
=
manualStopReason
;
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
downloads
.
get
(
i
).
setManualStopReason
(
manualStopReason
);
}
}
}
Download
download
=
new
Download
(
this
,
action
,
notMetRequirements
,
manualStopReason
);
fileIOHandler
.
post
(
downloads
.
add
(
download
);
()
->
{
logd
(
"Download is added"
,
download
);
try
{
if
(
id
!=
null
)
{
downloadIndex
.
setManualStopReason
(
id
,
manualStopReason
);
}
else
{
downloadIndex
.
setManualStopReason
(
manualStopReason
);
}
}
catch
(
DatabaseIOException
e
)
{
Log
.
e
(
TAG
,
"setManualStopReason failed"
,
e
);
}
});
}
}
private
void
maybeNotifyListenersIdle
()
{
private
void
maybeNotifyListenersIdle
()
{
...
@@ -422,33 +441,44 @@ public final class DownloadManager {
...
@@ -422,33 +441,44 @@ public final class DownloadManager {
}
}
}
}
private
void
onDownloadStateChange
(
Download
download
)
{
private
void
onDownloadStateChange
(
Download
download
,
DownloadState
downloadState
)
{
if
(
released
)
{
if
(
released
)
{
return
;
return
;
}
}
logd
(
"Download state is changed"
,
download
);
logd
(
"Download state is changed"
,
download
);
DownloadState
downloadState
=
download
.
getDownloadState
(
);
updateDownloadIndex
(
downloadState
);
for
(
Listener
listener
:
listeners
)
{
for
(
Listener
listener
:
listeners
)
{
listener
.
onDownloadStateChanged
(
this
,
downloadState
);
listener
.
onDownloadStateChanged
(
this
,
downloadState
);
}
}
if
(
download
.
isFinished
())
{
if
(
download
.
isFinished
())
{
downloads
.
remove
(
download
);
downloads
.
remove
(
download
);
saveActions
();
}
}
}
}
private
void
onRequirementsStateChanged
(
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
private
void
onRequirementsStateChanged
(
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
this
.
notMetRequirements
=
notMetRequirements
;
logdFlags
(
"Not met requirements are changed"
,
notMetRequirements
);
Requirements
requirements
=
requirementsWatcher
.
getRequirements
();
Requirements
requirements
=
requirementsWatcher
.
getRequirements
();
for
(
Listener
listener
:
listeners
)
{
for
(
Listener
listener
:
listeners
)
{
listener
.
onRequirementsStateChanged
(
DownloadManager
.
this
,
requirements
,
notMetRequirements
);
listener
.
onRequirementsStateChanged
(
DownloadManager
.
this
,
requirements
,
notMetRequirements
);
}
}
setNotMetRequirements
(
notMetRequirements
);
}
private
void
setNotMetRequirements
(
@Requirements
.
RequirementFlags
int
notMetRequirements
)
{
this
.
notMetRequirements
=
notMetRequirements
;
logdFlags
(
"Not met requirements are changed"
,
notMetRequirements
);
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
downloads
.
get
(
i
).
setNotMetRequirements
(
notMetRequirements
);
downloads
.
get
(
i
).
setNotMetRequirements
(
notMetRequirements
);
}
}
}
}
@Requirements
.
RequirementFlags
private
int
watchRequirements
(
Requirements
requirements
)
{
RequirementsWatcher
.
Listener
listener
=
(
requirementsWatcher
,
notMetRequirements
)
->
onRequirementsStateChanged
(
notMetRequirements
);
requirementsWatcher
=
new
RequirementsWatcher
(
context
,
listener
,
requirements
);
return
requirementsWatcher
.
start
();
}
@Nullable
@Nullable
private
Download
getDownload
(
String
id
)
{
private
Download
getDownload
(
String
id
)
{
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
...
@@ -460,34 +490,85 @@ public final class DownloadManager {
...
@@ -460,34 +490,85 @@ public final class DownloadManager {
return
null
;
return
null
;
}
}
private
void
loadActions
()
{
private
void
processActionQueue
()
{
if
(
loadingDownload
||
actionQueue
.
isEmpty
())
{
return
;
}
DownloadAction
action
=
actionQueue
.
remove
();
Download
download
=
getDownload
(
action
.
id
);
if
(
download
!=
null
)
{
download
.
addAction
(
action
);
logd
(
"Action is added to existing download"
,
download
);
return
;
}
loadDownload
(
action
);
}
private
void
loadDownload
(
DownloadAction
action
)
{
loadingDownload
=
true
;
fileIOHandler
.
post
(
fileIOHandler
.
post
(
()
->
{
()
->
{
Download
Action
[]
loadedActions
;
Download
State
downloadState
=
null
;
try
{
try
{
loadedActions
=
actionFile
.
load
();
downloadState
=
downloadIndex
.
getDownloadState
(
action
.
id
);
logd
(
"Action file is loaded."
);
}
catch
(
DatabaseIOException
e
)
{
}
catch
(
Throwable
e
)
{
Log
.
e
(
TAG
,
"loadDownload failed"
,
e
);
Log
.
e
(
TAG
,
"Action file loading failed."
,
e
);
loadedActions
=
new
DownloadAction
[
0
];
}
}
final
DownloadAction
[]
actions
=
loadedActions
;
DownloadState
finalDownloadState
=
downloadState
;
handler
.
post
(
handler
.
post
(
()
->
{
()
->
{
loadingDownload
=
false
;
if
(
released
)
{
if
(
released
)
{
return
;
return
;
}
}
for
(
DownloadAction
action
:
actions
)
{
DownloadState
state
;
addDownloadForAction
(
action
);
if
(
finalDownloadState
==
null
)
{
state
=
new
DownloadState
(
action
);
logd
(
"Download state is created for "
+
action
.
id
);
}
else
{
state
=
finalDownloadState
.
mergeAction
(
action
);
logd
(
"Download state is loaded for "
+
action
.
id
);
}
addDownloadForState
(
state
);
processActionQueue
();
});
});
}
private
void
loadDownloads
()
{
fileIOHandler
.
post
(
()
->
{
DownloadState
[]
loadedStates
;
try
{
DownloadStateCursor
cursor
=
downloadIndex
.
getDownloadStates
(
STATE_QUEUED
,
STATE_STOPPED
,
STATE_DOWNLOADING
,
STATE_REMOVING
,
STATE_RESTARTING
);
loadedStates
=
new
DownloadState
[
cursor
.
getCount
()];
for
(
int
i
=
0
,
length
=
loadedStates
.
length
;
i
<
length
;
i
++)
{
cursor
.
moveToNext
();
loadedStates
[
i
]
=
cursor
.
getDownloadState
();
}
logd
(
"Download states are loaded."
);
}
catch
(
Throwable
e
)
{
Log
.
e
(
TAG
,
"Download state loading failed."
,
e
);
loadedStates
=
new
DownloadState
[
0
];
}
final
DownloadState
[]
states
=
loadedStates
;
handler
.
post
(
()
->
{
if
(
released
)
{
return
;
}
}
if
(!
actionQueue
.
isEmpty
())
{
for
(
DownloadState
downloadState
:
states
)
{
while
(!
actionQueue
.
isEmpty
())
{
addDownloadForState
(
downloadState
);
addDownloadForAction
(
actionQueue
.
remove
());
}
saveActions
();
}
}
logd
(
"Downloads are created."
);
logd
(
"Downloads are created."
);
initialized
=
true
;
initialized
=
true
;
processActionQueue
();
for
(
Listener
listener
:
listeners
)
{
for
(
Listener
listener
:
listeners
)
{
listener
.
onInitialized
(
DownloadManager
.
this
);
listener
.
onInitialized
(
DownloadManager
.
this
);
}
}
...
@@ -498,22 +579,26 @@ public final class DownloadManager {
...
@@ -498,22 +579,26 @@ public final class DownloadManager {
});
});
}
}
private
void
saveActions
()
{
private
void
addDownloadForState
(
DownloadState
downloadState
)
{
if
(
released
)
{
Download
download
=
new
Download
(
this
,
downloadState
,
notMetRequirements
,
manualStopReason
);
return
;
downloads
.
add
(
download
);
}
logd
(
"Download is added"
,
download
);
ArrayList
<
DownloadAction
>
actions
=
new
ArrayList
<>(
downloads
.
size
());
}
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
downloads
.
get
(
i
).
addActions
(
actions
);
private
void
updateDownloadIndex
(
DownloadState
downloadState
)
{
}
final
DownloadAction
[]
actionsArray
=
actions
.
toArray
(
new
DownloadAction
[
0
]);
fileIOHandler
.
post
(
fileIOHandler
.
post
(
()
->
{
()
->
{
if
(
released
)
{
return
;
}
try
{
try
{
actionFile
.
store
(
actionsArray
);
if
(
downloadState
.
state
==
DownloadState
.
STATE_REMOVED
)
{
logd
(
"Actions persisted."
);
downloadIndex
.
removeDownloadState
(
downloadState
.
id
);
}
catch
(
IOException
e
)
{
}
else
{
Log
.
e
(
TAG
,
"Persisting actions failed."
,
e
);
downloadIndex
.
putDownloadState
(
downloadState
);
}
}
catch
(
DatabaseIOException
e
)
{
Log
.
e
(
TAG
,
"updateDownloadIndex failed"
,
e
);
}
}
});
});
}
}
...
@@ -536,20 +621,6 @@ public final class DownloadManager {
...
@@ -536,20 +621,6 @@ public final class DownloadManager {
}
}
}
}
@Requirements
.
RequirementFlags
private
int
watchRequirements
(
Requirements
requirements
)
{
RequirementsWatcher
.
Listener
listener
=
(
requirementsWatcher
,
notMetRequirements
)
->
onRequirementsStateChanged
(
notMetRequirements
);
requirementsWatcher
=
new
RequirementsWatcher
(
context
,
listener
,
requirements
);
@Requirements
.
RequirementFlags
int
notMetRequirements
=
requirementsWatcher
.
start
();
if
(
notMetRequirements
==
0
)
{
startDownloads
();
}
else
{
stopDownloads
();
}
return
notMetRequirements
;
}
@StartThreadResults
@StartThreadResults
private
int
startDownloadThread
(
Download
download
,
DownloadAction
action
)
{
private
int
startDownloadThread
(
Download
download
,
DownloadAction
action
)
{
if
(!
initialized
||
released
)
{
if
(!
initialized
||
released
)
{
...
@@ -634,13 +705,13 @@ public final class DownloadManager {
...
@@ -634,13 +705,13 @@ public final class DownloadManager {
private
Download
(
private
Download
(
DownloadManager
downloadManager
,
DownloadManager
downloadManager
,
Download
Action
action
,
Download
State
downloadState
,
@Requirements
.
RequirementFlags
int
notMetRequirements
,
@Requirements
.
RequirementFlags
int
notMetRequirements
,
int
manualStopReason
)
{
int
manualStopReason
)
{
this
.
downloadManager
=
downloadManager
;
this
.
downloadManager
=
downloadManager
;
this
.
downloadState
=
downloadState
;
this
.
notMetRequirements
=
notMetRequirements
;
this
.
notMetRequirements
=
notMetRequirements
;
this
.
manualStopReason
=
manualStopReason
;
this
.
manualStopReason
=
manualStopReason
;
downloadState
=
new
DownloadState
(
action
);
initialize
(
downloadState
.
state
);
initialize
(
downloadState
.
state
);
}
}
...
@@ -649,17 +720,17 @@ public final class DownloadManager {
...
@@ -649,17 +720,17 @@ public final class DownloadManager {
return
downloadState
.
id
;
return
downloadState
.
id
;
}
}
public
boolean
addAction
(
DownloadAction
newAction
)
{
public
void
addAction
(
DownloadAction
newAction
)
{
if
(!
getId
().
equals
(
newAction
.
id
))
{
Assertions
.
checkArgument
(
getId
().
equals
(
newAction
.
id
));
return
false
;
if
(!
downloadState
.
type
.
equals
(
newAction
.
type
))
{
String
format
=
"Action type (%s) doesn't match existing download type (%s)"
;
Log
.
e
(
TAG
,
String
.
format
(
format
,
newAction
.
type
,
downloadState
.
type
));
}
}
Assertions
.
checkState
(
downloadState
.
type
.
equals
(
newAction
.
type
));
downloadState
=
downloadState
.
mergeAction
(
newAction
);
downloadState
=
downloadState
.
mergeAction
(
newAction
);
initialize
(
downloadState
.
state
);
initialize
(
downloadState
.
state
);
return
true
;
}
}
public
DownloadState
getDownloadState
()
{
public
DownloadState
get
Updated
DownloadState
()
{
float
downloadPercentage
=
C
.
PERCENTAGE_UNSET
;
float
downloadPercentage
=
C
.
PERCENTAGE_UNSET
;
long
downloadedBytes
=
0
;
long
downloadedBytes
=
0
;
long
totalBytes
=
C
.
LENGTH_UNSET
;
long
totalBytes
=
C
.
LENGTH_UNSET
;
...
@@ -721,6 +792,7 @@ public final class DownloadManager {
...
@@ -721,6 +792,7 @@ public final class DownloadManager {
}
}
private
void
updateStopState
()
{
private
void
updateStopState
()
{
DownloadState
oldDownloadState
=
downloadState
;
if
(
canStart
())
{
if
(
canStart
())
{
if
(
state
==
STATE_STOPPED
)
{
if
(
state
==
STATE_STOPPED
)
{
startOrQueue
();
startOrQueue
();
...
@@ -731,6 +803,9 @@ public final class DownloadManager {
...
@@ -731,6 +803,9 @@ public final class DownloadManager {
setState
(
STATE_STOPPED
);
setState
(
STATE_STOPPED
);
}
}
}
}
if
(
oldDownloadState
==
downloadState
)
{
downloadManager
.
onDownloadStateChange
(
this
,
getUpdatedDownloadState
());
}
}
}
private
void
initialize
(
int
initialState
)
{
private
void
initialize
(
int
initialState
)
{
...
@@ -745,7 +820,7 @@ public final class DownloadManager {
...
@@ -745,7 +820,7 @@ public final class DownloadManager {
setState
(
STATE_STOPPED
);
setState
(
STATE_STOPPED
);
}
}
if
(
state
==
initialState
)
{
if
(
state
==
initialState
)
{
downloadManager
.
onDownloadStateChange
(
this
);
downloadManager
.
onDownloadStateChange
(
this
,
getUpdatedDownloadState
()
);
}
}
}
}
...
@@ -770,20 +845,18 @@ public final class DownloadManager {
...
@@ -770,20 +845,18 @@ public final class DownloadManager {
return
DownloadAction
.
createRemoveAction
(
return
DownloadAction
.
createRemoveAction
(
downloadState
.
type
,
downloadState
.
uri
,
downloadState
.
cacheKey
);
downloadState
.
type
,
downloadState
.
uri
,
downloadState
.
cacheKey
);
}
}
return
getDownloadAction
(
downloadState
);
return
DownloadAction
.
createDownloadAction
(
}
downloadState
.
type
,
downloadState
.
uri
,
private
void
addActions
(
List
<
DownloadAction
>
actions
)
{
Arrays
.
asList
(
downloadState
.
streamKeys
),
actions
.
add
(
getAction
());
downloadState
.
cacheKey
,
if
(
state
==
STATE_RESTARTING
)
{
downloadState
.
customMetadata
);
actions
.
add
(
getDownloadAction
(
downloadState
));
}
}
}
private
void
setState
(
@DownloadState
.
State
int
newState
)
{
private
void
setState
(
@DownloadState
.
State
int
newState
)
{
if
(
state
!=
newState
)
{
if
(
state
!=
newState
)
{
state
=
newState
;
state
=
newState
;
downloadManager
.
onDownloadStateChange
(
this
);
downloadManager
.
onDownloadStateChange
(
this
,
getUpdatedDownloadState
()
);
}
}
}
}
...
@@ -808,14 +881,6 @@ public final class DownloadManager {
...
@@ -808,14 +881,6 @@ public final class DownloadManager {
}
}
}
}
private
static
DownloadAction
getDownloadAction
(
DownloadState
downloadState
)
{
return
DownloadAction
.
createDownloadAction
(
downloadState
.
type
,
downloadState
.
uri
,
Arrays
.
asList
(
downloadState
.
streamKeys
),
downloadState
.
cacheKey
,
downloadState
.
customMetadata
);
}
}
}
private
class
DownloadThread
extends
Thread
{
private
class
DownloadThread
extends
Thread
{
...
...
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
View file @
3919f384
...
@@ -25,10 +25,10 @@ import com.google.android.exoplayer2.C;
...
@@ -25,10 +25,10 @@ import com.google.android.exoplayer2.C;
import
com.google.android.exoplayer2.offline.DownloadState.State
;
import
com.google.android.exoplayer2.offline.DownloadState.State
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.scheduler.Requirements
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.DummyMainThread
;
import
com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable
;
import
com.google.android.exoplayer2.testutil.RobolectricUtil
;
import
com.google.android.exoplayer2.testutil.RobolectricUtil
;
import
com.google.android.exoplayer2.testutil.TestDownloadManagerListener
;
import
com.google.android.exoplayer2.testutil.TestDownloadManagerListener
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.testutil.TestUtil
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
...
@@ -64,7 +64,7 @@ public class DownloadManagerTest {
...
@@ -64,7 +64,7 @@ public class DownloadManagerTest {
private
Uri
uri2
;
private
Uri
uri2
;
private
Uri
uri3
;
private
Uri
uri3
;
private
DummyMainThread
dummyMainThread
;
private
DummyMainThread
dummyMainThread
;
private
File
actionFile
;
private
DefaultDownloadIndex
downloadIndex
;
private
TestDownloadManagerListener
downloadManagerListener
;
private
TestDownloadManagerListener
downloadManagerListener
;
private
FakeDownloaderFactory
downloaderFactory
;
private
FakeDownloaderFactory
downloaderFactory
;
private
DownloadManager
downloadManager
;
private
DownloadManager
downloadManager
;
...
@@ -77,7 +77,7 @@ public class DownloadManagerTest {
...
@@ -77,7 +77,7 @@ public class DownloadManagerTest {
uri2
=
Uri
.
parse
(
"http://abc.com/media2"
);
uri2
=
Uri
.
parse
(
"http://abc.com/media2"
);
uri3
=
Uri
.
parse
(
"http://abc.com/media3"
);
uri3
=
Uri
.
parse
(
"http://abc.com/media3"
);
dummyMainThread
=
new
DummyMainThread
();
dummyMainThread
=
new
DummyMainThread
();
actionFile
=
Util
.
createTempFile
(
ApplicationProvider
.
getApplicationContext
(),
"ExoPlayerTest"
);
downloadIndex
=
new
DefaultDownloadIndex
(
TestUtil
.
getTestDatabaseProvider
()
);
downloaderFactory
=
new
FakeDownloaderFactory
();
downloaderFactory
=
new
FakeDownloaderFactory
();
setUpDownloadManager
(
100
);
setUpDownloadManager
(
100
);
}
}
...
@@ -85,7 +85,6 @@ public class DownloadManagerTest {
...
@@ -85,7 +85,6 @@ public class DownloadManagerTest {
@After
@After
public
void
tearDown
()
throws
Exception
{
public
void
tearDown
()
throws
Exception
{
releaseDownloadManager
();
releaseDownloadManager
();
actionFile
.
delete
();
dummyMainThread
.
release
();
dummyMainThread
.
release
();
}
}
...
@@ -359,6 +358,7 @@ public class DownloadManagerTest {
...
@@ -359,6 +358,7 @@ public class DownloadManagerTest {
TaskWrapper
task2
=
new
DownloadRunner
(
uri2
).
postDownloadAction
().
getTask
();
TaskWrapper
task2
=
new
DownloadRunner
(
uri2
).
postDownloadAction
().
getTask
();
TaskWrapper
task3
=
new
DownloadRunner
(
uri3
).
postRemoveAction
().
getTask
();
TaskWrapper
task3
=
new
DownloadRunner
(
uri3
).
postRemoveAction
().
getTask
();
task3
.
assertRemoving
();
DownloadState
[]
states
=
downloadManager
.
getAllDownloadStates
();
DownloadState
[]
states
=
downloadManager
.
getAllDownloadStates
();
assertThat
(
states
).
hasLength
(
3
);
assertThat
(
states
).
hasLength
(
3
);
...
@@ -471,7 +471,7 @@ public class DownloadManagerTest {
...
@@ -471,7 +471,7 @@ public class DownloadManagerTest {
downloadManager
=
downloadManager
=
new
DownloadManager
(
new
DownloadManager
(
ApplicationProvider
.
getApplicationContext
(),
ApplicationProvider
.
getApplicationContext
(),
actionFile
,
downloadIndex
,
downloaderFactory
,
downloaderFactory
,
maxActiveDownloadTasks
,
maxActiveDownloadTasks
,
MIN_RETRY_COUNT
,
MIN_RETRY_COUNT
,
...
@@ -494,8 +494,8 @@ public class DownloadManagerTest {
...
@@ -494,8 +494,8 @@ public class DownloadManagerTest {
}
}
}
}
private
void
runOnMainThread
(
final
Runnable
r
)
{
private
void
runOnMainThread
(
final
Test
Runnable
r
)
{
dummyMainThread
.
runOnMainThread
(
r
);
dummyMainThread
.
run
Test
OnMainThread
(
r
);
}
}
private
final
class
DownloadRunner
{
private
final
class
DownloadRunner
{
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
View file @
3919f384
...
@@ -27,6 +27,7 @@ import android.os.ConditionVariable;
...
@@ -27,6 +27,7 @@ import android.os.ConditionVariable;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.offline.DefaultDownloadIndex
;
import
com.google.android.exoplayer2.offline.DefaultDownloaderFactory
;
import
com.google.android.exoplayer2.offline.DefaultDownloaderFactory
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
...
@@ -69,7 +70,7 @@ public class DownloadManagerDashTest {
...
@@ -69,7 +70,7 @@ public class DownloadManagerDashTest {
private
StreamKey
fakeStreamKey1
;
private
StreamKey
fakeStreamKey1
;
private
StreamKey
fakeStreamKey2
;
private
StreamKey
fakeStreamKey2
;
private
TestDownloadManagerListener
downloadManagerListener
;
private
TestDownloadManagerListener
downloadManagerListener
;
private
File
actionFile
;
private
DefaultDownloadIndex
downloadIndex
;
private
DummyMainThread
dummyMainThread
;
private
DummyMainThread
dummyMainThread
;
@Before
@Before
...
@@ -95,7 +96,7 @@ public class DownloadManagerDashTest {
...
@@ -95,7 +96,7 @@ public class DownloadManagerDashTest {
fakeStreamKey1
=
new
StreamKey
(
0
,
0
,
0
);
fakeStreamKey1
=
new
StreamKey
(
0
,
0
,
0
);
fakeStreamKey2
=
new
StreamKey
(
0
,
1
,
0
);
fakeStreamKey2
=
new
StreamKey
(
0
,
1
,
0
);
actionFile
=
new
File
(
tempFolder
,
"actionFile"
);
downloadIndex
=
new
DefaultDownloadIndex
(
TestUtil
.
getTestDatabaseProvider
()
);
createDownloadManager
();
createDownloadManager
();
}
}
...
@@ -136,8 +137,6 @@ public class DownloadManagerDashTest {
...
@@ -136,8 +137,6 @@ public class DownloadManagerDashTest {
downloadManager
.
release
();
downloadManager
.
release
();
});
});
assertThat
(
actionFile
.
exists
()).
isTrue
();
assertThat
(
actionFile
.
length
()).
isGreaterThan
(
0L
);
assertCacheEmpty
(
cache
);
assertCacheEmpty
(
cache
);
// Revert fakeDataSet to normal.
// Revert fakeDataSet to normal.
...
@@ -239,13 +238,13 @@ public class DownloadManagerDashTest {
...
@@ -239,13 +238,13 @@ public class DownloadManagerDashTest {
}
}
private
void
createDownloadManager
()
{
private
void
createDownloadManager
()
{
dummyMainThread
.
runOnMainThread
(
dummyMainThread
.
run
Test
OnMainThread
(
()
->
{
()
->
{
Factory
fakeDataSourceFactory
=
new
FakeDataSource
.
Factory
().
setFakeDataSet
(
fakeDataSet
);
Factory
fakeDataSourceFactory
=
new
FakeDataSource
.
Factory
().
setFakeDataSet
(
fakeDataSet
);
downloadManager
=
downloadManager
=
new
DownloadManager
(
new
DownloadManager
(
ApplicationProvider
.
getApplicationContext
(),
ApplicationProvider
.
getApplicationContext
(),
actionFile
,
downloadIndex
,
new
DefaultDownloaderFactory
(
new
DefaultDownloaderFactory
(
new
DownloaderConstructorHelper
(
cache
,
fakeDataSourceFactory
)),
new
DownloaderConstructorHelper
(
cache
,
fakeDataSourceFactory
)),
/* maxSimultaneousDownloads= */
1
,
/* maxSimultaneousDownloads= */
1
,
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
View file @
3919f384
...
@@ -26,6 +26,7 @@ import android.net.Uri;
...
@@ -26,6 +26,7 @@ import android.net.Uri;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.offline.DefaultDownloadIndex
;
import
com.google.android.exoplayer2.offline.DefaultDownloaderFactory
;
import
com.google.android.exoplayer2.offline.DefaultDownloaderFactory
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
...
@@ -107,19 +108,14 @@ public class DownloadServiceDashTest {
...
@@ -107,19 +108,14 @@ public class DownloadServiceDashTest {
fakeStreamKey1
=
new
StreamKey
(
0
,
0
,
0
);
fakeStreamKey1
=
new
StreamKey
(
0
,
0
,
0
);
fakeStreamKey2
=
new
StreamKey
(
0
,
1
,
0
);
fakeStreamKey2
=
new
StreamKey
(
0
,
1
,
0
);
dummyMainThread
.
runOnMainThread
(
dummyMainThread
.
run
Test
OnMainThread
(
()
->
{
()
->
{
File
actionFile
;
DefaultDownloadIndex
downloadIndex
=
try
{
new
DefaultDownloadIndex
(
TestUtil
.
getTestDatabaseProvider
());
actionFile
=
Util
.
createTempFile
(
context
,
"ExoPlayerTest"
);
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
e
);
}
actionFile
.
delete
();
final
DownloadManager
dashDownloadManager
=
final
DownloadManager
dashDownloadManager
=
new
DownloadManager
(
new
DownloadManager
(
ApplicationProvider
.
getApplicationContext
(),
ApplicationProvider
.
getApplicationContext
(),
actionFile
,
downloadIndex
,
new
DefaultDownloaderFactory
(
new
DefaultDownloaderFactory
(
new
DownloaderConstructorHelper
(
cache
,
fakeDataSourceFactory
)),
new
DownloaderConstructorHelper
(
cache
,
fakeDataSourceFactory
)),
/* maxSimultaneousDownloads= */
1
,
/* maxSimultaneousDownloads= */
1
,
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java
View file @
3919f384
...
@@ -27,6 +27,11 @@ import java.util.concurrent.atomic.AtomicReference;
...
@@ -27,6 +27,11 @@ import java.util.concurrent.atomic.AtomicReference;
/** Helper class to simulate main/UI thread in tests. */
/** Helper class to simulate main/UI thread in tests. */
public
final
class
DummyMainThread
{
public
final
class
DummyMainThread
{
/** {@link Runnable} variant which can throw a checked exception. */
public
interface
TestRunnable
{
void
run
()
throws
Exception
;
}
/** Default timeout value used for {@link #runOnMainThread(Runnable)}. */
/** Default timeout value used for {@link #runOnMainThread(Runnable)}. */
public
static
final
int
TIMEOUT_MS
=
10000
;
public
static
final
int
TIMEOUT_MS
=
10000
;
...
@@ -57,8 +62,33 @@ public final class DummyMainThread {
...
@@ -57,8 +62,33 @@ public final class DummyMainThread {
* @param runnable The {@link Runnable} to run.
* @param runnable The {@link Runnable} to run.
*/
*/
public
void
runOnMainThread
(
int
timeoutMs
,
final
Runnable
runnable
)
{
public
void
runOnMainThread
(
int
timeoutMs
,
final
Runnable
runnable
)
{
runTestOnMainThread
(
timeoutMs
,
runnable:
:
run
);
}
/**
* Runs the provided {@link TestRunnable} on the main thread, blocking until execution completes
* or until {@link #TIMEOUT_MS} milliseconds have passed.
*
* @param runnable The {@link TestRunnable} to run.
*/
public
void
runTestOnMainThread
(
final
TestRunnable
runnable
)
{
runTestOnMainThread
(
TIMEOUT_MS
,
runnable
);
}
/**
* Runs the provided {@link TestRunnable} on the main thread, blocking until execution completes
* or until timeout milliseconds have passed.
*
* @param timeoutMs The maximum time to wait in milliseconds.
* @param runnable The {@link TestRunnable} to run.
*/
public
void
runTestOnMainThread
(
int
timeoutMs
,
final
TestRunnable
runnable
)
{
if
(
Looper
.
myLooper
()
==
handler
.
getLooper
())
{
if
(
Looper
.
myLooper
()
==
handler
.
getLooper
())
{
runnable
.
run
();
try
{
runnable
.
run
();
}
catch
(
Exception
e
)
{
Util
.
sneakyThrow
(
e
);
}
}
else
{
}
else
{
ConditionVariable
finishedCondition
=
new
ConditionVariable
();
ConditionVariable
finishedCondition
=
new
ConditionVariable
();
AtomicReference
<
Throwable
>
thrown
=
new
AtomicReference
<>();
AtomicReference
<
Throwable
>
thrown
=
new
AtomicReference
<>();
...
...
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