package com.seafile.seadroid2.transfer; import android.util.Log; import com.google.common.collect.Lists; import com.seafile.seadroid2.util.ConcurrentAsyncTask; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Manages file downloading and uploading. * <p/> * Currently use an AsyncTask for an file. */ public abstract class TransferManager { private static final String DEBUG_TAG = "TransferManager"; public static final String BROADCAST_ACTION = "com.seafile.seadroid.TX_BROADCAST"; /** * unique task id */ protected int notificationID; protected static final int TRANSFER_MAX_COUNT = 2; /** * contains all transfer tasks, including failed, cancelled, finished, transferring, waiting tasks. */ protected List<TransferTask> allTaskList = Lists.newArrayList(); /** * contains currently transferring tasks */ protected List<TransferTask> transferringList = Lists.newArrayList(); /** * contains waiting tasks */ protected List<TransferTask> waitingList = Lists.newArrayList(); protected synchronized TransferTask getTask(int taskID) { for (TransferTask task : allTaskList) { if (task.getTaskID() == taskID) { return task; } } return null; } public TransferTaskInfo getTaskInfo(int taskID) { TransferTask task = getTask(taskID); if (task != null) { return task.getTaskInfo(); } return null; } private synchronized boolean hasInQue(TransferTask transferTask) { if (waitingList.contains(transferTask)) { // Log.d(DEBUG_TAG, "in Que " + taskID + " " + repoName + path + "in waiting list"); return true; } if (transferringList.contains(transferTask)) { // Log.d(DEBUG_TAG, "in Que " + taskID + " " + repoName + path + " in downloading list"); return true; } return false; } protected void addTaskToQue(TransferTask task) { if (!hasInQue(task)) { // remove the cancelled or failed task if any synchronized (this) { allTaskList.remove(task); // add new created task allTaskList.add(task); // Log.d(DEBUG_TAG, "add Que " + taskID + " " + repoName + path); waitingList.add(task); } doNext(); } } public synchronized void doNext() { if (!waitingList.isEmpty() && transferringList.size() < TRANSFER_MAX_COUNT) { Log.d(DEBUG_TAG, "do next!"); TransferTask task = waitingList.remove(0); transferringList.add(task); ConcurrentAsyncTask.execute(task); } } protected void cancel(int taskID) { TransferTask task = getTask(taskID); if (task != null) { task.cancel(); } remove(taskID); } protected synchronized void remove(int taskID) { TransferTask toCancel = getTask(taskID); if (toCancel == null) return; if (!waitingList.isEmpty()) { waitingList.remove(toCancel); } if (!transferringList.isEmpty()) { transferringList.remove(toCancel); } } public void removeInAllTaskList(int taskID) { TransferTask task = getTask(taskID); if (task != null) { synchronized (this) { allTaskList.remove(task); } } } public synchronized List<TransferTask> getTasksByState(TaskState taskState) { List<TransferTask> taskList = Lists.newArrayList(); Iterator<TransferTask> iter = allTaskList.iterator(); while (iter.hasNext()) { TransferTask task = iter.next(); if (task.state.equals(taskState)) { taskList.add(task); } } return taskList; } /** * remove tasks from {@link #allTaskList} by comparing the taskState, * all tasks with the same taskState will be removed. * * @param taskState * taskState */ public synchronized void removeByState(TaskState taskState) { Iterator<TransferTask> iter = allTaskList.iterator(); while (iter.hasNext()) { TransferTask task = iter.next(); if (task.getState().equals(taskState)) { iter.remove(); } } } /** * remove tasks from {@link #allTaskList} by traversing the taskId list * * @param ids * taskId list */ public synchronized void removeByIds(List<Integer> ids) { for (int taskID : ids) { TransferTask transferTask = getTask(taskID); allTaskList.remove(transferTask); } } /** * check if there are tasks under transferring state * * @return true, if there are tasks whose {@link com.seafile.seadroid2.transfer.TaskState} is {@code TRANSFERRING}. * false, otherwise. */ public boolean isTransferring() { List<? extends TransferTaskInfo> transferTaskInfos = getAllTaskInfoList(); for (TransferTaskInfo transferTaskInfo : transferTaskInfos) { if (transferTaskInfo.state.equals(TaskState.TRANSFERRING)) return true; } return false; } public void cancelAll() { List<? extends TransferTaskInfo> transferTaskInfos = getAllTaskInfoList(); for (TransferTaskInfo transferTaskInfo : transferTaskInfos) { cancel(transferTaskInfo.taskID); } } public void cancelByIds(List<Integer> taskIds) { for (int taskID : taskIds) { cancel(taskID); } } public synchronized List<? extends TransferTaskInfo> getAllTaskInfoList() { ArrayList<TransferTaskInfo> infos = Lists.newArrayList(); for (TransferTask task : allTaskList) { infos.add(task.getTaskInfo()); } return infos; } }