aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/layout/filesystem_info_dialog.xml4
-rw-r--r--res/layout/fso_properties_dialog.xml35
-rw-r--r--res/values/overlay.xml33
-rw-r--r--res/values/strings.xml23
-rw-r--r--res/xml/command_list.xml6
-rw-r--r--src/com/cyanogenmod/explorer/activities/NavigationActivity.java4
-rw-r--r--src/com/cyanogenmod/explorer/activities/SearchActivity.java57
-rw-r--r--src/com/cyanogenmod/explorer/commands/AsyncResultListener.java7
-rw-r--r--src/com/cyanogenmod/explorer/commands/ExecutableCreator.java55
-rw-r--r--src/com/cyanogenmod/explorer/commands/FindExecutable.java2
-rw-r--r--src/com/cyanogenmod/explorer/commands/FolderUsageExecutable.java24
-rw-r--r--src/com/cyanogenmod/explorer/commands/shell/FindCommand.java11
-rw-r--r--src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommand.java208
-rw-r--r--src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommand.java21
-rw-r--r--src/com/cyanogenmod/explorer/commands/shell/Shell.java21
-rw-r--r--src/com/cyanogenmod/explorer/commands/shell/ShellExecutableCreator.java31
-rw-r--r--src/com/cyanogenmod/explorer/console/shell/ShellConsole.java22
-rw-r--r--src/com/cyanogenmod/explorer/model/FolderUsage.java220
-rw-r--r--src/com/cyanogenmod/explorer/ui/dialogs/FsoPropertiesDialog.java207
-rw-r--r--src/com/cyanogenmod/explorer/util/CommandHelper.java183
-rw-r--r--src/com/cyanogenmod/explorer/util/FileHelper.java15
-rw-r--r--src/com/cyanogenmod/explorer/util/MimeTypeHelper.java32
-rw-r--r--src/com/cyanogenmod/explorer/util/ParseHelper.java52
-rw-r--r--tests/AndroidManifest.xml2
-rw-r--r--tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java7
-rw-r--r--tests/src/com/cyanogenmod/explorer/commands/shell/FolderUsageCommandTest.java91
-rw-r--r--tests/src/com/cyanogenmod/explorer/commands/shell/ProcessIdCommandTest.java23
27 files changed, 1206 insertions, 190 deletions
diff --git a/res/layout/filesystem_info_dialog.xml b/res/layout/filesystem_info_dialog.xml
index 3103e604..9a15b1c6 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" />
</TableRow>
@@ -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" />
</TableRow>
@@ -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" />
</TableRow>
@@ -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" />
</TableRow>
diff --git a/res/layout/fso_properties_dialog.xml b/res/layout/fso_properties_dialog.xml
index 08e15868..45fe0123 100644
--- a/res/layout/fso_properties_dialog.xml
+++ b/res/layout/fso_properties_dialog.xml
@@ -15,7 +15,7 @@
** limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- Tabs -->
@@ -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" />
</TableRow>
@@ -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" />
</TableRow>
@@ -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" />
</TableRow>
@@ -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" />
</TableRow>
@@ -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" />
+ </TableRow>
+
+ <!-- Contains -->
+ <TableRow
+ android:id="@+id/fso_properties_contains_row"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/extra_large_margin"
+ android:layout_marginRight="@dimen/extra_large_margin"
+ android:visibility="gone" >
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/default_margin"
+ android:gravity="left|center_vertical"
+ android:text="@string/fso_properties_dialog_contains"
+ android:textAppearance="@style/primary_text_appearance" />
+
+ <TextView
+ android:id="@+id/fso_properties_contains"
+ android:layout_width="match_parent"
+ 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" />
</TableRow>
@@ -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" />
</TableRow>
diff --git a/res/values/overlay.xml b/res/values/overlay.xml
new file mode 100644
index 00000000..36e12381
--- /dev/null
+++ b/res/values/overlay.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ** 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.
+-->
+
+<!--
+ This file contains values that could be overlayed. This allow
+ configure special values for each device. Use overlay building folder on device tree
+ for overlay this values
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- The buffer use to read files (in bytes). Default: 0.5 Mb -->
+ <integer name="read_buffer_size">512</integer>
+
+ <!-- The maximum file size that the app is able to read. Beyond this size the user will get a
+ warning message (in bytes). Default: 5 Mb
+ -->
+ <integer name="max_read_file_size">5120</integer>
+
+</resources> \ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 98ba532b..47948e41 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -55,6 +55,12 @@
<!-- Loading waiting message -->
<string name="loading_message">Loading&#8230;</string>
+ <!-- Computing message -->
+ <string name="computing_message">Computing&#8230; <xliff:g id="data">%1$s</xliff:g></string>
+ <!-- Computing new line message -->
+ <string name="computing_message_ln">Computing&#8230;\n<xliff:g id="data">%1$s</xliff:g></string>
+ <!-- Cancelled message -->
+ <string name="cancelled_message">Cancelled.</string>
<!-- Error message -->
<string name="error_message">Error.</string>
@@ -232,6 +238,8 @@
<string name="fso_properties_dialog_link">Link:</string>
<!-- Fso Properties Dialog * Size Label -->
<string name="fso_properties_dialog_size">Size:</string>
+ <!-- Fso Properties Dialog * Contains Label -->
+ <string name="fso_properties_dialog_contains">Contains:</string>
<!-- Fso Properties Dialog * Date Label -->
<string name="fso_properties_dialog_date">Last Access:</string>
<!-- Fso Properties Dialog * Owner Label -->
@@ -248,6 +256,21 @@
<string name="fso_properties_dialog_write" translatable="false">W</string>
<!-- Fso Properties Dialog * Execute Label -->
<string name="fso_properties_dialog_execute" translatable="false">X</string>
+ <!-- Fso Properties Dialog * Execute Label -->
+ <string name="fso_properties_dialog_folder_items">
+ <xliff:g id="folders">%1$s</xliff:g> / <xliff:g id="files">%2$s</xliff:g></string>
+ <!-- Fso Properties Dialog * Folders -->
+ <plurals name="fso_properties_dialog_folders">
+ <item quantity="zero">0 folders</item>
+ <item quantity="one">1 folder</item>
+ <item quantity="other"><xliff:g id="folders">%1$d</xliff:g> folders</item>
+ </plurals>
+ <!-- Fso Properties Dialog * Files -->
+ <plurals name="fso_properties_dialog_files">
+ <item quantity="zero">0 files</item>
+ <item quantity="one">1 files</item>
+ <item quantity="other"><xliff:g id="files">%1$d</xliff:g> files</item>
+ </plurals>
<!-- Choose console dialog title -->
<string name="choose_console_dialog_title">Choose console</string>
diff --git a/res/xml/command_list.xml b/res/xml/command_list.xml
index d1693690..489ea250 100644
--- a/res/xml/command_list.xml
+++ b/res/xml/command_list.xml
@@ -44,6 +44,7 @@
<command commandId="echo" commandPath="/system/xbin/echo" commandArgs="%1$s" />
<command commandId="fileinfo" commandPath="/system/bin/ls" commandArgs="-ald %1$s" />
<command commandId="find" commandPath="/system/xbin/find" commandArgs="%1$s \\( -name %2$s -o -name %3$s -o -name %4$s -o -name %5$s -o -name %6$s \\) -exec /system/xbin/echo {} \\; -exec /system/bin/ls -ald {} \\;" />
+ <command commandId="folderusage" commandPath="/system/bin/ls" commandArgs="-alR %1$s" />
<command commandId="groups" commandPath="/system/xbin/groups" commandArgs="" />
<command commandId="id" commandPath="/system/bin/id" commandArgs="-Gn" />
<command commandId="ls" commandPath="cd" commandArgs="%1$s &amp;&amp; /system/bin/ls -al %1$s | /system/xbin/grep -v -e '->' &amp;&amp; echo '>SIMLINKS>' &amp;&amp; /system/bin/ls -al %1$s | { /system/xbin/grep -e '->' || true; } &amp;&amp; echo '>SIMLINKS_DATA>' &amp;&amp; /system/bin/ls -aF %1$s | /system/xbin/grep -e '^l' | /system/xbin/awk '{print $2}' | /system/xbin/xargs -r -n1 /system/xbin/readlink -f &amp;&amp; /system/bin/ls -F %1$s | /system/xbin/grep -e '^l' | /system/xbin/awk '{print $2}' | /system/xbin/xargs -r -n1 /system/xbin/readlink -f | { /system/xbin/xargs -r -n1 /system/bin/ls -ald || true; }" />
@@ -51,10 +52,11 @@
<command commandId="mount" commandPath="/system/bin/mount" commandArgs="-o %1$s,remount -t auto %2$s %3$s" />
<command commandId="mountpointinfo" commandPath="/system/bin/cat" commandArgs="/proc/mounts" />
<command commandId="mv" commandPath="/system/bin/mv" commandArgs="%1$s %2$s" />
- <command commandId="pid" commandPath="/system/bin/ps" commandArgs="| /system/xbin/grep `ps | /system/xbin/grep %1$s | /system/xbin/awk '{print $1}'` | grep %2$s | /system/xbin/awk '{print $2}'" />
+ <command commandId="pid_shell" commandPath="/system/xbin/echo" commandArgs="$$" />
+ <command commandId="pid_cmd" commandPath="/system/bin/ps" commandArgs="| /system/xbin/grep %1$s | /system/xbin/grep -w %2$s | /system/xbin/awk '{print $2}'" />
<command commandId="pwd" commandPath="/system/xbin/pwd" commandArgs="-P" />
<command commandId="quickfoldersearch" commandPath="/system/bin/ls" commandArgs="-aFd %1$s.* %1$s* | /system/xbin/grep -e '^d' -e '^ld' | /system/xbin/awk '{print $2}'" />
- <command commandId="readlink" commandPath="cd" commandArgs="`/system/xbin/dirname %1$s` &amp;&amp; /system/xbin/readlink -f %1$s | awk -F// '{print &quot;\\&quot;&quot;$1&quot;\\&quot;&quot;}' | /system/xbin/xargs -n1 /system/xbin/dirname &amp;&amp; /system/xbin/readlink -f %1$s | awk -F// '{print &quot;\\&quot;&quot;$1&quot;\\&quot;&quot;}' | /system/xbin/xargs -n1 /system/bin/ls -ald" />
+ <command commandId="readlink" commandPath="cd" commandArgs="`/system/xbin/dirname %1$s` &amp;&amp; /system/xbin/readlink -f %1$s | /system/xbin/awk -F// '{print &quot;\\&quot;&quot;$1&quot;\\&quot;&quot;}' | /system/xbin/xargs -n1 /system/xbin/dirname &amp;&amp; /system/xbin/readlink -f %1$s | /system/xbin/awk -F// '{print &quot;\\&quot;&quot;$1&quot;\\&quot;&quot;}' | /system/xbin/xargs -n1 /system/bin/ls -ald" />
<command commandId="rm" commandPath="/system/bin/rm" commandArgs="%1$s" />
<command commandId="rmdir" commandPath="/system/bin/rm" commandArgs="-r %1$s" />
<command commandId="touch" commandPath="/system/xbin/echo" commandArgs="-n '' >> %1$s" />
diff --git a/src/com/cyanogenmod/explorer/activities/NavigationActivity.java b/src/com/cyanogenmod/explorer/activities/NavigationActivity.java
index 5631e5b1..13dca603 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 8fe4dc2c..2f94b729 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<SearchResult> 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<FileSystemObject> 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<FileSystemObject>)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 e0f2a14b..defa9305 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<FileSystemObject> 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 33810032..e024b9e2 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 b4a8dc9e..ad08716b 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 00000000..cc1b6a42
--- /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 e519171a..5168c166 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 <code>FindCommand</code>. This constructor uses a
- * <code>DIRECTORY</code> mode as listing mode.
+ * Constructor of <code>FindCommand</code>.
*
* @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 00000000..b662c574
--- /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 <code>FolderUsageCommand</code>.
+ *
+ * @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<String> lines = new ArrayList<String>();
+ 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 228bd96a..fc202033 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 <code>ProcessIdCommand</code>.
+ * Constructor of <code>ProcessIdCommand</code>.<br/>
+ * 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 <code>ProcessIdCommand</code>.<br/>
+ * 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 9b05326c..bb311233 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 <code>Shell</code>
*
@@ -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 a4e3dca3..b13afb1a 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 c6ae3d5d..d5f68849 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 00000000..0d6339e2
--- /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<Long> mStatistics;
+
+ /**
+ * Constructor of <code>FolderUsage</code>.
+ *
+ * @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<Long>(categories.length-1);
+ for (int i=0; i<categories.length; i++) {
+ this.mStatistics.put(categories[i].ordinal(), Long.valueOf(0));
+ }
+ }
+
+ /**
+ * Method that adds 1 folder to the total number of folders.
+ */
+ public void addFolder() {
+ this.mNumberOfFolders ++;
+ }
+
+ /**
+ * Method that adds 1 file to the total number of files.
+ */
+ public void addFile() {
+ this.mNumberOfFiles ++;
+ }
+
+ /**
+ * Method that adds to the total size.
+ *
+ * @param size The size to add to the total
+ */
+ public void addSize(long size) {
+ this.mTotalSize += size;
+ }
+
+ /**
+ * Method that add a file to the category
+ *
+ * @param category The category
+ */
+ public void addFileToCategory(MimeTypeCategory category) {
+ long count = this.mStatistics.get(category.ordinal()).longValue();
+ count++;
+ this.mStatistics.put(category.ordinal(), Long.valueOf(count));
+ }
+
+ /**
+ * Method that returns the folder of which retrieve the usage.
+ *
+ * @return String The folder of which retrieve the usage
+ */
+ public String getFolder() {
+ return this.mFolder;
+ }
+
+ /**
+ * Method that returns the total number of folders.
+ *
+ * @return int The total number of folders
+ */
+ public int getNumberOfFolders() {
+ return this.mNumberOfFolders;
+ }
+
+ /**
+ * Method that returns the total number of files.
+ *
+ * @return int The total number of files
+ */
+ public int getNumberOfFiles() {
+ return this.mNumberOfFiles;
+ }
+
+ /**
+ * Method that returns the total size.
+ *
+ * @return long The total size
+ */
+ public long getTotalSize() {
+ return this.mTotalSize;
+ }
+
+ /**
+ * Method sets the total size.
+ *
+ * @param totalSize The total size
+ */
+ public void setTotalSize(long totalSize) {
+ this.mTotalSize = totalSize;
+ }
+
+ /**
+ * Method that returns the number of files for a {@link MimeTypeCategory}.
+ *
+ * @param category The category
+ * @return long The number of files for the category
+ */
+ public long getStatisticsForCategory(MimeTypeCategory category) {
+ return this.mStatistics.get(category.ordinal()).longValue();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.mFolder == null) ? 0 : this.mFolder.hashCode());
+ result = prime * result + this.mNumberOfFiles;
+ result = prime * result + this.mNumberOfFolders;
+ result = prime * result
+ + ((this.mStatistics == null) ? 0 : this.mStatistics.hashCode());
+ result = prime * result + (int) (this.mTotalSize ^ (this.mTotalSize >>> 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 27db6bc3..8824908f 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<Void, Void, SparseArray<AID>> aidsTask =
new AsyncTask<Void, Void, SparseArray<AID>>() {
@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 07e11bc3..74d2f6b8 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<FileSystemObject> files = executable.getResult();
if (files != null && files.size() > 0) {
@@ -450,8 +464,9 @@ public final class CommandHelper {
* @see GroupsExecutable
*/
public static List<Group> 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<FileSystemObject> 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.
+ * <code>null</code> 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<DiskUsage> 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<MountPoint> 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<String> 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. <code>null</code>
* 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 15291eeb..6d43dc01 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 <code>fso</code> 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 <code>null</code>
+ * if <code>fso</code> 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 903ca0ff..127debb3 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 e8b9e2a8..6d7024fb 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
*/
//
//<permission> <user> <group> <size> <last modified> <name>
@@ -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 39b1415b..1fd0d883 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -4,6 +4,8 @@
<original-package android:name="com.cyanogenmod.explorer.test" />
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16" />
+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
diff --git a/tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java b/tests/src/com/cyanogenmod/explorer/commands/shell/FindCommandTest.java
index 870121d0..664e141d 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<FileSystemObject> files = new ArrayList<FileSystemObject>();
@@ -67,9 +67,10 @@ public class FindCommandTest extends AbstractConsoleTest {
public void onException(Exception cause) {
fail(cause.toString());
}
- public void onPartialResult(List<FileSystemObject> results) {
+ @SuppressWarnings("unchecked")
+ public void onPartialResult(Object results) {
FindCommandTest.this.mNewPartialData = true;
- files.addAll(results);
+ files.addAll((List<FileSystemObject>)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 00000000..29b43546
--- /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 bdabcc53..61966903 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.
}