aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Brabham <optedoblivion@cyngn.com>2015-04-02 20:33:41 -0700
committerMatt Garnes <matt@cyngn.com>2015-04-13 17:20:34 +0000
commit948e0d1d3407d8e611d0d82aac2f399703a494e3 (patch)
tree3c3cd6b89fee93a9e149c56dbadb6f0e4c2eee1f
parent17388c6d5436f7736b38e11dda30a8a7fd0e17f6 (diff)
downloadandroid_packages_apps_CMFileManager-948e0d1d3407d8e611d0d82aac2f399703a494e3.tar.gz
android_packages_apps_CMFileManager-948e0d1d3407d8e611d0d82aac2f399703a494e3.tar.bz2
android_packages_apps_CMFileManager-948e0d1d3407d8e611d0d82aac2f399703a494e3.zip
Implement ability to cancel file copy.
- Short circuit Java CopyCommand for move/copy when the user cancels the dialog. - Bubble up CancelledOperationException when the Cancel/Move operation is cancelled. Handle cancellation differently than success. Change-Id: I3e4426aaccf42e12bf299041d489e72b3b76a626 (cherry picked from commit 7e13ec2fa4fc052c2a880a8dba8ed871b3bc10ca)
-rw-r--r--src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java6
-rw-r--r--src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java8
-rw-r--r--src/com/cyanogenmod/filemanager/commands/java/Program.java12
-rw-r--r--src/com/cyanogenmod/filemanager/console/java/JavaConsole.java15
-rw-r--r--src/com/cyanogenmod/filemanager/console/shell/ShellConsole.java9
-rw-r--r--src/com/cyanogenmod/filemanager/ui/policy/ActionsPolicy.java15
-rw-r--r--src/com/cyanogenmod/filemanager/ui/policy/CompressActionPolicy.java12
-rw-r--r--src/com/cyanogenmod/filemanager/ui/policy/CopyMoveActionPolicy.java49
-rw-r--r--src/com/cyanogenmod/filemanager/ui/policy/DeleteActionPolicy.java7
-rw-r--r--src/com/cyanogenmod/filemanager/util/CommandHelper.java2
-rw-r--r--src/com/cyanogenmod/filemanager/util/FileHelper.java25
11 files changed, 133 insertions, 27 deletions
diff --git a/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java b/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java
index 0c7832cc..5d8073fd 100644
--- a/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java
+++ b/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java
@@ -19,6 +19,7 @@ package com.cyanogenmod.filemanager.commands.java;
import android.util.Log;
import com.cyanogenmod.filemanager.commands.CopyExecutable;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
@@ -64,7 +65,8 @@ public class CopyCommand extends Program implements CopyExecutable {
*/
@Override
public void execute()
- throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException {
+ throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException,
+ CancelledOperationException {
if (isTrace()) {
Log.v(TAG,
String.format("Moving from %s to %s", //$NON-NLS-1$
@@ -81,7 +83,7 @@ public class CopyCommand extends Program implements CopyExecutable {
}
//Copy recursively
- if (!FileHelper.copyRecursive(s, d, getBufferSize())) {
+ if (!FileHelper.copyRecursive(s, d, getBufferSize(), this)) {
if (isTrace()) {
Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$
}
diff --git a/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java b/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java
index b0c85fb3..c4943b27 100644
--- a/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java
+++ b/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java
@@ -19,6 +19,7 @@ package com.cyanogenmod.filemanager.commands.java;
import android.util.Log;
import com.cyanogenmod.filemanager.commands.MoveExecutable;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
@@ -64,7 +65,8 @@ public class MoveCommand extends Program implements MoveExecutable {
*/
@Override
public void execute()
- throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException {
+ throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException,
+ CancelledOperationException {
if (isTrace()) {
Log.v(TAG,
String.format("Creating from %s to %s", this.mSrc, this.mDst)); //$NON-NLS-1$
@@ -81,7 +83,7 @@ public class MoveCommand extends Program implements MoveExecutable {
//Move or copy recursively
if (d.exists()) {
- if (!FileHelper.copyRecursive(s, d, getBufferSize())) {
+ if (!FileHelper.copyRecursive(s, d, getBufferSize(), this)) {
if (isTrace()) {
Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$
}
@@ -95,7 +97,7 @@ public class MoveCommand extends Program implements MoveExecutable {
} else {
// Move between filesystem is not allow. If rename fails then use copy operation
if (!s.renameTo(d)) {
- if (!FileHelper.copyRecursive(s, d, getBufferSize())) {
+ if (!FileHelper.copyRecursive(s, d, getBufferSize(), this)) {
if (isTrace()) {
Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$
}
diff --git a/src/com/cyanogenmod/filemanager/commands/java/Program.java b/src/com/cyanogenmod/filemanager/commands/java/Program.java
index b5eeebd2..34e70cc5 100644
--- a/src/com/cyanogenmod/filemanager/commands/java/Program.java
+++ b/src/com/cyanogenmod/filemanager/commands/java/Program.java
@@ -17,6 +17,7 @@
package com.cyanogenmod.filemanager.commands.java;
import com.cyanogenmod.filemanager.commands.Executable;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
@@ -29,6 +30,7 @@ public abstract class Program implements Executable {
private boolean mTrace;
private int mBufferSize;
+ private boolean mCancelled = false;
/**
* Constructor of <code>Program</code>
@@ -92,6 +94,14 @@ public abstract class Program implements Executable {
* @throws ExecutionException If the operation returns a invalid exit code
*/
public abstract void execute()
- throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException;
+ throws InsufficientPermissionsException, NoSuchFileOrDirectory, ExecutionException,
+ CancelledOperationException;
+ public void requestCancel() {
+ mCancelled = true;
+ }
+
+ public boolean isCancelled() {
+ return mCancelled;
+ }
}
diff --git a/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java b/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java
index f59f7461..741fc8f5 100644
--- a/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java
+++ b/src/com/cyanogenmod/filemanager/console/java/JavaConsole.java
@@ -23,6 +23,7 @@ import com.cyanogenmod.filemanager.commands.Executable;
import com.cyanogenmod.filemanager.commands.ExecutableFactory;
import com.cyanogenmod.filemanager.commands.java.JavaExecutableFactory;
import com.cyanogenmod.filemanager.commands.java.Program;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.CommandNotFoundException;
import com.cyanogenmod.filemanager.console.ConsoleAllocException;
import com.cyanogenmod.filemanager.console.ExecutionException;
@@ -43,6 +44,7 @@ public final class JavaConsole extends VirtualConsole {
private static final String TAG = "JavaConsole"; //$NON-NLS-1$
private final int mBufferSize;
+ private Program mActiveProgram;
/**
* Constructor of <code>JavaConsole</code>
@@ -78,8 +80,8 @@ public final class JavaConsole extends VirtualConsole {
@Override
public synchronized void execute(Executable executable, Context ctx)
throws ConsoleAllocException, InsufficientPermissionsException, NoSuchFileOrDirectory,
- OperationTimeoutException, ExecutionException, CommandNotFoundException,
- ReadOnlyFilesystemException {
+ OperationTimeoutException, ExecutionException, CommandNotFoundException,
+ CancelledOperationException, ReadOnlyFilesystemException {
// Check that the program is a java program
try {
Program p = (Program)executable;
@@ -98,6 +100,7 @@ public final class JavaConsole extends VirtualConsole {
// Execute the program
final Program program = (Program)executable;
+ mActiveProgram = program;
program.setTrace(isTrace());
program.setBufferSize(this.mBufferSize);
if (program.isAsynchronous()) {
@@ -123,4 +126,12 @@ public final class JavaConsole extends VirtualConsole {
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onCancel() {
+ mActiveProgram.requestCancel();
+ return true;
+ }
} \ No newline at end of file
diff --git a/src/com/cyanogenmod/filemanager/console/shell/ShellConsole.java b/src/com/cyanogenmod/filemanager/console/shell/ShellConsole.java
index 88006079..b9464d27 100644
--- a/src/com/cyanogenmod/filemanager/console/shell/ShellConsole.java
+++ b/src/com/cyanogenmod/filemanager/console/shell/ShellConsole.java
@@ -1252,8 +1252,13 @@ public abstract class ShellConsole extends Console implements Program.ProgramLis
}
} catch (Throwable ex) {
Log.w(TAG,
- String.format("Unable to kill current program: %s", //$NON-NLS-1$
- this.mActiveCommand.getCommand()), ex);
+ String.format("Unable to kill current program: %s",
+ (
+ (this.mActiveCommand == null) ?
+ "" :
+ this.mActiveCommand.getCommand()
+ )
+ ), ex);
}
}
}
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/ActionsPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/ActionsPolicy.java
index 8964c5ef..c127d3fc 100644
--- a/src/com/cyanogenmod/filemanager/ui/policy/ActionsPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/ActionsPolicy.java
@@ -77,6 +77,12 @@ public abstract class ActionsPolicy {
* Method invoked when the operation was successfully
*/
void onSuccess();
+
+ /**
+ * Method invoked to handle cancelling
+ */
+ void onCancel();
+
}
/**
@@ -117,7 +123,9 @@ public abstract class ActionsPolicy {
this.mDialog.setOnCancelListener(new MessageProgressDialog.OnCancelListener() {
@Override
public boolean onCancel() {
- return task.cancel(true);
+ mCallable.onCancel();
+ task.cancel(true);
+ return true;
}
});
Spanned progress = this.mCallable.requestProgress();
@@ -155,8 +163,7 @@ public abstract class ActionsPolicy {
@Override
protected void onCancelled() {
- //Operation complete.
- this.mCallable.onSuccess();
+ this.mCallable.onCancel();
}
@Override
@@ -182,4 +189,4 @@ public abstract class ActionsPolicy {
protected static void showOperationSuccessMsg(Context ctx) {
DialogHelper.showToast(ctx, R.string.msgs_success, Toast.LENGTH_SHORT);
}
-} \ No newline at end of file
+}
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/CompressActionPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/CompressActionPolicy.java
index c2c10e5f..b5021b88 100644
--- a/src/com/cyanogenmod/filemanager/ui/policy/CompressActionPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/CompressActionPolicy.java
@@ -266,6 +266,11 @@ public final class CompressActionPolicy extends ActionsPolicy {
}
@Override
+ public void onCancel() {
+ // nop
+ }
+
+ @Override
public void doInBackground(Object... params) throws Throwable {
this.mCause = null;
this.mStarted = true;
@@ -568,6 +573,11 @@ public final class CompressActionPolicy extends ActionsPolicy {
}
@Override
+ public void onCancel() {
+ // nop
+ }
+
+ @Override
public void doInBackground(Object... params) throws Throwable {
this.mCause = null;
this.mStarted = true;
@@ -842,4 +852,4 @@ public final class CompressActionPolicy extends ActionsPolicy {
protected static void showOperationSuccessMsg(Context ctx, int res, String dst) {
DialogHelper.showToast(ctx, ctx.getString(res, dst), Toast.LENGTH_SHORT);
}
-} \ No newline at end of file
+}
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/CopyMoveActionPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/CopyMoveActionPolicy.java
index 33e0b985..c2dde32e 100644
--- a/src/com/cyanogenmod/filemanager/ui/policy/CopyMoveActionPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/CopyMoveActionPolicy.java
@@ -19,10 +19,13 @@ package com.cyanogenmod.filemanager.ui.policy;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
import android.text.Html;
import android.text.Spanned;
import com.cyanogenmod.filemanager.R;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
+import com.cyanogenmod.filemanager.console.Console;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
import com.cyanogenmod.filemanager.console.RelaunchableException;
import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
@@ -280,7 +283,7 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
}
@Override
public boolean isDialogCancellable() {
- return false;
+ return true;
}
@Override
@@ -301,8 +304,7 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
return Html.fromHtml(progress);
}
- @Override
- public void onSuccess() {
+ private void refreshUIAfterCompletion() {
// Remove orphan bookmark paths
if (files != null) {
for (LinkedResource linkedFiles : files) {
@@ -315,6 +317,11 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
// The reference is not the same, so refresh the complete navigation view
this.mOnRequestRefreshListener.onRequestRefresh(null, true);
}
+ }
+
+ @Override
+ public void onSuccess() {
+ refreshUIAfterCompletion();
ActionsPolicy.showOperationSuccessMsg(ctx);
}
@@ -341,6 +348,21 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
}
}
+ @Override
+ public void onCancel() {
+ if (mSrcConsole != null) {
+ mSrcConsole.onCancel();
+ }
+ if (mDstConsole != null) {
+ mDstConsole.onCancel();
+ }
+ refreshUIAfterCompletion();
+ }
+
+ // Handles required for issuing command death to the consoles
+ private Console mSrcConsole;
+ private Console mDstConsole;
+
/**
* Method that copy or move the file to another location
*
@@ -360,6 +382,21 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
// under using absolute paths) Issue: CYAN-2791
String source = src.getAbsolutePath() +
(src.isDirectory() ? File.separator : "");
+ String dest = dst.getAbsolutePath() +
+ (dst.isDirectory() ? File.separator : "");
+
+ /*
+ There is a possibility that the src and dst can have different consoles.
+ A possible case:
+ - src is from sd card and dst is secure storage
+ This could happen with anything that goes from a real console to a virtual
+ console or visa versa. Here we grab a handle on the console such that we
+ may explicitly kill the actions happening in both consoles.
+ */
+ // Need to derive the console for the source
+ mSrcConsole = CommandHelper.ensureConsoleForFile(ctx, null, source);
+ // Need to derive the console for the destination
+ mDstConsole = CommandHelper.ensureConsoleForFile(ctx, null, dest);
// Copy or move?
if (operation.compareTo(COPY_MOVE_OPERATION.MOVE) == 0 ||
@@ -368,13 +405,13 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
ctx,
source,
dst.getAbsolutePath(),
- null);
+ mSrcConsole);
} else {
CommandHelper.copy(
ctx,
source,
dst.getAbsolutePath(),
- null);
+ mSrcConsole);
}
} catch (Exception e) {
// Need to be relaunched?
@@ -545,4 +582,4 @@ public final class CopyMoveActionPolicy extends ActionsPolicy {
}
return true;
}
-} \ No newline at end of file
+}
diff --git a/src/com/cyanogenmod/filemanager/ui/policy/DeleteActionPolicy.java b/src/com/cyanogenmod/filemanager/ui/policy/DeleteActionPolicy.java
index 843afe24..003ed465 100644
--- a/src/com/cyanogenmod/filemanager/ui/policy/DeleteActionPolicy.java
+++ b/src/com/cyanogenmod/filemanager/ui/policy/DeleteActionPolicy.java
@@ -213,6 +213,11 @@ public final class DeleteActionPolicy extends ActionsPolicy {
}
@Override
+ public void onCancel() {
+
+ }
+
+ @Override
public void doInBackground(Object... params) throws Throwable {
this.mCause = null;
@@ -372,4 +377,4 @@ public final class DeleteActionPolicy extends ActionsPolicy {
}
return true;
}
-} \ No newline at end of file
+}
diff --git a/src/com/cyanogenmod/filemanager/util/CommandHelper.java b/src/com/cyanogenmod/filemanager/util/CommandHelper.java
index de717989..33ddc404 100644
--- a/src/com/cyanogenmod/filemanager/util/CommandHelper.java
+++ b/src/com/cyanogenmod/filemanager/util/CommandHelper.java
@@ -2012,7 +2012,7 @@ public final class CommandHelper {
* @throws IOException If initial directory couldn't be checked
* @throws FileNotFoundException If the initial directory not exists
*/
- private static Console ensureConsoleForFile(Context context, Console console, String src)
+ public static Console ensureConsoleForFile(Context context, Console console, String src)
throws FileNotFoundException, IOException, InvalidCommandDefinitionException,
ConsoleAllocException, InsufficientPermissionsException {
diff --git a/src/com/cyanogenmod/filemanager/util/FileHelper.java b/src/com/cyanogenmod/filemanager/util/FileHelper.java
index 14059d69..0cf98fee 100644
--- a/src/com/cyanogenmod/filemanager/util/FileHelper.java
+++ b/src/com/cyanogenmod/filemanager/util/FileHelper.java
@@ -26,7 +26,9 @@ import android.util.Log;
import com.cyanogenmod.filemanager.FileManagerApplication;
import com.cyanogenmod.filemanager.R;
import com.cyanogenmod.filemanager.commands.SyncResultExecutable;
+import com.cyanogenmod.filemanager.commands.java.Program;
import com.cyanogenmod.filemanager.commands.shell.ResolveLinkCommand;
+import com.cyanogenmod.filemanager.console.CancelledOperationException;
import com.cyanogenmod.filemanager.console.Console;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
@@ -1105,7 +1107,8 @@ public final class FileHelper {
* @throws ExecutionException If a problem was detected in the operation
*/
public static boolean copyRecursive(
- final File src, final File dst, int bufferSize) throws ExecutionException {
+ final File src, final File dst, int bufferSize, Program program)
+ throws ExecutionException, CancelledOperationException {
if (src.isDirectory()) {
// Create the directory
if (dst.exists() && !dst.isDirectory()) {
@@ -1122,14 +1125,20 @@ public final class FileHelper {
File[] files = src.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
- if (!copyRecursive(files[i], new File(dst, files[i].getName()), bufferSize)) {
+ // Short circuit if we've been cancelled. Show's over :(
+ if (program.isCancelled()) {
+ throw new CancelledOperationException();
+ }
+
+ if (!copyRecursive(files[i], new File(dst, files[i].getName()), bufferSize,
+ program)) {
return false;
}
}
}
} else {
// Copy the directory
- if (!bufferedCopy(src, dst,bufferSize)) {
+ if (!bufferedCopy(src, dst,bufferSize, program)) {
return false;
}
}
@@ -1145,7 +1154,8 @@ public final class FileHelper {
* @return boolean If the operation complete successfully
*/
public static boolean bufferedCopy(final File src, final File dst,
- int bufferSize) throws ExecutionException {
+ int bufferSize, Program program)
+ throws ExecutionException, CancelledOperationException {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
@@ -1154,6 +1164,10 @@ public final class FileHelper {
int read = 0;
byte[] data = new byte[bufferSize];
while ((read = bis.read(data, 0, bufferSize)) != -1) {
+ // Short circuit if we've been cancelled. Show's over :(
+ if (program.isCancelled()) {
+ throw new CancelledOperationException();
+ }
bos.write(data, 0, read);
}
return true;
@@ -1167,6 +1181,9 @@ public final class FileHelper {
if (e.getCause() instanceof ErrnoException
&& ((ErrnoException)e.getCause()).errno == OsConstants.ENOSPC) {
throw new ExecutionException(R.string.msgs_no_disk_space);
+ } if (e instanceof CancelledOperationException) {
+ // If the user cancelled this operation, let it through.
+ throw (CancelledOperationException)e;
}
return false;