diff --git a/app/src/main/java/us/shandian/giga/get/DownloadMission.java b/app/src/main/java/us/shandian/giga/get/DownloadMission.java index 79e01b8cc..f3a817ba8 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadMission.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadMission.java @@ -341,6 +341,12 @@ public class DownloadMission extends Mission { finishCount++; if (finishCount == currentThreadCount) { + if (errCode > ERROR_NOTHING) return; + + if (DEBUG) { + Log.d(TAG, "onFinish" + (current + 1) + "/" + urls.length); + } + if ((current + 1) < urls.length) { // prepare next sub-mission long current_offset = offsets[current++]; @@ -354,10 +360,6 @@ public class DownloadMission extends Mission { if (!doPostprocessing()) return; - if (errCode > ERROR_NOTHING) return; - if (DEBUG) { - Log.d(TAG, "onFinish"); - } running = false; deleteThisFromFile(); @@ -517,10 +519,16 @@ public class DownloadMission extends Mission { } public long getLength() { - long near = offsets[current < offsets.length ? current : (offsets.length - 1)] + length; - near -= offsets[0];// don't count reserved space + long calculated; + 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() { diff --git a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java index 88cc337fd..80726f705 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/Postprocessing.java @@ -91,7 +91,7 @@ public abstract class Postprocessing { out = new CircularFile(file, 0, this::progressReport, checker); mission.done = 0; - mission.length = mission.getLength(); + mission.length = file.length(); int result = process(out, sources); diff --git a/app/src/main/java/us/shandian/giga/postprocessing/io/CircularFile.java b/app/src/main/java/us/shandian/giga/postprocessing/io/CircularFile.java index 7e5ad9929..d2fc82d33 100644 --- a/app/src/main/java/us/shandian/giga/postprocessing/io/CircularFile.java +++ b/app/src/main/java/us/shandian/giga/postprocessing/io/CircularFile.java @@ -121,45 +121,37 @@ public class CircularFile extends SharpStream { 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); - // check if there is enough space to dump the auxiliary buffer - if (available >= (aux.size + queue.size)) { + // check if there is enough space to flush it completely + while (available >= (aux.size + queue.size)) { available -= aux.size; writeQueue(aux.buffer, 0, aux.size); aux.dereference(); auxiliaryBuffers.remove(0); - continue; + + if (auxiliaryBuffers.size() < 1) { + aux = null; + break; + } + aux = auxiliaryBuffers.get(0); } if (IMMEDIATE_AUX_BUFFER_FLUSH) { - // try flush contents to avoid allocate another auxiliary buffer - if (aux.available() < len && available > queue.size) { - int size = Math.min(len, aux.available()); - aux.write(b, off, size); - - off += size; - len -= size; - - size = Math.min(aux.size, (int) available - queue.size); - if (size < 1) { - break; - } + // try partial flush to avoid allocate another auxiliary buffer + if (aux != null && aux.available() < len && available > queue.size) { + int size = Math.min(aux.size, (int) available - queue.size); writeQueue(aux.buffer, 0, size); aux.dereference(size); available -= size; } - break; } } - if (len < 1) { - return; - } - if (auxiliaryBuffers.size() < 1 && available > (len + queue.size)) { writeQueue(b, off, len); } else { diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManager.java b/app/src/main/java/us/shandian/giga/service/DownloadManager.java index 55a22c8c5..6bcf84745 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -150,10 +150,8 @@ public class DownloadManager { exists = true; mis.postprocessingRunning = false; mis.errCode = DownloadMission.ERROR_POSTPROCESSING_FAILED; - mis.errObject = new RuntimeException("post-processing stopped unexpectedly"); - } - - if (exists && !dl.isFile()) { + mis.errObject = new RuntimeException("stopped unexpectedly"); + } else if (exists && !dl.isFile()) { // probably a folder, this should never happens if (!sub.delete()) { Log.w(TAG, "Unable to delete serialized file: " + sub.getPath()); diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index 557c5a28a..1bb28fe95 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -90,8 +90,8 @@ public class DownloadManagerService extends Service { private SharedPreferences mPrefs = null; private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = this::handlePreferenceChange; - private boolean wakeLockAcquired = false; - private LockManager wakeLock = null; + private boolean mLockAcquired = false; + private LockManager mLock = null; private int downloadFailedNotificationID = DOWNLOADS_NOTIFICATION_ID + 1; 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_maximum_retry)); - wakeLock = new LockManager(this); + mLock = new LockManager(this); } @Override @@ -228,7 +228,7 @@ public class DownloadManagerService extends Service { mManager.pauseAllMissions(); - if (wakeLockAcquired) wakeLock.releaseWifiAndCpu(); + manageLock(false); unregisterReceiver(mNetworkStateListener); mPrefs.unregisterOnSharedPreferenceChangeListener(mPrefChangeListener); @@ -341,12 +341,12 @@ public class DownloadManagerService extends Service { if (state) { startForeground(FOREGROUND_NOTIFICATION_ID, mNotification); - if (!wakeLockAcquired) wakeLock.acquireWifiAndCpu(); } else { stopForeground(true); - if (wakeLockAcquired) wakeLock.releaseWifiAndCpu(); } + manageLock(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 public class DMBinder extends Binder { public DownloadManager getDownloadManager() { diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 8c332565b..df5f9e429 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -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_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 { private static final SparseArray ALGORITHMS = new SparseArray<>(); @@ -158,24 +169,27 @@ public class MissionAdapter extends Adapter { h.item = item; 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.name.setText(item.mission.name); - h.size.setText(Utility.formatBytes(length)); h.progress.setColors(Utility.getBackgroundForFileType(mContext, type), Utility.getForegroundForFileType(mContext, type)); if (h.item.mission instanceof DownloadMission) { DownloadMission mission = (DownloadMission) item.mission; - h.progress.setMarquee(mission.done < 1); - updateProgress(h); + String length = Utility.formatBytes(mission.getLength()); + if (mission.running && !mission.postprocessingRunning) length += " --.- kB/s"; + + h.size.setText(length); h.pause.setTitle(mission.unknownLength ? R.string.stop : R.string.pause); + h.lastCurrent = mission.current; + updateProgress(h); mPendingDownloadsItems.add(h); } else { h.progress.setMarquee(false); h.status.setText("100%"); h.progress.setProgress(1f); + h.size.setText(Utility.formatBytes(item.mission.length)); } } @@ -207,7 +221,7 @@ public class MissionAdapter extends Adapter { long deltaTime = now - h.lastTimeStamp; 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 h.progress.setMarquee(!hasError && (mission.done < 1 || mission.unknownLength)); @@ -237,7 +251,9 @@ public class MissionAdapter extends Adapter { long length = mission.getLength(); int state; - if (!mission.running) { + if (mission.errCode == ERROR_POSTPROCESSING_FAILED) { + state = 0; + } else if (!mission.running) { state = mission.enqueued ? 1 : 2; } else if (mission.postprocessingRunning) { state = 3; @@ -363,36 +379,36 @@ public class MissionAdapter extends Adapter { case 404: str.append(mContext.getString(R.string.error_http_not_found)); break; - case DownloadMission.ERROR_NOTHING: + case ERROR_NOTHING: str.append("¿?"); break; - case DownloadMission.ERROR_FILE_CREATION: + case ERROR_FILE_CREATION: str.append(mContext.getString(R.string.error_file_creation)); break; - case DownloadMission.ERROR_HTTP_NO_CONTENT: + case ERROR_HTTP_NO_CONTENT: str.append(mContext.getString(R.string.error_http_no_content)); break; - case DownloadMission.ERROR_HTTP_UNSUPPORTED_RANGE: + case ERROR_HTTP_UNSUPPORTED_RANGE: str.append(mContext.getString(R.string.error_http_unsupported_range)); break; - case DownloadMission.ERROR_PATH_CREATION: + case ERROR_PATH_CREATION: str.append(mContext.getString(R.string.error_path_creation)); break; - case DownloadMission.ERROR_PERMISSION_DENIED: + case ERROR_PERMISSION_DENIED: str.append(mContext.getString(R.string.permission_denied)); break; - case DownloadMission.ERROR_SSL_EXCEPTION: + case ERROR_SSL_EXCEPTION: str.append(mContext.getString(R.string.error_ssl_exception)); break; - case DownloadMission.ERROR_UNKNOWN_HOST: + case ERROR_UNKNOWN_HOST: str.append(mContext.getString(R.string.error_unknown_host)); break; - case DownloadMission.ERROR_CONNECT_HOST: + case ERROR_CONNECT_HOST: str.append(mContext.getString(R.string.error_connect_host)); break; - case DownloadMission.ERROR_POSTPROCESSING_FAILED: + case ERROR_POSTPROCESSING_FAILED: str.append(mContext.getString(R.string.error_postprocessing_failed)); - case DownloadMission.ERROR_UNKNOWN_EXCEPTION: + case ERROR_UNKNOWN_EXCEPTION: break; default: if (mission.errCode >= 100 && mission.errCode < 600) { @@ -655,15 +671,15 @@ public class MissionAdapter extends Adapter { if (mission.running) { pause.setVisible(true); } else { - if (mission.errCode != DownloadMission.ERROR_NOTHING) { + if (mission.errCode != ERROR_NOTHING) { showError.setVisible(true); } queue.setChecked(mission.enqueued); delete.setVisible(true); - start.setVisible(mission.errCode != DownloadMission.ERROR_POSTPROCESSING_FAILED); - queue.setVisible(mission.errCode != DownloadMission.ERROR_POSTPROCESSING_FAILED); + start.setVisible(mission.errCode != ERROR_POSTPROCESSING_FAILED); + queue.setVisible(mission.errCode != ERROR_POSTPROCESSING_FAILED); } } } else {