From: jruesga Date: Sat, 29 Sep 2012 23:39:06 +0000 (+0200) Subject: Fix commands X-Git-Tag: android-x86-6.0-r1~814 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=47c142cb6b2ac01f16d3aef2a3fdf83b9e3e9861;p=android-x86%2Fpackages-apps-CMFileManager.git Fix commands * Fix cancelable commands * New pid_shell and pid_cmd command * New FolderUsage command * New compute folder statistics in fso properties * Add overlay file for device specific stuff * Fix invalid executable drawable * Clean up --- diff --git a/res/layout/filesystem_info_dialog.xml b/res/layout/filesystem_info_dialog.xml index 3103e60..9a15b1c 100644 --- a/res/layout/filesystem_info_dialog.xml +++ b/res/layout/filesystem_info_dialog.xml @@ -117,6 +117,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -141,6 +142,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -165,6 +167,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -214,6 +217,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> diff --git a/res/layout/fso_properties_dialog.xml b/res/layout/fso_properties_dialog.xml index 08e1586..45fe012 100644 --- a/res/layout/fso_properties_dialog.xml +++ b/res/layout/fso_properties_dialog.xml @@ -15,7 +15,7 @@ ** limitations under the License. --> @@ -93,6 +93,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -117,6 +118,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -141,6 +143,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -167,6 +170,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> @@ -191,6 +195,34 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" + android:textAppearance="@style/secondary_text_appearance" /> + + + + + + + + @@ -215,6 +247,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/default_margin" android:gravity="left|center_vertical" + android:singleLine="false" android:textAppearance="@style/secondary_text_appearance" /> diff --git a/res/values/overlay.xml b/res/values/overlay.xml new file mode 100644 index 0000000..36e1238 --- /dev/null +++ b/res/values/overlay.xml @@ -0,0 +1,33 @@ + + + + + + + + 512 + + + 5120 + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 98ba532..47948e4 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -55,6 +55,12 @@ Loading… + + Computing… %1$s + + Computing…\n%1$s + + Cancelled. Error. @@ -232,6 +238,8 @@ Link: Size: + + Contains: Last Access: @@ -248,6 +256,21 @@ W X + + + %1$s / %2$s + + + 0 folders + 1 folder + %1$d folders + + + + 0 files + 1 files + %1$d files + Choose console diff --git a/res/xml/command_list.xml b/res/xml/command_list.xml index d169369..489ea25 100644 --- a/res/xml/command_list.xml +++ b/res/xml/command_list.xml @@ -44,6 +44,7 @@ + @@ -51,10 +52,11 @@ - + + - + diff --git a/src/com/cyanogenmod/explorer/activities/NavigationActivity.java b/src/com/cyanogenmod/explorer/activities/NavigationActivity.java index 5631e5b..13dca60 100644 --- a/src/com/cyanogenmod/explorer/activities/NavigationActivity.java +++ b/src/com/cyanogenmod/explorer/activities/NavigationActivity.java @@ -985,9 +985,9 @@ public class NavigationActivity extends Activity //Do back operation over the navigation history boolean flag = this.mExitFlag; - + this.mExitFlag = !back(); - + // Retrieve if the exit status timeout has expired long now = System.currentTimeMillis(); boolean timeout = (this.mExitBackTimeout == -1 || diff --git a/src/com/cyanogenmod/explorer/activities/SearchActivity.java b/src/com/cyanogenmod/explorer/activities/SearchActivity.java index 8fe4dc2..2f94b72 100644 --- a/src/com/cyanogenmod/explorer/activities/SearchActivity.java +++ b/src/com/cyanogenmod/explorer/activities/SearchActivity.java @@ -541,7 +541,8 @@ public class SearchActivity extends Activity if (SearchActivity.this.mExecutable.cancel()) { if (SearchActivity.this.mAdapter != null) { SearchActivity.this.toggleResults( - SearchActivity.this.mAdapter.getCount() > 0); + SearchActivity.this. + mAdapter.getCount() > 0, true); } return true; } @@ -598,7 +599,7 @@ public class SearchActivity extends Activity //Toggle results List list = SearchActivity.this.mRestoreState.getSearchResultList(); String directory = SearchActivity.this.mRestoreState.getSearchDirectory(); - SearchActivity.this.toggleResults(list.size() > 0); + SearchActivity.this.toggleResults(list.size() > 0, true); setFoundItems(list.size(), directory); //Set terms @@ -672,17 +673,18 @@ public class SearchActivity extends Activity this.mAdapter.clear(); this.mAdapter.notifyDataSetChanged(); this.mSearchListView.setSelection(0); - toggleResults(false); + toggleResults(false, true); } /** * Method that toggle the views when there are results. * * @param hasResults Indicates if there are results + * @param showEmpty Show the empty list message */ - private void toggleResults(boolean hasResults) { + private void toggleResults(boolean hasResults, boolean showEmpty) { this.mSearchListView.setVisibility(hasResults ? View.VISIBLE : View.INVISIBLE); - this.mEmptyListMsg.setVisibility(!hasResults ? View.VISIBLE : View.INVISIBLE); + this.mEmptyListMsg.setVisibility(!hasResults && showEmpty ? View.VISIBLE : View.INVISIBLE); } /** @@ -866,7 +868,7 @@ public class SearchActivity extends Activity @Override @SuppressWarnings("synthetic-access") public void run() { - SearchActivity.this.toggleResults(false); + SearchActivity.this.toggleResults(false, false); } }); } @@ -901,31 +903,13 @@ public class SearchActivity extends Activity } /** - * Method that draw the results in the listview - */ - private void drawResults() { - //Toggle results - this.toggleResults(this.mResultList.size() > 0); - setFoundItems(this.mResultList.size(), this.mSearchDirectory); - - //Create the task for drawing the data - this.mDrawingSearchResultTask = - new SearchResultDrawingAsyncTask( - this.mSearchListView, - this.mSearchWaiting, - this, - this.mResultList, - this.mQuery); - this.mDrawingSearchResultTask.execute(); - } - - /** * {@inheritDoc} */ @Override - public void onPartialResult(final List partialResults) { + @SuppressWarnings("unchecked") + public void onPartialResult(final Object partialResults) { //Saved in the global result list, for save at the end - SearchActivity.this.mResultList.addAll(partialResults); + SearchActivity.this.mResultList.addAll((List)partialResults); //Notify progress this.mSearchListView.post(new Runnable() { @@ -950,6 +934,25 @@ public class SearchActivity extends Activity } /** + * Method that draw the results in the listview + */ + private void drawResults() { + //Toggle results + this.toggleResults(this.mResultList.size() > 0, true); + setFoundItems(this.mResultList.size(), this.mSearchDirectory); + + //Create the task for drawing the data + this.mDrawingSearchResultTask = + new SearchResultDrawingAsyncTask( + this.mSearchListView, + this.mSearchWaiting, + this, + this.mResultList, + this.mQuery); + this.mDrawingSearchResultTask.execute(); + } + + /** * Method that creates a {@link SearchInfoParcelable} reference from * the current data. * diff --git a/src/com/cyanogenmod/explorer/commands/AsyncResultListener.java b/src/com/cyanogenmod/explorer/commands/AsyncResultListener.java index e0f2a14..defa930 100644 --- a/src/com/cyanogenmod/explorer/commands/AsyncResultListener.java +++ b/src/com/cyanogenmod/explorer/commands/AsyncResultListener.java @@ -16,9 +16,6 @@ package com.cyanogenmod.explorer.commands; -import com.cyanogenmod.explorer.model.FileSystemObject; - -import java.util.List; /** * An interface for communicate partial results. @@ -39,9 +36,9 @@ public interface AsyncResultListener { /** * Method invoked when new partial data are ready. * - * @param results New data results + * @param result New data result */ - void onPartialResult(List results); + void onPartialResult(Object result); /** * Method invoked when an exception occurs while executing the program. diff --git a/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java b/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java index 3381003..e024b9e 100644 --- a/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java +++ b/src/com/cyanogenmod/explorer/commands/ExecutableCreator.java @@ -80,10 +80,12 @@ public interface ExecutableCreator { * Method that creates an executable for create a new directory. * * @param dir The absolute path of the new directory - * @return CreateDirExecutable A {@link CreateDirExecutable} executable implementation reference + * @return CreateDirExecutable A {@link CreateDirExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ - CreateDirExecutable createCreateDirectoryExecutable(String dir) throws CommandNotFoundException; + CreateDirExecutable createCreateDirectoryExecutable(String dir) + throws CommandNotFoundException; /** * Method that creates an executable for create a new file. @@ -108,7 +110,8 @@ public interface ExecutableCreator { * Method that creates an executable for delete a directory. * * @param dir The absolute path to the directory to be deleted - * @return DeleteDirExecutable A {@link DeleteDirExecutable} executable implementation reference + * @return DeleteDirExecutable A {@link DeleteDirExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ DeleteDirExecutable createDeleteDirExecutable(String dir) throws CommandNotFoundException; @@ -127,7 +130,8 @@ public interface ExecutableCreator { * Method that creates an executable for retrieve the disk usage. * for all filesystems * - * @return DiskUsageExecutable A {@link DiskUsageExecutable} executable implementation reference + * @return DiskUsageExecutable A {@link DiskUsageExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ DiskUsageExecutable createDiskUsageExecutable() throws CommandNotFoundException; @@ -137,7 +141,8 @@ public interface ExecutableCreator { * of the filesystem of a directory * * @param dir The absolute path to the directory - * @return DiskUsageExecutable A {@link DiskUsageExecutable} executable implementation reference + * @return DiskUsageExecutable A {@link DiskUsageExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ DiskUsageExecutable createDiskUsageExecutable(String dir) throws CommandNotFoundException; @@ -153,7 +158,7 @@ public interface ExecutableCreator { EchoExecutable createEchoExecutable(String msg) throws CommandNotFoundException; /** - * Method that creates an executable for make search over the filesystem. + * Method that creates an executable for make searches over the filesystem. * * @param directory The directory where to search * @param query The term of the query @@ -166,6 +171,19 @@ public interface ExecutableCreator { throws CommandNotFoundException; /** + * Method that creates an executable for compute the disk usage of a folder. + * + * @param directory The directory where to search + * @param asyncResultListener The listener where to return partial results + * @return FolderUsageExecutable A {@link FolderUsageExecutable} executable + * implementation reference + * @throws CommandNotFoundException If the executable can't be created + */ + FolderUsageExecutable createFolderUsageExecutable( + String directory, AsyncResultListener asyncResultListener) + throws CommandNotFoundException; + + /** * Method that creates an executable for retrieve the groups of the current user. * * @return GroupsExecutable A {@link GroupsExecutable} executable implementation reference @@ -191,7 +209,8 @@ public interface ExecutableCreator { * @throws CommandNotFoundException If the executable can't be created * @see LIST_MODE */ - ListExecutable createListExecutable(String src, LIST_MODE mode) throws CommandNotFoundException; + ListExecutable createListExecutable(String src, LIST_MODE mode) + throws CommandNotFoundException; /** * Method that creates an executable for retrieve identity information of the current user. @@ -229,28 +248,42 @@ public interface ExecutableCreator { * of a file system object. * * @param fso The absolute path to the file system object - * @return ParentDirExecutable A {@link ParentDirExecutable} executable implementation reference + * @return ParentDirExecutable A {@link ParentDirExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ ParentDirExecutable createParentDirExecutable(String fso) throws CommandNotFoundException; /** * Method that creates an executable for retrieve operating system process identifier of a + * shell. + * + * @return ProcessIdExecutable A {@link ProcessIdExecutable} executable implementation + * reference + * @throws CommandNotFoundException If the executable can't be created + */ + ProcessIdExecutable createShellProcessIdExecutable() throws CommandNotFoundException; + + /** + * Method that creates an executable for retrieve operating system process identifier of a * process. * + * @param pid The shell process id where the process is running * @param processName The process name - * @return ProcessIdExecutable A {@link ProcessIdExecutable} executable implementation reference + * @return ProcessIdExecutable A {@link ProcessIdExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ ProcessIdExecutable createProcessIdExecutable( - String processName) throws CommandNotFoundException; + int pid, String processName) throws CommandNotFoundException; /** * Method that creates an executable for quickly retrieve the name of directories * that matches a string. * * @param regexp The regular expression - * @return ProcessIdExecutable A {@link ProcessIdExecutable} executable implementation reference + * @return ProcessIdExecutable A {@link ProcessIdExecutable} executable implementation + * reference * @throws CommandNotFoundException If the executable can't be created */ QuickFolderSearchExecutable createQuickFolderSearchExecutable( diff --git a/src/com/cyanogenmod/explorer/commands/FindExecutable.java b/src/com/cyanogenmod/explorer/commands/FindExecutable.java index b4a8dc9..ad08716 100644 --- a/src/com/cyanogenmod/explorer/commands/FindExecutable.java +++ b/src/com/cyanogenmod/explorer/commands/FindExecutable.java @@ -17,7 +17,7 @@ package com.cyanogenmod.explorer.commands; /** - * An interface that represents an executable for make search over + * An interface that represents an executable for make a search over * the filesystem. */ public interface FindExecutable extends AsyncResultExecutable { diff --git a/src/com/cyanogenmod/explorer/commands/FolderUsageExecutable.java b/src/com/cyanogenmod/explorer/commands/FolderUsageExecutable.java new file mode 100644 index 0000000..cc1b6a4 --- /dev/null +++ b/src/com/cyanogenmod/explorer/commands/FolderUsageExecutable.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.explorer.commands; + +/** + * An interface that represents an executable for retrieve a folder usage + */ +public interface FolderUsageExecutable extends AsyncResultExecutable { + /**NON BLOCK**/ +} diff --git a/src/com/cyanogenmod/explorer/commands/shell/FindCommand.java b/src/com/cyanogenmod/explorer/commands/shell/FindCommand.java index e519171..5168c16 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/FindCommand.java +++ b/src/com/cyanogenmod/explorer/commands/shell/FindCommand.java @@ -38,7 +38,7 @@ import java.util.List; /** * A class for search files. * - * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?ls"} + * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?find"} */ public class FindCommand extends AsyncResultProgram implements FindExecutable { @@ -60,8 +60,7 @@ public class FindCommand extends AsyncResultProgram implements FindExecutable { private String mPartial; /** - * Constructor of FindCommand. This constructor uses a - * DIRECTORY mode as listing mode. + * Constructor of FindCommand. * * @param directory The "absolute" directory where start the search * @param query The terms to be searched @@ -202,8 +201,10 @@ public class FindCommand extends AsyncResultProgram implements FindExecutable { //Search in a subdirectory without permissions returns 1, but this //not must be treated as an error //Ignore exit code 143 (canceled) - if (exitCode != 0 && exitCode != 1 && exitCode != 143) { - throw new ExecutionException("exitcode != 0 && != 1 && != 143"); //$NON-NLS-1$ + //Ignore exit code 137 (kill -9) + if (exitCode != 0 && exitCode != 1 && exitCode != 143 && exitCode != 137) { + throw new ExecutionException( + "exitcode != 0 && != 1 && != 143 && != 137"); //$NON-NLS-1$ } } diff --git a/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommand.java b/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommand.java new file mode 100644 index 0000000..b662c57 --- /dev/null +++ b/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommand.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.explorer.commands.shell; + +import android.util.Log; + +import com.cyanogenmod.explorer.commands.AsyncResultListener; +import com.cyanogenmod.explorer.commands.FolderUsageExecutable; +import com.cyanogenmod.explorer.console.CommandNotFoundException; +import com.cyanogenmod.explorer.console.ExecutionException; +import com.cyanogenmod.explorer.console.InsufficientPermissionsException; +import com.cyanogenmod.explorer.model.Directory; +import com.cyanogenmod.explorer.model.FileSystemObject; +import com.cyanogenmod.explorer.model.FolderUsage; +import com.cyanogenmod.explorer.model.Symlink; +import com.cyanogenmod.explorer.util.FileHelper; +import com.cyanogenmod.explorer.util.MimeTypeHelper; +import com.cyanogenmod.explorer.util.MimeTypeHelper.MimeTypeCategory; +import com.cyanogenmod.explorer.util.ParseHelper; + +import java.io.BufferedReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +/** + * A class for retrieve the disk usage of a folder + * + * {@link "http://unixhelp.ed.ac.uk/CGI/man-cgi?ls"} + */ +public class FolderUsageCommand extends AsyncResultProgram implements FolderUsageExecutable { + + private static final String TAG = "FolderUsageCommand"; //$NON-NLS-1$ + + private static final String ID_FOLDER_USAGE_DIRECTORY = "folderusage"; //$NON-NLS-1$ + + private final String mDirectory; + private FolderUsage mFolderUsage; + private String mPartial; + + /** + * Constructor of FolderUsageCommand. + * + * @param directory The "absolute" directory to compute + * @param asyncResultListener The partial result listener + * @throws InvalidCommandDefinitionException If the command has an invalid definition + */ + public FolderUsageCommand( + String directory, AsyncResultListener asyncResultListener) + throws InvalidCommandDefinitionException { + super(ID_FOLDER_USAGE_DIRECTORY, asyncResultListener, new String[]{directory}); + this.mFolderUsage = new FolderUsage(directory); + this.mPartial = ""; //$NON-NLS-1$ + this.mDirectory = directory; + } + + /** + * {@inheritDoc} + */ + @Override + public void onStartParsePartialResult() { + this.mFolderUsage = new FolderUsage(this.mDirectory); + this.mPartial = ""; //$NON-NLS-1$ + } + + /** + * {@inheritDoc} + */ + @Override + public void onEndParsePartialResult(boolean cancelled) { + this.mPartial = ""; //$NON-NLS-1$ + } + + /** + * {@inheritDoc} + */ + @Override + public void onParsePartialResult(final String partialIn) { + + // Check the in buffer to extract information + BufferedReader br = null; + try { + //Read the partial + previous partial and clean partial + br = new BufferedReader(new StringReader(this.mPartial + partialIn)); + this.mPartial = ""; //$NON-NLS-1$ + + //Add all lines to an array + List lines = new ArrayList(); + String line = null; + while ((line = br.readLine()) != null) { + if (line.trim().length() == 0) { + continue; + } + lines.add(line); + } + + //2 lines per file system object translation + boolean newData = false; + int c = 0; + while (lines.size() > 0) { + try { + // Retrieve the info + String szLine = lines.get(0).trim(); + + // Parent folder is not necessary here. Only the information relative to + // type and size + FileSystemObject fso = + ParseHelper.toFileSystemObject( + FileHelper.ROOT_DIRECTORY, szLine, true); + + // Only regular files or directories. No compute Symlinks + if (fso instanceof Symlink) { + + // Directory + } else if (fso instanceof Directory) { + // Folder + this.mFolderUsage.addFolder(); + newData = true; + + // Regular File, Block device, ... + } else { + this.mFolderUsage.addFile(); + // Compute statistics and size + MimeTypeCategory category = + MimeTypeHelper.getCategory(null, fso); + this.mFolderUsage.addFileToCategory(category); + this.mFolderUsage.addSize(fso.getSize()); + newData = true; + } + + // Partial notification + if (c % 5 == 0) { + //If a listener is defined, then send the partial result + if (getAsyncResultListener() != null && newData) { + getAsyncResultListener().onPartialResult(this.mFolderUsage); + } + } + + } catch (Exception ex) { /**NON BLOCK **/ } + + //Remove the the line + lines.remove(0); + } + + //Saves the lines for the next partial read (At this point only one line + //can exists in the buffer. The rest was processed or discarded) + if (lines.size() > 0) { + this.mPartial = lines.get(0).concat(FileHelper.NEWLINE); + } + + //If a listener is defined, then send the partial result + if (getAsyncResultListener() != null && newData) { + getAsyncResultListener().onPartialResult(this.mFolderUsage); + } + + } catch (Exception ex) { + Log.w(TAG, "Partial result fails", ex); //$NON-NLS-1$ + + } finally { + try { + if (br != null) { + br.close(); + } + } catch (Throwable ex) { + /**NON BLOCK**/ + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isIgnoreShellStdErrCheck() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void checkExitCode(int exitCode) + throws InsufficientPermissionsException, CommandNotFoundException, ExecutionException { + + //Access a subdirectory without permissions returns 1, but this + //not must be treated as an error + //Ignore exit code 143 (canceled) + //Ignore exit code 137 (kill -9) + if (exitCode != 0 && exitCode != 1 && exitCode != 143 && exitCode != 137) { + throw new ExecutionException( + "exitcode != 0 && != 1 && != 143 && != 137"); //$NON-NLS-1$ + } + } +} diff --git a/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommand.java b/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommand.java index 228bd96..fc20203 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommand.java +++ b/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommand.java @@ -34,17 +34,30 @@ import java.text.ParseException; */ public class ProcessIdCommand extends SyncResultProgram implements ProcessIdExecutable { - private static final String ID = "pid"; //$NON-NLS-1$ + private static final String ID_SHELL = "pid_shell"; //$NON-NLS-1$ + private static final String ID_CMD = "pid_cmd"; //$NON-NLS-1$ private Integer mPID; /** - * Constructor of ProcessIdCommand. + * Constructor of ProcessIdCommand.
+ * Use this to retrieve the PID of a shell. * + * @throws InvalidCommandDefinitionException If the command has an invalid definition + */ + public ProcessIdCommand() throws InvalidCommandDefinitionException { + super(ID_SHELL); + } + + /** + * Constructor of ProcessIdCommand.
+ * Use this to retrieve the PID of a command running on a shell. + * + * @param pid The process identifier of the shell when the process is running * @param processName The process name * @throws InvalidCommandDefinitionException If the command has an invalid definition */ - public ProcessIdCommand(String processName) throws InvalidCommandDefinitionException { - super(ID, processName); + public ProcessIdCommand(int pid, String processName) throws InvalidCommandDefinitionException { + super(ID_CMD, new String[]{processName, String.valueOf(pid)}); } /** diff --git a/src/com/cyanogenmod/explorer/commands/shell/Shell.java b/src/com/cyanogenmod/explorer/commands/shell/Shell.java index 9b05326..bb31123 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/Shell.java +++ b/src/com/cyanogenmod/explorer/commands/shell/Shell.java @@ -31,6 +31,8 @@ import com.cyanogenmod.explorer.console.ReadOnlyFilesystemException; */ public abstract class Shell extends Command { + private int mPid; + /** * @Constructor of Shell * @@ -41,6 +43,25 @@ public abstract class Shell extends Command { */ public Shell(String id, String... args) throws InvalidCommandDefinitionException { super(id, args); + this.mPid = -1; + } + + /** + * Method that returns the process identifier of the console + * + * @return int The process identifier + */ + public final int getPid() { + return this.mPid; + } + + /** + * Method that sets the process identifier of the console + * + * @param pid The process identifier + */ + public final void setPid(int pid) { + this.mPid = pid; } /** diff --git a/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java b/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java index a4e3dca..b13afb1 100644 --- a/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java +++ b/src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java @@ -30,6 +30,7 @@ import com.cyanogenmod.explorer.commands.DiskUsageExecutable; import com.cyanogenmod.explorer.commands.EchoExecutable; import com.cyanogenmod.explorer.commands.ExecutableCreator; import com.cyanogenmod.explorer.commands.FindExecutable; +import com.cyanogenmod.explorer.commands.FolderUsageExecutable; import com.cyanogenmod.explorer.commands.GroupsExecutable; import com.cyanogenmod.explorer.commands.IdentityExecutable; import com.cyanogenmod.explorer.commands.ListExecutable; @@ -237,6 +238,20 @@ public class ShellExecutableCreator implements ExecutableCreator { * {@inheritDoc} */ @Override + public FolderUsageExecutable createFolderUsageExecutable( + String directory, AsyncResultListener asyncResultListener) + throws CommandNotFoundException { + try { + return new FolderUsageCommand(directory, asyncResultListener); + } catch (InvalidCommandDefinitionException icdEx) { + throw new CommandNotFoundException("FolderUsageCommand", icdEx); //$NON-NLS-1$ + } + } + + /** + * {@inheritDoc} + */ + @Override public GroupsExecutable createGroupsExecutable() throws CommandNotFoundException { try { return new GroupsCommand(); @@ -326,10 +341,22 @@ public class ShellExecutableCreator implements ExecutableCreator { * {@inheritDoc} */ @Override - public ProcessIdExecutable createProcessIdExecutable(String processName) + public ProcessIdExecutable createShellProcessIdExecutable() throws CommandNotFoundException { + try { + return new ProcessIdCommand(); + } catch (InvalidCommandDefinitionException icdEx) { + throw new CommandNotFoundException("ProcessIdCommand", icdEx); //$NON-NLS-1$ + } + } + + /** + * {@inheritDoc} + */ + @Override + public ProcessIdExecutable createProcessIdExecutable(int pid, String processName) throws CommandNotFoundException { try { - return new ProcessIdCommand(processName); + return new ProcessIdCommand(pid, processName); } catch (InvalidCommandDefinitionException icdEx) { throw new CommandNotFoundException("ProcessIdCommand", icdEx); //$NON-NLS-1$ } diff --git a/src/com/cyanogenmod/explorer/console/shell/ShellConsole.java b/src/com/cyanogenmod/explorer/console/shell/ShellConsole.java index c6ae3d5..d5f6884 100644 --- a/src/com/cyanogenmod/explorer/console/shell/ShellConsole.java +++ b/src/com/cyanogenmod/explorer/console/shell/ShellConsole.java @@ -24,6 +24,7 @@ import com.cyanogenmod.explorer.commands.Executable; import com.cyanogenmod.explorer.commands.ExecutableFactory; import com.cyanogenmod.explorer.commands.GroupsExecutable; import com.cyanogenmod.explorer.commands.IdentityExecutable; +import com.cyanogenmod.explorer.commands.ProcessIdExecutable; import com.cyanogenmod.explorer.commands.shell.AsyncResultProgram; import com.cyanogenmod.explorer.commands.shell.Command; import com.cyanogenmod.explorer.commands.shell.InvalidCommandDefinitionException; @@ -220,6 +221,18 @@ public abstract class ShellConsole extends Console { } } + // Retrieve the PID of the shell + ProcessIdExecutable processIdCmd = + getExecutableFactory(). + newCreator().createShellProcessIdExecutable(); + execute(processIdCmd); + Integer pid = processIdCmd.getResult(); + if (pid == null) { + throw new ConsoleAllocException( + "Can't retrieve the PID of the shell."); //$NON-NLS-1$ + } + this.mShell.setPid(pid.intValue()); + //Retrieve identity IdentityExecutable identityCmd = getExecutableFactory().newCreator().createIdentityExecutable(); @@ -452,6 +465,14 @@ public abstract class ShellConsole extends Console { //Retrieve exit code int exitCode = getExitCode(this.mSbIn); + if (isTrace()) { + Log.v(TAG, + String.format("%s-%s, command: %s, exitCode: %s", //$NON-NLS-1$ + ShellConsole.this.mShell.getId(), + program.getId(), + cmd, + String.valueOf(exitCode))); + } //Check if invocation was successfully or not if (!program.isIgnoreShellStdErrCheck()) { @@ -805,6 +826,7 @@ public abstract class ShellConsole extends Console { Integer pid = CommandHelper.getProcessId( null, + this.mShell.getPid(), program.getCommand(), ExplorerApplication.getBackgroundConsole()); if (pid != null) { diff --git a/src/com/cyanogenmod/explorer/model/FolderUsage.java b/src/com/cyanogenmod/explorer/model/FolderUsage.java new file mode 100644 index 0000000..0d6339e --- /dev/null +++ b/src/com/cyanogenmod/explorer/model/FolderUsage.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.explorer.model; + +import android.util.SparseArray; + +import com.cyanogenmod.explorer.util.MimeTypeHelper.MimeTypeCategory; + +import java.io.Serializable; + +/** + * A class that holds information about the usage of a folder (space and number of files/folders). + */ +public class FolderUsage implements Serializable, Cloneable { + + private static final long serialVersionUID = -8830510087518648692L; + + private final String mFolder; + private int mNumberOfFolders; + private int mNumberOfFiles; + private long mTotalSize; + private SparseArray mStatistics; + + /** + * Constructor of FolderUsage. + * + * @param folder The folder of which retrieve the usage + */ + public FolderUsage(String folder) { + super(); + + // Initialize the class + this.mFolder = folder; + this.mNumberOfFolders = 0; + this.mNumberOfFiles = 0; + this.mTotalSize = 0; + + // Fill the array of statistics + MimeTypeCategory[] categories = MimeTypeCategory.values(); + this.mStatistics = new SparseArray(categories.length-1); + for (int i=0; i>> 32)); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + FolderUsage other = (FolderUsage) obj; + if (this.mFolder == null) { + if (other.mFolder != null) + return false; + } else if (!this.mFolder.equals(other.mFolder)) + return false; + if (this.mNumberOfFiles != other.mNumberOfFiles) + return false; + if (this.mNumberOfFolders != other.mNumberOfFolders) + return false; + if (this.mStatistics == null) { + if (other.mStatistics != null) + return false; + } else if (!this.mStatistics.equals(other.mStatistics)) + return false; + if (this.mTotalSize != other.mTotalSize) + return false; + return true; + } + + /* (non-Javadoc) + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + FolderUsage other = new FolderUsage(this.mFolder); + other.mNumberOfFolders = this.mNumberOfFolders; + other.mNumberOfFiles = this.mNumberOfFiles; + other.mTotalSize = this.mTotalSize; + other.mStatistics = this.mStatistics.clone(); + return super.clone(); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "FolderUsage [folder=" + this.mFolder + //$NON-NLS-1$ + ", numberOfFolders=" + this.mNumberOfFolders + //$NON-NLS-1$ + ", numberOfFiles=" + this.mNumberOfFiles + //$NON-NLS-1$ + ", totalSize=" + this.mTotalSize + //$NON-NLS-1$ + ", statistics=" + this.mStatistics + "]"; //$NON-NLS-1$//$NON-NLS-2$ + } +} diff --git a/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java b/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java index 27db6bc..8824908 100644 --- a/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java +++ b/src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java @@ -16,11 +16,13 @@ package com.cyanogenmod.explorer.ui.dialogs; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.os.AsyncTask; +import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; @@ -35,9 +37,12 @@ import android.widget.Spinner; import android.widget.TextView; import com.cyanogenmod.explorer.R; +import com.cyanogenmod.explorer.commands.AsyncResultExecutable; +import com.cyanogenmod.explorer.commands.AsyncResultListener; import com.cyanogenmod.explorer.console.ConsoleBuilder; import com.cyanogenmod.explorer.model.AID; import com.cyanogenmod.explorer.model.FileSystemObject; +import com.cyanogenmod.explorer.model.FolderUsage; import com.cyanogenmod.explorer.model.Group; import com.cyanogenmod.explorer.model.GroupPermission; import com.cyanogenmod.explorer.model.OthersPermission; @@ -61,7 +66,9 @@ import java.text.DateFormat; */ public class FsoPropertiesDialog implements OnClickListener, OnCheckedChangeListener, OnItemSelectedListener, - DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { + DialogInterface.OnCancelListener, DialogInterface.OnDismissListener, AsyncResultListener { + + private static final String TAG = "FsoPropertiesDialog"; //$NON-NLS-1$ private static final String OWNER_TYPE = "owner"; //$NON-NLS-1$ private static final String GROUP_TYPE = "group"; //$NON-NLS-1$ @@ -86,10 +93,16 @@ public class FsoPropertiesDialog private CheckBox[] mChkGroupPermission; private CheckBox[] mChkOthersPermission; private TextView mInfoMsgView; + private TextView mTvSize; + private TextView mTvContains; private boolean mIgnoreCheckEvents; private boolean mHasPrivileged; + private AsyncResultExecutable mFolderUsageExecutable; + private FolderUsage mFolderUsage; + private boolean mDrawingFolderUsage; + private DialogInterface.OnDismissListener mOnDismissListener; /** @@ -185,7 +198,9 @@ public class FsoPropertiesDialog TextView tvType = (TextView)contentView.findViewById(R.id.fso_properties_type); View vLinkRow = contentView.findViewById(R.id.fso_properties_link_row); TextView tvLink = (TextView)contentView.findViewById(R.id.fso_properties_link); - TextView tvSize = (TextView)contentView.findViewById(R.id.fso_properties_size); + this.mTvSize = (TextView)contentView.findViewById(R.id.fso_properties_size); + View vContatinsRow = contentView.findViewById(R.id.fso_properties_contains_row); + this.mTvContains = (TextView)contentView.findViewById(R.id.fso_properties_contains); TextView tvDate = (TextView)contentView.findViewById(R.id.fso_properties_date); this.mSpnOwner = (Spinner)contentView.findViewById(R.id.fso_properties_owner); this.mSpnGroup = (Spinner)contentView.findViewById(R.id.fso_properties_group); @@ -203,10 +218,10 @@ public class FsoPropertiesDialog vLinkRow.setVisibility(this.mFso instanceof Symlink ? View.VISIBLE : View.GONE); String size = FileHelper.getHumanReadableSize(this.mFso); if (size.length() == 0) { - //TODO Compute Size size = "-"; //$NON-NLS-1$ } - tvSize.setText(size); + this.mTvSize.setText(size); + this.mTvContains.setText("-"); //$NON-NLS-1$ DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); tvDate.setText(df.format(this.mFso.getLastModifiedTime())); @@ -219,6 +234,38 @@ public class FsoPropertiesDialog updatePermissions(); // Load owners and groups AIDs in background + loadAIDs(); + + // Load owners and groups AIDs in background + if (FileHelper.isDirectory(this.mFso)) { + vContatinsRow.setVisibility(View.VISIBLE); + computeFolderUsage(); + } + + // Check if permissions operations are allowed + try { + this.mHasPrivileged = ConsoleBuilder.getConsole(this.mContext).isPrivileged(); + } catch (Throwable ex) {/**NON BLOCK**/} + this.mSpnOwner.setEnabled(this.mHasPrivileged); + this.mSpnGroup.setEnabled(this.mHasPrivileged); + setCheckBoxesPermissionsEnable(this.mChkUserPermission, this.mHasPrivileged); + setCheckBoxesPermissionsEnable(this.mChkGroupPermission, this.mHasPrivileged); + setCheckBoxesPermissionsEnable(this.mChkOthersPermission, this.mHasPrivileged); + if (!this.mHasPrivileged) { + this.mInfoMsgView.setVisibility(View.VISIBLE); + this.mInfoMsgView.setOnClickListener(this); + } + + //Change the tab + onClick(this.mInfoViewTab); + this.mIgnoreCheckEvents = false; + } + + /** + * Method that loads the AIDs in background + */ + private void loadAIDs() { + // Load owners and groups AIDs in background AsyncTask> aidsTask = new AsyncTask>() { @Override @@ -272,24 +319,21 @@ public class FsoPropertiesDialog } }; aidsTask.execute(); + } - // Check if permissions operations are allowed + /** + * Method that computes the disk usage of the folder in background + */ + private void computeFolderUsage() { try { - this.mHasPrivileged = ConsoleBuilder.getConsole(this.mContext).isPrivileged(); - } catch (Throwable ex) {/**NON BLOCK**/} - this.mSpnOwner.setEnabled(this.mHasPrivileged); - this.mSpnGroup.setEnabled(this.mHasPrivileged); - setCheckBoxesPermissionsEnable(this.mChkUserPermission, this.mHasPrivileged); - setCheckBoxesPermissionsEnable(this.mChkGroupPermission, this.mHasPrivileged); - setCheckBoxesPermissionsEnable(this.mChkOthersPermission, this.mHasPrivileged); - if (!this.mHasPrivileged) { - this.mInfoMsgView.setVisibility(View.VISIBLE); - this.mInfoMsgView.setOnClickListener(this); + this.mFolderUsageExecutable = + CommandHelper.getFolderUsage(this.mContext, this.mFso.getFullPath(), this, null); + } catch (Exception cause) { + //Capture the exception + ExceptionUtil.translateException(this.mContext, cause, true, false); + this.mTvSize.setText(R.string.error_message); + this.mTvContains.setText(R.string.error_message); } - - //Change the tab - onClick(this.mInfoViewTab); - this.mIgnoreCheckEvents = false; } /** @@ -297,6 +341,7 @@ public class FsoPropertiesDialog */ @Override public void onDismiss(DialogInterface dialog) { + cancelFolderUsageCommand(); if (this.mOnDismissListener != null) { this.mOnDismissListener.onDismiss(dialog); } @@ -307,6 +352,7 @@ public class FsoPropertiesDialog */ @Override public void onCancel(DialogInterface dialog) { + cancelFolderUsageCommand(); if (this.mOnDismissListener != null) { this.mOnDismissListener.onDismiss(dialog); } @@ -376,6 +422,9 @@ public class FsoPropertiesDialog if (this.mIgnoreCheckEvents) return; try { + // Cancel the folder usage command + cancelFolderUsageCommand(); + // Retrieve the permissions and send to operating system Permissions permissions = getPermissions(); if (!CommandHelper.changePermissions( @@ -502,6 +551,9 @@ public class FsoPropertiesDialog return; } + // Cancel the folder usage command + cancelFolderUsageCommand(); + // Change the owner and group of the fso try { if (!CommandHelper.changeOwner( @@ -788,4 +840,121 @@ public class FsoPropertiesDialog this.mHasPrivileged && msg == null ? View.GONE : View.VISIBLE); } + /** + * {@inheritDoc} + */ + @Override + public void onAsyncStart() { + this.mDrawingFolderUsage = false; + this.mFolderUsage = new FolderUsage(this.mFso.getFullPath()); + printFolderUsage(true, false); + } + + /** + * {@inheritDoc} + */ + @Override + public void onAsyncEnd(final boolean cancelled) { + printFolderUsage(false, cancelled); + } + + /** + * {@inheritDoc} + */ + @Override + public void onPartialResult(final Object partialResults) { + try { + // Do not saturate ui thread + if (this.mDrawingFolderUsage) { + return; + } + + // Clone the reference + FsoPropertiesDialog.this.mFolderUsage = + (FolderUsage)(((FolderUsage)partialResults).clone()); + printFolderUsage(true, false); + }catch (Exception ex) {/** NON BLOCK**/} + } + + /** + * {@inheritDoc} + */ + @Override + public void onException(Exception cause) { + //Capture the exception + ExceptionUtil.translateException(this.mContext, cause); + } + + /** + * Method that cancels the folder usage command execution + */ + private void cancelFolderUsageCommand() { + // Cancel the folder usage command + try { + if (this.mFolderUsageExecutable != null && + this.mFolderUsageExecutable.isCancelable() && + !this.mFolderUsageExecutable.isCanceled()) { + this.mFolderUsageExecutable.cancel(); + } + } catch (Exception ex) { + Log.e(TAG, "Failed to cancel the folder usage command", ex); //$NON-NLS-1$ + } + } + + /** + * Method that redraws the information about folder usage + * + * @param computing If the process if computing the data + * @param cancelled If the process was cancelled + */ + private void printFolderUsage(final boolean computing, final boolean cancelled) { + // Mark that a drawing is in progress + this.mDrawingFolderUsage = true; + + final Resources res = this.mContext.getResources(); + if (cancelled) { + FsoPropertiesDialog.this.mTvSize.setText(R.string.cancelled_message); + FsoPropertiesDialog.this.mTvContains.setText(R.string.cancelled_message); + + // End of drawing + this.mDrawingFolderUsage = false; + } else { + // Calculate size prior to use ui thread + final String size = FileHelper.getHumanReadableSize(this.mFolderUsage.getTotalSize()); + + // Compute folders and files string + String folders = res.getQuantityString( + R.plurals.fso_properties_dialog_folders, + this.mFolderUsage.getNumberOfFolders(), + Integer.valueOf(this.mFolderUsage.getNumberOfFolders())); + String files = res.getQuantityString( + R.plurals.fso_properties_dialog_files, + this.mFolderUsage.getNumberOfFiles(), + Integer.valueOf(this.mFolderUsage.getNumberOfFiles())); + final String contains = res.getString( + R.string.fso_properties_dialog_folder_items, + folders, files); + + // Update the dialog + ((Activity)this.mContext).runOnUiThread(new Runnable() { + @Override + @SuppressWarnings("synthetic-access") + public void run() { + if (computing) { + FsoPropertiesDialog.this.mTvSize.setText( + res.getString(R.string.computing_message, size)); + FsoPropertiesDialog.this.mTvContains.setText( + res.getString(R.string.computing_message_ln, contains)); + } else { + FsoPropertiesDialog.this.mTvSize.setText(size); + FsoPropertiesDialog.this.mTvContains.setText(contains); + } + + // End of drawing + FsoPropertiesDialog.this.mDrawingFolderUsage = false; + } + }); + } + } + } diff --git a/src/com/cyanogenmod/explorer/util/CommandHelper.java b/src/com/cyanogenmod/explorer/util/CommandHelper.java index 07e11bc..74d2f6b 100644 --- a/src/com/cyanogenmod/explorer/util/CommandHelper.java +++ b/src/com/cyanogenmod/explorer/util/CommandHelper.java @@ -33,6 +33,7 @@ import com.cyanogenmod.explorer.commands.DiskUsageExecutable; import com.cyanogenmod.explorer.commands.EchoExecutable; import com.cyanogenmod.explorer.commands.Executable; import com.cyanogenmod.explorer.commands.FindExecutable; +import com.cyanogenmod.explorer.commands.FolderUsageExecutable; import com.cyanogenmod.explorer.commands.GroupsExecutable; import com.cyanogenmod.explorer.commands.IdentityExecutable; import com.cyanogenmod.explorer.commands.ListExecutable; @@ -102,8 +103,9 @@ public final class CommandHelper { * @see ChangeCurrentDirExecutable */ public static boolean changeCurrentDir(Context context, String dst, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ChangeCurrentDirExecutable executable = @@ -136,12 +138,14 @@ public final class CommandHelper { */ public static boolean changeOwner( Context context, String src, User user, Group group, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); ChangeOwnerExecutable executable = - c.getExecutableFactory().newCreator().createChangeOwnerExecutable(src, user, group); + c.getExecutableFactory(). + newCreator().createChangeOwnerExecutable(src, user, group); writableExecute(context, executable, c); return executable.getResult().booleanValue(); } @@ -169,8 +173,9 @@ public final class CommandHelper { */ public static boolean changePermissions( Context context, String src, Permissions permissions, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); ChangePermissionsExecutable executable = @@ -201,8 +206,9 @@ public final class CommandHelper { * @see CreateDirExecutable */ public static boolean createDirectory(Context context, String directory, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); CreateDirExecutable executable = @@ -232,8 +238,9 @@ public final class CommandHelper { * @see CreateFileExecutable */ public static boolean createFile(Context context, String file, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); CreateFileExecutable executable = @@ -263,8 +270,9 @@ public final class CommandHelper { * @see DeleteDirExecutable */ public static boolean deleteDirectory(Context context, String directory, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); DeleteDirExecutable executable = @@ -294,8 +302,9 @@ public final class CommandHelper { * @see DeleteFileExecutable */ public static boolean deleteFile(Context context, String file, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); DeleteFileExecutable executable = @@ -324,8 +333,9 @@ public final class CommandHelper { * @see ResolveLinkExecutable */ public static String getAbsolutePath(Context context, String path, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ResolveLinkExecutable executable = @@ -358,8 +368,9 @@ public final class CommandHelper { * @see ResolveLinkExecutable */ public static FileSystemObject resolveSymlink(Context context, String symlink, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ResolveLinkExecutable executable = @@ -387,8 +398,9 @@ public final class CommandHelper { * @see CurrentDirExecutable */ public static String getCurrentDir(Context context, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); CurrentDirExecutable executable = @@ -417,12 +429,14 @@ public final class CommandHelper { * @see ListExecutable */ public static FileSystemObject getFileInfo(Context context, String src, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ListExecutable executable = - c.getExecutableFactory().newCreator().createListExecutable(src, LIST_MODE.FILEINFO); + c.getExecutableFactory(). + newCreator().createListExecutable(src, LIST_MODE.FILEINFO); execute(context, executable, c); List files = executable.getResult(); if (files != null && files.size() > 0) { @@ -450,8 +464,9 @@ public final class CommandHelper { * @see GroupsExecutable */ public static List getGroups(Context context, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); GroupsExecutable executable = @@ -479,8 +494,9 @@ public final class CommandHelper { * @see IdentityExecutable */ public static Identity getIdentity(Context context, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); IdentityExecutable executable = @@ -509,8 +525,9 @@ public final class CommandHelper { * @see ParentDirExecutable */ public static String getParentDir(Context context, String src, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ParentDirExecutable executable = @@ -540,11 +557,13 @@ public final class CommandHelper { * @see EchoExecutable */ public static String getVariable(Context context, String msg, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); - EchoExecutable executable = c.getExecutableFactory().newCreator().createEchoExecutable(msg); + EchoExecutable executable = + c.getExecutableFactory().newCreator().createEchoExecutable(msg); execute(context, executable, c); return executable.getResult(); } @@ -570,8 +589,9 @@ public final class CommandHelper { */ public static List listFiles( Context context, String directory, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ListExecutable executable = @@ -603,8 +623,9 @@ public final class CommandHelper { * @see MoveExecutable */ public static boolean move(Context context, String src, String dst, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); MoveExecutable executable = @@ -635,8 +656,9 @@ public final class CommandHelper { * @see CopyExecutable */ public static boolean copy(Context context, String src, String dst, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException, ReadOnlyFilesystemException { Console c = ensureConsole(context, console); CopyExecutable executable = @@ -646,7 +668,7 @@ public final class CommandHelper { } /** - * Method that makes a search in a directory for search a term. + * Method that does a search in a directory tree seeking for some terms. * * @param context The current context (needed if console == null) * @param directory The "absolute" directory where start the search @@ -670,8 +692,9 @@ public final class CommandHelper { public static AsyncResultExecutable findFiles( Context context, String directory, Query search, AsyncResultListener asyncResultListener, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); FindExecutable executable = @@ -682,6 +705,42 @@ public final class CommandHelper { } /** + * Method that compute the disk usage of a folder. + * + * @param context The current context (needed if console == null) + * @param directory The "absolute" directory where start the search + * @param asyncResultListener The partial result listener + * @param console The console in which execute the program. + * null to attach to the default console + * @return AsyncResultProgram The command executed in background + * @throws FileNotFoundException If the initial directory not exists + * @throws IOException If initial directory can't not be checked + * @throws InvalidCommandDefinitionException If the command has an invalid definition + * @throws NoSuchFileOrDirectory If the file or directory was not found + * @throws ConsoleAllocException If the console can't be allocated + * @throws InsufficientPermissionsException If an operation requires elevated permissions + * @throws CommandNotFoundException If the command was not found + * @throws OperationTimeoutException If the operation exceeded the maximum time of wait + * @throws ExecutionException If the operation returns a invalid exit code + * @see "SearchResult" + * @see AsyncResultExecutable + */ + public static AsyncResultExecutable getFolderUsage( + Context context, String directory, + AsyncResultListener asyncResultListener, Console console) + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, + ExecutionException, InvalidCommandDefinitionException { + Console c = ensureConsole(context, console); + FolderUsageExecutable executable = + c.getExecutableFactory().newCreator(). + createFolderUsageExecutable(directory, asyncResultListener); + execute(context, executable, c); + return executable; + } + + /** * Method that retrieves the disk usage of all the mount points. * * @param context The current context (needed if console == null) @@ -700,8 +759,9 @@ public final class CommandHelper { * @see DiskUsageExecutable */ public static List getDiskUsage(Context context, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); DiskUsageExecutable executable = @@ -730,8 +790,9 @@ public final class CommandHelper { * @see DiskUsageExecutable */ public static DiskUsage getDiskUsage(Context context, String dir, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); DiskUsageExecutable executable = @@ -763,8 +824,9 @@ public final class CommandHelper { * @see MountPointInfoExecutable */ public static List getMountPoints(Context context, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); MountPointInfoExecutable executable = @@ -794,8 +856,9 @@ public final class CommandHelper { * @see MountExecutable */ public static boolean remount(Context context, MountPoint mp, boolean rw, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); MountExecutable executable = @@ -824,8 +887,9 @@ public final class CommandHelper { * @see QuickFolderSearchExecutable */ public static List quickFolderSearch(Context context, String regexp, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); QuickFolderSearchExecutable executable = @@ -839,6 +903,7 @@ public final class CommandHelper { * owned by the main process of this application). * * @param context The current context (needed if console == null) + * @param pid The process id of the shell where the command is running * @param processName The process name * @param console The console in which execute the program. null * to attach to the default console @@ -854,13 +919,15 @@ public final class CommandHelper { * @throws ExecutionException If the operation returns a invalid exit code * @see ProcessIdExecutable */ - public static Integer getProcessId(Context context, String processName, Console console) - throws FileNotFoundException, IOException, ConsoleAllocException, NoSuchFileOrDirectory, - InsufficientPermissionsException, CommandNotFoundException, OperationTimeoutException, + public static Integer getProcessId( + Context context, int pid, String processName, Console console) + throws FileNotFoundException, IOException, ConsoleAllocException, + NoSuchFileOrDirectory, InsufficientPermissionsException, + CommandNotFoundException, OperationTimeoutException, ExecutionException, InvalidCommandDefinitionException { Console c = ensureConsole(context, console); ProcessIdExecutable executable = - c.getExecutableFactory().newCreator().createProcessIdExecutable(processName); + c.getExecutableFactory().newCreator().createProcessIdExecutable(pid, processName); execute(context, executable, c); return executable.getResult(); } @@ -917,8 +984,8 @@ public final class CommandHelper { try { console.execute(executable); } catch (ReadOnlyFilesystemException rofEx) { - //ReadOnlyFilesystemException don't have sense if command is not writable - //WritableExecutable must be used with "writableExecute" method + // ReadOnlyFilesystemException don't have sense if command is not writable + // WritableExecutable must be used with "writableExecute" method throw new ExecutionException(rofEx.getMessage(), rofEx); } } diff --git a/src/com/cyanogenmod/explorer/util/FileHelper.java b/src/com/cyanogenmod/explorer/util/FileHelper.java index 15291ee..6d43dc0 100644 --- a/src/com/cyanogenmod/explorer/util/FileHelper.java +++ b/src/com/cyanogenmod/explorer/util/FileHelper.java @@ -193,12 +193,23 @@ public final class FileHelper { * if fso has no extension. */ public static String getExtension(FileSystemObject fso) { + return getExtension(fso.getName()); + } + + /** + * Method that returns the extension of a file system object. + * + * @param fso The file system object + * @return The extension of the file system object, or null + * if fso has no extension. + */ + public static String getExtension(String fso) { final char dot = '.'; - int pos = fso.getName().lastIndexOf(dot); + int pos = fso.lastIndexOf(dot); if (pos == -1) { return null; } - return fso.getName().substring(pos + 1); + return fso.substring(pos + 1); } /** diff --git a/src/com/cyanogenmod/explorer/util/MimeTypeHelper.java b/src/com/cyanogenmod/explorer/util/MimeTypeHelper.java index 903ca0f..127debb 100644 --- a/src/com/cyanogenmod/explorer/util/MimeTypeHelper.java +++ b/src/com/cyanogenmod/explorer/util/MimeTypeHelper.java @@ -56,35 +56,35 @@ public final class MimeTypeHelper { */ DOCUMENT, /** - * CD Image file + * CD Image file */ CDIMAGE, /** - * Compressed file + * Compressed file */ COMPRESS, /** - * Executable file + * Executable file */ EXEC, /** - * Database file + * Database file */ DATABASE, /** - * Image file + * Image file */ IMAGE, /** - * Audio file + * Audio file */ AUDIO, /** - * Video file + * Video file */ VIDEO, /** - * Security file (certificate, keys, ...) + * Security file (certificate, keys, ...) */ SECURITY } @@ -150,12 +150,11 @@ public final class MimeTypeHelper { // Check if the fso is executable if (fso.getPermissions().getUser().isExecute()) { - return R.drawable.ic_fso_type_executable; + return R.drawable.fso_type_executable; } return R.drawable.ic_fso_default; } - /** * Method that returns the mime/type description of the {@link FileSystemObject}. * @@ -190,15 +189,20 @@ public final class MimeTypeHelper { } return res.getString(R.string.mime_unknown); } - + /** - * Method that returns the mime/type category of the {@link FileSystemObject} - * + * Method that returns the mime/type category of the file system object. + * * @param context The current context * @param fso The file system object * @return MimeTypeCategory The mime/type category */ public static final MimeTypeCategory getCategory(Context context, FileSystemObject fso) { + // Ensure that have a context + if (context == null && sMimeTypes == null) { + // No category + return MimeTypeCategory.NONE; + } //Ensure that mime types are loaded if (sMimeTypes == null) { loadMimeTypes(context); @@ -253,7 +257,7 @@ public final class MimeTypeHelper { } catch (Exception e2) { /**NON BLOCK**/} } - + } catch (Exception e) { Log.e(TAG, "Fail to load mime types raw file.", e); //$NON-NLS-1$ } diff --git a/src/com/cyanogenmod/explorer/util/ParseHelper.java b/src/com/cyanogenmod/explorer/util/ParseHelper.java index e8b9e2a..6d7024f 100644 --- a/src/com/cyanogenmod/explorer/util/ParseHelper.java +++ b/src/com/cyanogenmod/explorer/util/ParseHelper.java @@ -67,6 +67,22 @@ public final class ParseHelper { * @param src The unix string style line * @return FileSystemObject The file system object reference * @throws ParseException If the line can't be parsed + * @see #toFileSystemObject(String, String, boolean) + */ + public static FileSystemObject toFileSystemObject( + final String parent, final String src) throws ParseException { + return toFileSystemObject(parent, src, false); + } + + /** + * Method that parses and creates a {@link FileSystemObject} references from + * a unix string style line. + * + * @param parent The parent of the object + * @param src The unix string style line + * @param quick Do not resolve data (User and Group doesn't have a valid reference) + * @return FileSystemObject The file system object reference + * @throws ParseException If the line can't be parsed */ // // @@ -119,7 +135,7 @@ public final class ParseHelper { // - if object is a symlink, the value must be "link name -> real name" // public static FileSystemObject toFileSystemObject( - final String parent, final String src) throws ParseException { + final String parent, final String src, final boolean quick) throws ParseException { String raw = src; @@ -146,17 +162,27 @@ public final class ParseHelper { String szStartLine = raw.substring(0, matcher.start()).trim(); String szEndLine = raw.substring(matcher.end()).trim(); - //3.- Extract user (user name has no spaces. Can ensure this?) + //3.- Extract user (user name has no spaces. int pos = szStartLine.indexOf(" "); //$NON-NLS-1$ String szUser = szStartLine.substring(0, pos).trim(); szStartLine = szStartLine.substring(pos).trim(); - User oUser = new User(Process.getUidForName(szUser), szUser); + User oUser = null; + if (!quick) { + oUser = new User(Process.getUidForName(szUser), szUser); + } else { + oUser = new User(-1, szUser); + } - //4.- Extract group (group name has no spaces. Can ensure this?) + //4.- Extract group (group name has no spaces. pos = szStartLine.indexOf(" "); //$NON-NLS-1$ String szGroup = szStartLine.substring(0, (pos == -1) ? szStartLine.length() : pos).trim(); szStartLine = szStartLine.substring((pos == -1) ? szStartLine.length() : pos).trim(); - Group oGroup = new Group(Process.getGidForName(szGroup), szGroup); + Group oGroup = null; + if (!quick) { + oGroup = new Group(Process.getGidForName(szGroup), szGroup); + } else { + oGroup = new Group(-1, szGroup); + } //5.- Extract size long lSize = 0; @@ -360,24 +386,24 @@ public final class ParseHelper { * Method that converts to bytes the string representation * of a size (10M, 1G, 0K, ...). * - * @param szSize The size as a string representation + * @param size The size as a string representation * @return long The size in bytes */ - private static long toBytes(String szSize) { - long size = Long.parseLong(szSize.substring(0, szSize.length() - 1)); - String unit = szSize.substring(szSize.length() - 1); + private static long toBytes(String size) { + long bytes = Long.parseLong(size.substring(0, size.length() - 1)); + String unit = size.substring(size.length() - 1); if (unit.compareToIgnoreCase("G") == 0) { //$NON-NLS-1$ - return size * 1024 * 1024 * 1024; + return bytes * 1024 * 1024 * 1024; } if (unit.compareToIgnoreCase("M") == 0) { //$NON-NLS-1$ - return size * 1024 * 1024; + return bytes * 1024 * 1024; } if (unit.compareToIgnoreCase("K") == 0) { //$NON-NLS-1$ - return size * 1024; + return bytes * 1024; } //Don't touch - return size; + return bytes; } } diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 39b1415..1fd0d88 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -4,6 +4,8 @@ + + diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java index 870121d..664e141 100644 --- a/tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java +++ b/tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java @@ -51,7 +51,7 @@ public class FindCommandTest extends AbstractConsoleTest { * @throws Exception If test failed */ @SuppressWarnings("synthetic-access") - public void testListWithPartialResult() throws Exception { + public void testFindWithPartialResult() throws Exception { this.mNewPartialData = false; Query query = new Query().setSlot(FIND_TERM_PARTIAL, 0); final List files = new ArrayList(); @@ -67,9 +67,10 @@ public class FindCommandTest extends AbstractConsoleTest { public void onException(Exception cause) { fail(cause.toString()); } - public void onPartialResult(List results) { + @SuppressWarnings("unchecked") + public void onPartialResult(Object results) { FindCommandTest.this.mNewPartialData = true; - files.addAll(results); + files.addAll((List)results); } }, getConsole()); synchronized (FindCommandTest.this.mSync) { diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommandTest.java new file mode 100644 index 0000000..29b4354 --- /dev/null +++ b/tests/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommandTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.explorer.commands.shell; + +import android.util.Log; + +import com.cyanogenmod.explorer.commands.AsyncResultListener; +import com.cyanogenmod.explorer.model.FolderUsage; +import com.cyanogenmod.explorer.util.CommandHelper; +import com.cyanogenmod.explorer.util.MimeTypeHelper.MimeTypeCategory; + +/** + * A class for testing folder usage command. + * + * @see FindCommand + */ +public class FolderUsageCommandTest extends AbstractConsoleTest { + + private static final String TAG = "FolderUsageCommandTest"; //$NON-NLS-1$ + + private static final String PATH = "/system"; //$NON-NLS-1$ + + private final Object mSync = new Object(); + private boolean mNewPartialData; + private FolderUsage mUsage; + + /** + * {@inheritDoc} + */ + @Override + public boolean isRootConsoleNeeded() { + return false; + } + + /** + * Method that performs a test over known search results. + * + * @throws Exception If test failed + */ + @SuppressWarnings("synthetic-access") + public void testFolderUsageWithPartialResult() throws Exception { + this.mNewPartialData = false; + this.mUsage = null; + CommandHelper.getFolderUsage(getContext(), PATH, new AsyncResultListener() { + public void onAsyncStart() { + /**NON BLOCK**/ + } + public void onAsyncEnd(boolean cancelled) { + synchronized (FolderUsageCommandTest.this.mSync) { + FolderUsageCommandTest.this.mSync.notifyAll(); + } + } + public void onException(Exception cause) { + fail(cause.toString()); + } + public void onPartialResult(Object result) { + FolderUsageCommandTest.this.mNewPartialData = true; + try { + FolderUsageCommandTest.this.mUsage = + (FolderUsage)(((FolderUsage)result).clone()); + } catch (Exception e) {/**NON BLOCK**/} + Log.d(TAG, FolderUsageCommandTest.this.mUsage.toString()); + } + }, getConsole()); + synchronized (FolderUsageCommandTest.this.mSync) { + FolderUsageCommandTest.this.mSync.wait(25000L); + } + assertTrue("no new partial data", this.mNewPartialData); //$NON-NLS-1$ + assertNotNull("usage==null", this.mUsage); //$NON-NLS-1$ + assertTrue("no folder returned", this.mUsage.getNumberOfFolders() > 0); //$NON-NLS-1$ + assertTrue("no files returned", this.mUsage.getNumberOfFiles() > 0); //$NON-NLS-1$ + assertTrue("no size returned", this.mUsage.getTotalSize() > 0); //$NON-NLS-1$ + assertTrue("no text category returned", //$NON-NLS-1$ + this.mUsage.getStatisticsForCategory(MimeTypeCategory.TEXT) > 0); + } + +} diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommandTest.java index bdabcc5..6196690 100644 --- a/tests/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommandTest.java +++ b/tests/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommandTest.java @@ -15,10 +15,6 @@ */ package com.cyanogenmod.explorer.commands.shell; - -import com.cyanogenmod.explorer.ExplorerApplication; -import com.cyanogenmod.explorer.util.CommandHelper; - /** * A class for testing the {@link ProcessIdCommand} command. * @@ -34,21 +30,6 @@ public class ProcessIdCommandTest extends AbstractConsoleTest { return false; } - /** - * Method that performs a test over id command. - * - * @throws Exception If test failed - */ - public void testId() throws Exception { - Integer main = Integer.valueOf(android.os.Process.myPid()); - Integer pid = - CommandHelper.getProcessId( - getContext(), - ExplorerApplication.MAIN_PROCESS, getConsole()); - assertNotNull("pid==null", pid); //$NON-NLS-1$ - assertTrue( - String.format("pid != main process id (%d)", main), //$NON-NLS-1$ - pid.compareTo(main) == 0); - } - + // Can't perform any test, because a running program in a shell is needed, and PID of + // shell is not available for external use outside the console. }