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
8c624081
authored
Apr 18, 2019
by
olly
Committed by
Oliver Woodman
Apr 18, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Rename start/stopDownloads to resume/pauseDownloads
PiperOrigin-RevId: 244216620
parent
138da6d5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
91 additions
and
71 deletions
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/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
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
View file @
8c624081
...
@@ -55,8 +55,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
...
@@ -55,8 +55,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* Manages downloads.
* Manages downloads.
*
*
* <p>Normally a download manager should be accessed via a {@link DownloadService}. When a download
* <p>Normally a download manager should be accessed via a {@link DownloadService}. When a download
* manager is used directly instead, downloads will be initially
stopped and so must be start
ed by
* manager is used directly instead, downloads will be initially
paused and so must be resum
ed by
* calling {@link #
start
Downloads()}.
* calling {@link #
resume
Downloads()}.
*
*
* <p>A download manager instance must be accessed only from the thread that created it, unless that
* <p>A download manager instance must be accessed only from the thread that created it, unless that
* thread does not have a {@link Looper}. In that case, it must be accessed only from the
* thread does not have a {@link Looper}. In that case, it must be accessed only from the
...
@@ -126,7 +126,7 @@ public final class DownloadManager {
...
@@ -126,7 +126,7 @@ public final class DownloadManager {
// Messages posted to the background handler.
// Messages posted to the background handler.
private
static
final
int
MSG_INITIALIZE
=
0
;
private
static
final
int
MSG_INITIALIZE
=
0
;
private
static
final
int
MSG_SET_DOWNLOADS_
START
ED
=
1
;
private
static
final
int
MSG_SET_DOWNLOADS_
RESUM
ED
=
1
;
private
static
final
int
MSG_SET_NOT_MET_REQUIREMENTS
=
2
;
private
static
final
int
MSG_SET_NOT_MET_REQUIREMENTS
=
2
;
private
static
final
int
MSG_SET_STOP_REASON
=
3
;
private
static
final
int
MSG_SET_STOP_REASON
=
3
;
private
static
final
int
MSG_ADD_DOWNLOAD
=
4
;
private
static
final
int
MSG_ADD_DOWNLOAD
=
4
;
...
@@ -179,7 +179,7 @@ public final class DownloadManager {
...
@@ -179,7 +179,7 @@ public final class DownloadManager {
// Mutable fields that are accessed on the internal thread.
// Mutable fields that are accessed on the internal thread.
@Requirements
.
RequirementFlags
private
int
notMetRequirements
;
@Requirements
.
RequirementFlags
private
int
notMetRequirements
;
private
boolean
downloads
Start
ed
;
private
boolean
downloads
Resum
ed
;
private
int
simultaneousDownloads
;
private
int
simultaneousDownloads
;
/**
/**
...
@@ -346,19 +346,19 @@ public final class DownloadManager {
...
@@ -346,19 +346,19 @@ public final class DownloadManager {
return
Collections
.
unmodifiableList
(
new
ArrayList
<>(
downloads
));
return
Collections
.
unmodifiableList
(
new
ArrayList
<>(
downloads
));
}
}
/**
Start
s all downloads except those that have a non-zero {@link Download#stopReason}. */
/**
Resume
s all downloads except those that have a non-zero {@link Download#stopReason}. */
public
void
start
Downloads
()
{
public
void
resume
Downloads
()
{
pendingMessages
++;
pendingMessages
++;
internalHandler
internalHandler
.
obtainMessage
(
MSG_SET_DOWNLOADS_
STARTED
,
/* downloadsStart
ed */
1
,
/* unused */
0
)
.
obtainMessage
(
MSG_SET_DOWNLOADS_
RESUMED
,
/* downloadsResum
ed */
1
,
/* unused */
0
)
.
sendToTarget
();
.
sendToTarget
();
}
}
/**
Stop
s all downloads. */
/**
Pause
s all downloads. */
public
void
stop
Downloads
()
{
public
void
pause
Downloads
()
{
pendingMessages
++;
pendingMessages
++;
internalHandler
internalHandler
.
obtainMessage
(
MSG_SET_DOWNLOADS_
STARTED
,
/* downloadsStart
ed */
0
,
/* unused */
0
)
.
obtainMessage
(
MSG_SET_DOWNLOADS_
RESUMED
,
/* downloadsResum
ed */
0
,
/* unused */
0
)
.
sendToTarget
();
.
sendToTarget
();
}
}
...
@@ -541,9 +541,9 @@ public final class DownloadManager {
...
@@ -541,9 +541,9 @@ public final class DownloadManager {
int
notMetRequirements
=
message
.
arg1
;
int
notMetRequirements
=
message
.
arg1
;
initializeInternal
(
notMetRequirements
);
initializeInternal
(
notMetRequirements
);
break
;
break
;
case
MSG_SET_DOWNLOADS_
START
ED:
case
MSG_SET_DOWNLOADS_
RESUM
ED:
boolean
downloads
Start
ed
=
message
.
arg1
!=
0
;
boolean
downloads
Resum
ed
=
message
.
arg1
!=
0
;
setDownloads
Started
(
downloadsStart
ed
);
setDownloads
Resumed
(
downloadsResum
ed
);
break
;
break
;
case
MSG_SET_NOT_MET_REQUIREMENTS:
case
MSG_SET_NOT_MET_REQUIREMENTS:
notMetRequirements
=
message
.
arg1
;
notMetRequirements
=
message
.
arg1
;
...
@@ -604,11 +604,11 @@ public final class DownloadManager {
...
@@ -604,11 +604,11 @@ public final class DownloadManager {
}
}
}
}
private
void
setDownloads
Started
(
boolean
downloadsStart
ed
)
{
private
void
setDownloads
Resumed
(
boolean
downloadsResum
ed
)
{
if
(
this
.
downloads
Started
==
downloadsStart
ed
)
{
if
(
this
.
downloads
Resumed
==
downloadsResum
ed
)
{
return
;
return
;
}
}
this
.
downloads
Started
=
downloadsStart
ed
;
this
.
downloads
Resumed
=
downloadsResum
ed
;
for
(
int
i
=
0
;
i
<
downloadInternals
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
downloadInternals
.
size
();
i
++)
{
downloadInternals
.
get
(
i
).
updateStopState
();
downloadInternals
.
get
(
i
).
updateStopState
();
}
}
...
@@ -813,7 +813,7 @@ public final class DownloadManager {
...
@@ -813,7 +813,7 @@ public final class DownloadManager {
}
}
private
boolean
canStartDownloads
()
{
private
boolean
canStartDownloads
()
{
return
downloads
Start
ed
&&
notMetRequirements
==
0
;
return
downloads
Resum
ed
&&
notMetRequirements
==
0
;
}
}
/* package */
static
Download
mergeRequest
(
/* package */
static
Download
mergeRequest
(
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
View file @
8c624081
...
@@ -66,24 +66,24 @@ public abstract class DownloadService extends Service {
...
@@ -66,24 +66,24 @@ public abstract class DownloadService extends Service {
public
static
final
String
ACTION_ADD
=
"com.google.android.exoplayer.downloadService.action.ADD"
;
public
static
final
String
ACTION_ADD
=
"com.google.android.exoplayer.downloadService.action.ADD"
;
/**
/**
*
Start
s all downloads except those that have a non-zero {@link Download#stopReason}. Extras:
*
Resume
s all downloads except those that have a non-zero {@link Download#stopReason}. Extras:
*
*
* <ul>
* <ul>
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
* </ul>
*/
*/
public
static
final
String
ACTION_
START
=
public
static
final
String
ACTION_
RESUME
=
"com.google.android.exoplayer.downloadService.action.
START
"
;
"com.google.android.exoplayer.downloadService.action.
RESUME
"
;
/**
/**
*
Stop
s all downloads. Extras:
*
Pause
s all downloads. Extras:
*
*
* <ul>
* <ul>
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
* </ul>
*/
*/
public
static
final
String
ACTION_
STOP
=
public
static
final
String
ACTION_
PAUSE
=
"com.google.android.exoplayer.downloadService.action.
STOP
"
;
"com.google.android.exoplayer.downloadService.action.
PAUSE
"
;
/**
/**
* Sets the stop reason for one or all downloads. To clear the stop reason, pass {@link
* Sets the stop reason for one or all downloads. To clear the stop reason, pass {@link
...
@@ -278,51 +278,51 @@ public abstract class DownloadService extends Service {
...
@@ -278,51 +278,51 @@ public abstract class DownloadService extends Service {
}
}
/**
/**
* Builds an {@link Intent} for setting the stop reason for one or all downloads. To clear the
* Builds an {@link Intent} for resuming all downloads.
* stop reason, pass {@link Download#STOP_REASON_NONE}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param clazz The concrete download service being targeted by the intent.
* @param id The content id, or {@code null} to set the stop reason for all downloads.
* @param stopReason An application defined stop reason.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @return Created Intent.
* @return Created Intent.
*/
*/
public
static
Intent
buildSetStopReasonIntent
(
public
static
Intent
buildResumeDownloadsIntent
(
Context
context
,
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Class
<?
extends
DownloadService
>
clazz
,
return
getIntent
(
context
,
clazz
,
ACTION_RESUME
,
foreground
);
@Nullable
String
id
,
int
stopReason
,
boolean
foreground
)
{
return
getIntent
(
context
,
clazz
,
ACTION_SET_STOP_REASON
,
foreground
)
.
putExtra
(
KEY_CONTENT_ID
,
id
)
.
putExtra
(
KEY_STOP_REASON
,
stopReason
);
}
}
/**
/**
* Builds an {@link Intent}
for starting
all downloads.
* Builds an {@link Intent}
to pause
all downloads.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param clazz The concrete download service being targeted by the intent.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @return Created Intent.
* @return Created Intent.
*/
*/
public
static
Intent
build
Start
DownloadsIntent
(
public
static
Intent
build
Pause
DownloadsIntent
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
return
getIntent
(
context
,
clazz
,
ACTION_
START
,
foreground
);
return
getIntent
(
context
,
clazz
,
ACTION_
PAUSE
,
foreground
);
}
}
/**
/**
* Builds an {@link Intent} for stopping all downloads.
* Builds an {@link Intent} for setting the stop reason for one or all downloads. To clear the
* stop reason, pass {@link Download#STOP_REASON_NONE}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param clazz The concrete download service being targeted by the intent.
* @param id The content id, or {@code null} to set the stop reason for all downloads.
* @param stopReason An application defined stop reason.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @return Created Intent.
* @return Created Intent.
*/
*/
public
static
Intent
buildStopDownloadsIntent
(
public
static
Intent
buildSetStopReasonIntent
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Context
context
,
return
getIntent
(
context
,
clazz
,
ACTION_STOP
,
foreground
);
Class
<?
extends
DownloadService
>
clazz
,
@Nullable
String
id
,
int
stopReason
,
boolean
foreground
)
{
return
getIntent
(
context
,
clazz
,
ACTION_SET_STOP_REASON
,
foreground
)
.
putExtra
(
KEY_CONTENT_ID
,
id
)
.
putExtra
(
KEY_STOP_REASON
,
stopReason
);
}
}
/**
/**
...
@@ -343,6 +343,26 @@ public abstract class DownloadService extends Service {
...
@@ -343,6 +343,26 @@ public abstract class DownloadService extends Service {
}
}
/**
/**
* Starts the service if not started already and adds a new download.
*
* @param context A {@link Context}.
* @param clazz The concrete download service to be started.
* @param downloadRequest The request to be executed.
* @param stopReason An initial stop reason for the download, or {@link Download#STOP_REASON_NONE}
* if the download should be started.
* @param foreground Whether the service is started in the foreground.
*/
public
static
void
sendNewDownload
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
DownloadRequest
downloadRequest
,
int
stopReason
,
boolean
foreground
)
{
Intent
intent
=
buildAddRequestIntent
(
context
,
clazz
,
downloadRequest
,
stopReason
,
foreground
);
startService
(
context
,
intent
,
foreground
);
}
/**
* Starts the service if not started already and removes a download.
* Starts the service if not started already and removes a download.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
...
@@ -357,48 +377,48 @@ public abstract class DownloadService extends Service {
...
@@ -357,48 +377,48 @@ public abstract class DownloadService extends Service {
}
}
/**
/**
* Starts the service if not started already and sets the stop reason for one or all downloads. To
* Starts the service if not started already and resumes all downloads.
* clear stop reason, pass {@link Download#STOP_REASON_NONE}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param clazz The concrete download service to be started.
* @param clazz The concrete download service to be started.
* @param id The content id, or {@code null} to set the stop reason for all downloads.
* @param stopReason An application defined stop reason.
* @param foreground Whether the service is started in the foreground.
* @param foreground Whether the service is started in the foreground.
*/
*/
public
static
void
sendStopReason
(
public
static
void
sendResumeDownloads
(
Context
context
,
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Class
<?
extends
DownloadService
>
clazz
,
Intent
intent
=
buildResumeDownloadsIntent
(
context
,
clazz
,
foreground
);
@Nullable
String
id
,
int
stopReason
,
boolean
foreground
)
{
Intent
intent
=
buildSetStopReasonIntent
(
context
,
clazz
,
id
,
stopReason
,
foreground
);
startService
(
context
,
intent
,
foreground
);
startService
(
context
,
intent
,
foreground
);
}
}
/**
/**
* Starts the service if not started already and
start
s all downloads.
* Starts the service if not started already and
pause
s all downloads.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param clazz The concrete download service to be started.
* @param clazz The concrete download service to be started.
* @param foreground Whether the service is started in the foreground.
* @param foreground Whether the service is started in the foreground.
*/
*/
public
static
void
send
Start
Downloads
(
public
static
void
send
Pause
Downloads
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Intent
intent
=
build
Start
DownloadsIntent
(
context
,
clazz
,
foreground
);
Intent
intent
=
build
Pause
DownloadsIntent
(
context
,
clazz
,
foreground
);
startService
(
context
,
intent
,
foreground
);
startService
(
context
,
intent
,
foreground
);
}
}
/**
/**
* Starts the service if not started already and stops all downloads.
* Starts the service if not started already and sets the stop reason for one or all downloads. To
* clear stop reason, pass {@link Download#STOP_REASON_NONE}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param clazz The concrete download service to be started.
* @param clazz The concrete download service to be started.
* @param id The content id, or {@code null} to set the stop reason for all downloads.
* @param stopReason An application defined stop reason.
* @param foreground Whether the service is started in the foreground.
* @param foreground Whether the service is started in the foreground.
*/
*/
public
static
void
sendStopDownloads
(
public
static
void
sendStopReason
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Context
context
,
Intent
intent
=
buildStopDownloadsIntent
(
context
,
clazz
,
foreground
);
Class
<?
extends
DownloadService
>
clazz
,
@Nullable
String
id
,
int
stopReason
,
boolean
foreground
)
{
Intent
intent
=
buildSetStopReasonIntent
(
context
,
clazz
,
id
,
stopReason
,
foreground
);
startService
(
context
,
intent
,
foreground
);
startService
(
context
,
intent
,
foreground
);
}
}
...
@@ -438,7 +458,7 @@ public abstract class DownloadService extends Service {
...
@@ -438,7 +458,7 @@ public abstract class DownloadService extends Service {
DownloadManagerHelper
downloadManagerHelper
=
downloadManagerListeners
.
get
(
clazz
);
DownloadManagerHelper
downloadManagerHelper
=
downloadManagerListeners
.
get
(
clazz
);
if
(
downloadManagerHelper
==
null
)
{
if
(
downloadManagerHelper
==
null
)
{
DownloadManager
downloadManager
=
getDownloadManager
();
DownloadManager
downloadManager
=
getDownloadManager
();
downloadManager
.
start
Downloads
();
downloadManager
.
resume
Downloads
();
downloadManagerHelper
=
downloadManagerHelper
=
new
DownloadManagerHelper
(
new
DownloadManagerHelper
(
getApplicationContext
(),
downloadManager
,
getScheduler
(),
clazz
);
getApplicationContext
(),
downloadManager
,
getScheduler
(),
clazz
);
...
@@ -477,11 +497,11 @@ public abstract class DownloadService extends Service {
...
@@ -477,11 +497,11 @@ public abstract class DownloadService extends Service {
downloadManager
.
addDownload
(
downloadRequest
,
stopReason
);
downloadManager
.
addDownload
(
downloadRequest
,
stopReason
);
}
}
break
;
break
;
case
ACTION_
START
:
case
ACTION_
RESUME
:
downloadManager
.
start
Downloads
();
downloadManager
.
resume
Downloads
();
break
;
break
;
case
ACTION_
STOP
:
case
ACTION_
PAUSE
:
downloadManager
.
stop
Downloads
();
downloadManager
.
pause
Downloads
();
break
;
break
;
case
ACTION_SET_STOP_REASON:
case
ACTION_SET_STOP_REASON:
if
(!
intent
.
hasExtra
(
KEY_STOP_REASON
))
{
if
(!
intent
.
hasExtra
(
KEY_STOP_REASON
))
{
...
...
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
View file @
8c624081
...
@@ -368,7 +368,7 @@ public class DownloadManagerTest {
...
@@ -368,7 +368,7 @@ public class DownloadManagerTest {
runner2
.
postDownloadRequest
().
postRemoveRequest
().
getTask
().
assertRemoving
();
runner2
.
postDownloadRequest
().
postRemoveRequest
().
getTask
().
assertRemoving
();
runner2
.
postDownloadRequest
();
runner2
.
postDownloadRequest
();
runOnMainThread
(()
->
downloadManager
.
stop
Downloads
());
runOnMainThread
(()
->
downloadManager
.
pause
Downloads
());
runner1
.
getTask
().
assertStopped
();
runner1
.
getTask
().
assertStopped
();
...
@@ -386,7 +386,7 @@ public class DownloadManagerTest {
...
@@ -386,7 +386,7 @@ public class DownloadManagerTest {
// New download requests can be added but they don't start.
// New download requests can be added but they don't start.
runner3
.
postDownloadRequest
().
getDownloader
(
0
).
assertDoesNotStart
();
runner3
.
postDownloadRequest
().
getDownloader
(
0
).
assertDoesNotStart
();
runOnMainThread
(()
->
downloadManager
.
start
Downloads
());
runOnMainThread
(()
->
downloadManager
.
resume
Downloads
());
runner2
.
getDownloader
(
2
).
assertStarted
().
unblock
();
runner2
.
getDownloader
(
2
).
assertStarted
().
unblock
();
runner3
.
getDownloader
(
0
).
assertStarted
().
unblock
();
runner3
.
getDownloader
(
0
).
assertStarted
().
unblock
();
...
@@ -532,7 +532,7 @@ public class DownloadManagerTest {
...
@@ -532,7 +532,7 @@ public class DownloadManagerTest {
maxActiveDownloadTasks
,
maxActiveDownloadTasks
,
MIN_RETRY_COUNT
,
MIN_RETRY_COUNT
,
new
Requirements
(
0
));
new
Requirements
(
0
));
downloadManager
.
start
Downloads
();
downloadManager
.
resume
Downloads
();
downloadManagerListener
=
downloadManagerListener
=
new
TestDownloadManagerListener
(
downloadManager
,
dummyMainThread
);
new
TestDownloadManagerListener
(
downloadManager
,
dummyMainThread
);
});
});
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
View file @
8c624081
...
@@ -268,7 +268,7 @@ public class DownloadManagerDashTest {
...
@@ -268,7 +268,7 @@ public class DownloadManagerDashTest {
downloadManagerListener
=
downloadManagerListener
=
new
TestDownloadManagerListener
(
new
TestDownloadManagerListener
(
downloadManager
,
dummyMainThread
,
/* timeout= */
3000
);
downloadManager
,
dummyMainThread
,
/* timeout= */
3000
);
downloadManager
.
start
Downloads
();
downloadManager
.
resume
Downloads
();
});
});
}
}
...
...
library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
View file @
8c624081
...
@@ -126,7 +126,7 @@ public class DownloadServiceDashTest {
...
@@ -126,7 +126,7 @@ public class DownloadServiceDashTest {
new
Requirements
(
0
));
new
Requirements
(
0
));
downloadManagerListener
=
downloadManagerListener
=
new
TestDownloadManagerListener
(
dashDownloadManager
,
dummyMainThread
);
new
TestDownloadManagerListener
(
dashDownloadManager
,
dummyMainThread
);
dashDownloadManager
.
start
Downloads
();
dashDownloadManager
.
resume
Downloads
();
dashDownloadService
=
dashDownloadService
=
new
DownloadService
(
DownloadService
.
FOREGROUND_NOTIFICATION_ID_NONE
)
{
new
DownloadService
(
DownloadService
.
FOREGROUND_NOTIFICATION_ID_NONE
)
{
...
...
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