more of the same
* misc code clean-up * fix weird download speed, before switching the list view * fix CircularFile.java getting stuck on post-processing huge files >2GiB * keep crashed post-processing downloads visible to the user
This commit is contained in:
parent
feb8c27f1f
commit
9f4a7e664f
6 changed files with 84 additions and 59 deletions
|
@ -341,6 +341,12 @@ public class DownloadMission extends Mission {
|
||||||
finishCount++;
|
finishCount++;
|
||||||
|
|
||||||
if (finishCount == currentThreadCount) {
|
if (finishCount == currentThreadCount) {
|
||||||
|
if (errCode > ERROR_NOTHING) return;
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "onFinish" + (current + 1) + "/" + urls.length);
|
||||||
|
}
|
||||||
|
|
||||||
if ((current + 1) < urls.length) {
|
if ((current + 1) < urls.length) {
|
||||||
// prepare next sub-mission
|
// prepare next sub-mission
|
||||||
long current_offset = offsets[current++];
|
long current_offset = offsets[current++];
|
||||||
|
@ -354,10 +360,6 @@ public class DownloadMission extends Mission {
|
||||||
|
|
||||||
if (!doPostprocessing()) return;
|
if (!doPostprocessing()) return;
|
||||||
|
|
||||||
if (errCode > ERROR_NOTHING) return;
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "onFinish");
|
|
||||||
}
|
|
||||||
running = false;
|
running = false;
|
||||||
deleteThisFromFile();
|
deleteThisFromFile();
|
||||||
|
|
||||||
|
@ -517,10 +519,16 @@ public class DownloadMission extends Mission {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLength() {
|
public long getLength() {
|
||||||
long near = offsets[current < offsets.length ? current : (offsets.length - 1)] + length;
|
long calculated;
|
||||||
near -= offsets[0];// don't count reserved space
|
if (postprocessingRunning) {
|
||||||
|
calculated = length;
|
||||||
|
} else {
|
||||||
|
calculated = offsets[current < offsets.length ? current : (offsets.length - 1)] + length;
|
||||||
|
}
|
||||||
|
|
||||||
return near > nearLength ? near : nearLength;
|
calculated -= offsets[0];// don't count reserved space
|
||||||
|
|
||||||
|
return calculated > nearLength ? calculated : nearLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doPostprocessing() {
|
private boolean doPostprocessing() {
|
||||||
|
|
|
@ -91,7 +91,7 @@ public abstract class Postprocessing {
|
||||||
out = new CircularFile(file, 0, this::progressReport, checker);
|
out = new CircularFile(file, 0, this::progressReport, checker);
|
||||||
|
|
||||||
mission.done = 0;
|
mission.done = 0;
|
||||||
mission.length = mission.getLength();
|
mission.length = file.length();
|
||||||
|
|
||||||
int result = process(out, sources);
|
int result = process(out, sources);
|
||||||
|
|
||||||
|
|
|
@ -121,45 +121,37 @@ public class CircularFile extends SharpStream {
|
||||||
available = end - position;
|
available = end - position;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (available > 0 && auxiliaryBuffers.size() > 0) {
|
// Check if possible flush one or more auxiliary buffer
|
||||||
|
if (auxiliaryBuffers.size() > 0) {
|
||||||
ManagedBuffer aux = auxiliaryBuffers.get(0);
|
ManagedBuffer aux = auxiliaryBuffers.get(0);
|
||||||
|
|
||||||
// check if there is enough space to dump the auxiliary buffer
|
// check if there is enough space to flush it completely
|
||||||
if (available >= (aux.size + queue.size)) {
|
while (available >= (aux.size + queue.size)) {
|
||||||
available -= aux.size;
|
available -= aux.size;
|
||||||
writeQueue(aux.buffer, 0, aux.size);
|
writeQueue(aux.buffer, 0, aux.size);
|
||||||
aux.dereference();
|
aux.dereference();
|
||||||
auxiliaryBuffers.remove(0);
|
auxiliaryBuffers.remove(0);
|
||||||
continue;
|
|
||||||
|
if (auxiliaryBuffers.size() < 1) {
|
||||||
|
aux = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aux = auxiliaryBuffers.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IMMEDIATE_AUX_BUFFER_FLUSH) {
|
if (IMMEDIATE_AUX_BUFFER_FLUSH) {
|
||||||
// try flush contents to avoid allocate another auxiliary buffer
|
// try partial flush to avoid allocate another auxiliary buffer
|
||||||
if (aux.available() < len && available > queue.size) {
|
if (aux != null && aux.available() < len && available > queue.size) {
|
||||||
int size = Math.min(len, aux.available());
|
int size = Math.min(aux.size, (int) available - queue.size);
|
||||||
aux.write(b, off, size);
|
|
||||||
|
|
||||||
off += size;
|
|
||||||
len -= size;
|
|
||||||
|
|
||||||
size = Math.min(aux.size, (int) available - queue.size);
|
|
||||||
if (size < 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeQueue(aux.buffer, 0, size);
|
writeQueue(aux.buffer, 0, size);
|
||||||
aux.dereference(size);
|
aux.dereference(size);
|
||||||
|
|
||||||
available -= size;
|
available -= size;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auxiliaryBuffers.size() < 1 && available > (len + queue.size)) {
|
if (auxiliaryBuffers.size() < 1 && available > (len + queue.size)) {
|
||||||
writeQueue(b, off, len);
|
writeQueue(b, off, len);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -150,10 +150,8 @@ public class DownloadManager {
|
||||||
exists = true;
|
exists = true;
|
||||||
mis.postprocessingRunning = false;
|
mis.postprocessingRunning = false;
|
||||||
mis.errCode = DownloadMission.ERROR_POSTPROCESSING_FAILED;
|
mis.errCode = DownloadMission.ERROR_POSTPROCESSING_FAILED;
|
||||||
mis.errObject = new RuntimeException("post-processing stopped unexpectedly");
|
mis.errObject = new RuntimeException("stopped unexpectedly");
|
||||||
}
|
} else if (exists && !dl.isFile()) {
|
||||||
|
|
||||||
if (exists && !dl.isFile()) {
|
|
||||||
// probably a folder, this should never happens
|
// probably a folder, this should never happens
|
||||||
if (!sub.delete()) {
|
if (!sub.delete()) {
|
||||||
Log.w(TAG, "Unable to delete serialized file: " + sub.getPath());
|
Log.w(TAG, "Unable to delete serialized file: " + sub.getPath());
|
||||||
|
|
|
@ -90,8 +90,8 @@ public class DownloadManagerService extends Service {
|
||||||
private SharedPreferences mPrefs = null;
|
private SharedPreferences mPrefs = null;
|
||||||
private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange;
|
private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange;
|
||||||
|
|
||||||
private boolean wakeLockAcquired = false;
|
private boolean mLockAcquired = false;
|
||||||
private LockManager wakeLock = null;
|
private LockManager mLock = null;
|
||||||
|
|
||||||
private int downloadFailedNotificationID = DOWNLOADS_NOTIFICATION_ID + 1;
|
private int downloadFailedNotificationID = DOWNLOADS_NOTIFICATION_ID + 1;
|
||||||
private Builder downloadFailedNotification = null;
|
private Builder downloadFailedNotification = null;
|
||||||
|
@ -167,7 +167,7 @@ public class DownloadManagerService extends Service {
|
||||||
handlePreferenceChange(mPrefs, getString(R.string.downloads_cross_network));
|
handlePreferenceChange(mPrefs, getString(R.string.downloads_cross_network));
|
||||||
handlePreferenceChange(mPrefs, getString(R.string.downloads_maximum_retry));
|
handlePreferenceChange(mPrefs, getString(R.string.downloads_maximum_retry));
|
||||||
|
|
||||||
wakeLock = new LockManager(this);
|
mLock = new LockManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -228,7 +228,7 @@ public class DownloadManagerService extends Service {
|
||||||
|
|
||||||
mManager.pauseAllMissions();
|
mManager.pauseAllMissions();
|
||||||
|
|
||||||
if (wakeLockAcquired) wakeLock.releaseWifiAndCpu();
|
manageLock(false);
|
||||||
|
|
||||||
unregisterReceiver(mNetworkStateListener);
|
unregisterReceiver(mNetworkStateListener);
|
||||||
mPrefs.unregisterOnSharedPreferenceChangeListener(mPrefChangeListener);
|
mPrefs.unregisterOnSharedPreferenceChangeListener(mPrefChangeListener);
|
||||||
|
@ -341,12 +341,12 @@ public class DownloadManagerService extends Service {
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
startForeground(FOREGROUND_NOTIFICATION_ID, mNotification);
|
startForeground(FOREGROUND_NOTIFICATION_ID, mNotification);
|
||||||
if (!wakeLockAcquired) wakeLock.acquireWifiAndCpu();
|
|
||||||
} else {
|
} else {
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
if (wakeLockAcquired) wakeLock.releaseWifiAndCpu();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
manageLock(state);
|
||||||
|
|
||||||
mForeground = state;
|
mForeground = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,6 +476,17 @@ public class DownloadManagerService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void manageLock(boolean acquire) {
|
||||||
|
if (acquire == mLockAcquired) return;
|
||||||
|
|
||||||
|
if (acquire)
|
||||||
|
mLock.acquireWifiAndCpu();
|
||||||
|
else
|
||||||
|
mLock.releaseWifiAndCpu();
|
||||||
|
|
||||||
|
mLockAcquired = acquire;
|
||||||
|
}
|
||||||
|
|
||||||
// Wrapper of DownloadManager
|
// Wrapper of DownloadManager
|
||||||
public class DMBinder extends Binder {
|
public class DMBinder extends Binder {
|
||||||
public DownloadManager getDownloadManager() {
|
public DownloadManager getDownloadManager() {
|
||||||
|
|
|
@ -52,6 +52,17 @@ import us.shandian.giga.util.Utility;
|
||||||
|
|
||||||
import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
|
import static android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
|
||||||
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_CONNECT_HOST;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_FILE_CREATION;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_NO_CONTENT;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_HTTP_UNSUPPORTED_RANGE;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_NOTHING;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_PATH_CREATION;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_PERMISSION_DENIED;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_POSTPROCESSING_FAILED;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_SSL_EXCEPTION;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_UNKNOWN_EXCEPTION;
|
||||||
|
import static us.shandian.giga.get.DownloadMission.ERROR_UNKNOWN_HOST;
|
||||||
|
|
||||||
public class MissionAdapter extends Adapter<ViewHolder> {
|
public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
private static final SparseArray<String> ALGORITHMS = new SparseArray<>();
|
private static final SparseArray<String> ALGORITHMS = new SparseArray<>();
|
||||||
|
@ -158,24 +169,27 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
h.item = item;
|
h.item = item;
|
||||||
|
|
||||||
Utility.FileType type = Utility.getFileType(item.mission.kind, item.mission.name);
|
Utility.FileType type = Utility.getFileType(item.mission.kind, item.mission.name);
|
||||||
long length = item.mission instanceof FinishedMission ? item.mission.length : ((DownloadMission) item.mission).getLength();
|
|
||||||
|
|
||||||
h.icon.setImageResource(Utility.getIconForFileType(type));
|
h.icon.setImageResource(Utility.getIconForFileType(type));
|
||||||
h.name.setText(item.mission.name);
|
h.name.setText(item.mission.name);
|
||||||
h.size.setText(Utility.formatBytes(length));
|
|
||||||
|
|
||||||
h.progress.setColors(Utility.getBackgroundForFileType(mContext, type), Utility.getForegroundForFileType(mContext, type));
|
h.progress.setColors(Utility.getBackgroundForFileType(mContext, type), Utility.getForegroundForFileType(mContext, type));
|
||||||
|
|
||||||
if (h.item.mission instanceof DownloadMission) {
|
if (h.item.mission instanceof DownloadMission) {
|
||||||
DownloadMission mission = (DownloadMission) item.mission;
|
DownloadMission mission = (DownloadMission) item.mission;
|
||||||
h.progress.setMarquee(mission.done < 1);
|
String length = Utility.formatBytes(mission.getLength());
|
||||||
updateProgress(h);
|
if (mission.running && !mission.postprocessingRunning) length += " --.- kB/s";
|
||||||
|
|
||||||
|
h.size.setText(length);
|
||||||
h.pause.setTitle(mission.unknownLength ? R.string.stop : R.string.pause);
|
h.pause.setTitle(mission.unknownLength ? R.string.stop : R.string.pause);
|
||||||
|
h.lastCurrent = mission.current;
|
||||||
|
updateProgress(h);
|
||||||
mPendingDownloadsItems.add(h);
|
mPendingDownloadsItems.add(h);
|
||||||
} else {
|
} else {
|
||||||
h.progress.setMarquee(false);
|
h.progress.setMarquee(false);
|
||||||
h.status.setText("100%");
|
h.status.setText("100%");
|
||||||
h.progress.setProgress(1f);
|
h.progress.setProgress(1f);
|
||||||
|
h.size.setText(Utility.formatBytes(item.mission.length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +221,7 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
|
|
||||||
long deltaTime = now - h.lastTimeStamp;
|
long deltaTime = now - h.lastTimeStamp;
|
||||||
long deltaDone = mission.done - h.lastDone;
|
long deltaDone = mission.done - h.lastDone;
|
||||||
boolean hasError = mission.errCode != DownloadMission.ERROR_NOTHING;
|
boolean hasError = mission.errCode != ERROR_NOTHING;
|
||||||
|
|
||||||
// on error hide marquee or show if condition (mission.done < 1 || mission.unknownLength) is true
|
// on error hide marquee or show if condition (mission.done < 1 || mission.unknownLength) is true
|
||||||
h.progress.setMarquee(!hasError && (mission.done < 1 || mission.unknownLength));
|
h.progress.setMarquee(!hasError && (mission.done < 1 || mission.unknownLength));
|
||||||
|
@ -237,7 +251,9 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
long length = mission.getLength();
|
long length = mission.getLength();
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
if (!mission.running) {
|
if (mission.errCode == ERROR_POSTPROCESSING_FAILED) {
|
||||||
|
state = 0;
|
||||||
|
} else if (!mission.running) {
|
||||||
state = mission.enqueued ? 1 : 2;
|
state = mission.enqueued ? 1 : 2;
|
||||||
} else if (mission.postprocessingRunning) {
|
} else if (mission.postprocessingRunning) {
|
||||||
state = 3;
|
state = 3;
|
||||||
|
@ -363,36 +379,36 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
case 404:
|
case 404:
|
||||||
str.append(mContext.getString(R.string.error_http_not_found));
|
str.append(mContext.getString(R.string.error_http_not_found));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_NOTHING:
|
case ERROR_NOTHING:
|
||||||
str.append("¿?");
|
str.append("¿?");
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_FILE_CREATION:
|
case ERROR_FILE_CREATION:
|
||||||
str.append(mContext.getString(R.string.error_file_creation));
|
str.append(mContext.getString(R.string.error_file_creation));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_HTTP_NO_CONTENT:
|
case ERROR_HTTP_NO_CONTENT:
|
||||||
str.append(mContext.getString(R.string.error_http_no_content));
|
str.append(mContext.getString(R.string.error_http_no_content));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_HTTP_UNSUPPORTED_RANGE:
|
case ERROR_HTTP_UNSUPPORTED_RANGE:
|
||||||
str.append(mContext.getString(R.string.error_http_unsupported_range));
|
str.append(mContext.getString(R.string.error_http_unsupported_range));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_PATH_CREATION:
|
case ERROR_PATH_CREATION:
|
||||||
str.append(mContext.getString(R.string.error_path_creation));
|
str.append(mContext.getString(R.string.error_path_creation));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_PERMISSION_DENIED:
|
case ERROR_PERMISSION_DENIED:
|
||||||
str.append(mContext.getString(R.string.permission_denied));
|
str.append(mContext.getString(R.string.permission_denied));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_SSL_EXCEPTION:
|
case ERROR_SSL_EXCEPTION:
|
||||||
str.append(mContext.getString(R.string.error_ssl_exception));
|
str.append(mContext.getString(R.string.error_ssl_exception));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_UNKNOWN_HOST:
|
case ERROR_UNKNOWN_HOST:
|
||||||
str.append(mContext.getString(R.string.error_unknown_host));
|
str.append(mContext.getString(R.string.error_unknown_host));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_CONNECT_HOST:
|
case ERROR_CONNECT_HOST:
|
||||||
str.append(mContext.getString(R.string.error_connect_host));
|
str.append(mContext.getString(R.string.error_connect_host));
|
||||||
break;
|
break;
|
||||||
case DownloadMission.ERROR_POSTPROCESSING_FAILED:
|
case ERROR_POSTPROCESSING_FAILED:
|
||||||
str.append(mContext.getString(R.string.error_postprocessing_failed));
|
str.append(mContext.getString(R.string.error_postprocessing_failed));
|
||||||
case DownloadMission.ERROR_UNKNOWN_EXCEPTION:
|
case ERROR_UNKNOWN_EXCEPTION:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (mission.errCode >= 100 && mission.errCode < 600) {
|
if (mission.errCode >= 100 && mission.errCode < 600) {
|
||||||
|
@ -655,15 +671,15 @@ public class MissionAdapter extends Adapter<ViewHolder> {
|
||||||
if (mission.running) {
|
if (mission.running) {
|
||||||
pause.setVisible(true);
|
pause.setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
if (mission.errCode != DownloadMission.ERROR_NOTHING) {
|
if (mission.errCode != ERROR_NOTHING) {
|
||||||
showError.setVisible(true);
|
showError.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.setChecked(mission.enqueued);
|
queue.setChecked(mission.enqueued);
|
||||||
|
|
||||||
delete.setVisible(true);
|
delete.setVisible(true);
|
||||||
start.setVisible(mission.errCode != DownloadMission.ERROR_POSTPROCESSING_FAILED);
|
start.setVisible(mission.errCode != ERROR_POSTPROCESSING_FAILED);
|
||||||
queue.setVisible(mission.errCode != DownloadMission.ERROR_POSTPROCESSING_FAILED);
|
queue.setVisible(mission.errCode != ERROR_POSTPROCESSING_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue