diff options
Diffstat (limited to 'src')
10 files changed, 217 insertions, 157 deletions
diff --git a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java index 9e67966..912c0be 100644 --- a/src/com/cyanogenmod/filemanager/activities/EditorActivity.java +++ b/src/com/cyanogenmod/filemanager/activities/EditorActivity.java @@ -42,6 +42,7 @@ import android.widget.TextView; import android.widget.TextView.BufferType; import android.widget.Toast; +import com.cyanogenmod.filemanager.FileManagerApplication; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.commands.AsyncResultListener; import com.cyanogenmod.filemanager.commands.WriteExecutable; @@ -49,6 +50,7 @@ import com.cyanogenmod.filemanager.console.ConsoleBuilder; import com.cyanogenmod.filemanager.console.InsufficientPermissionsException; import com.cyanogenmod.filemanager.console.RelaunchableException; import com.cyanogenmod.filemanager.model.FileSystemObject; +import com.cyanogenmod.filemanager.preferences.AccessMode; import com.cyanogenmod.filemanager.preferences.FileManagerSettings; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; @@ -550,9 +552,12 @@ public class EditorActivity extends Activity implements TextWatcher { // Check if the read was successfully if (this.mReader.mCause != null) { // Check if we can't read the file because we don't the require - // permissions + // permissions. If we are in a ChRooted environment, resolve the + // error without doing anymore if (this.mReader.mCause instanceof InsufficientPermissionsException) { - if (!ConsoleBuilder.isPrivileged()) { + if (!ConsoleBuilder.isPrivileged() && + FileManagerApplication.getAccessMode(). + compareTo(AccessMode.SAFE) != 0) { // We don't have a privileged console, we can't ask the user // to gain privileges and relauch the command again askGainAccessAndRead( diff --git a/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java b/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java index 438e8c1..b78aafc 100644 --- a/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java +++ b/src/com/cyanogenmod/filemanager/activities/preferences/SettingsPreferences.java @@ -304,6 +304,8 @@ public class SettingsPreferences extends PreferenceActivity { FileManagerSettings.SETTINGS_ACCESS_MODE.getId(), defaultValue); this.mOnChangeListener.onPreferenceChange(this.mAccessMode, value); + // If device is not rooted, this setting cannot be changed + this.mAccessMode.setEnabled(FileManagerApplication.isDeviceRooted()); // Capture Debug traces this.mDebugTraces = diff --git a/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java b/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java index 3e1e316..0c7832c 100644 --- a/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java +++ b/src/com/cyanogenmod/filemanager/commands/java/CopyCommand.java @@ -23,13 +23,10 @@ import com.cyanogenmod.filemanager.console.ExecutionException; import com.cyanogenmod.filemanager.console.InsufficientPermissionsException; import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory; import com.cyanogenmod.filemanager.model.MountPoint; +import com.cyanogenmod.filemanager.util.FileHelper; import com.cyanogenmod.filemanager.util.MountPointHelper; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; /** @@ -84,7 +81,7 @@ public class CopyCommand extends Program implements CopyExecutable { } //Copy recursively - if (!copyRecursive(s, d)) { + if (!FileHelper.copyRecursive(s, d, getBufferSize())) { if (isTrace()) { Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$ } @@ -111,82 +108,4 @@ public class CopyCommand extends Program implements CopyExecutable { public MountPoint getDstWritableMountPoint() { return MountPointHelper.getMountPointFromDirectory(this.mDst); } - - /** - * Method that copies recursively to the destination - * - * @param src The source file or folder - * @param dst The destination file or folder - * @return boolean If the operation complete successfully - * @throws ExecutionException If a problem was detected in the operation - */ - public boolean copyRecursive(final File src, final File dst) throws ExecutionException { - if (src.isDirectory()) { - // Create the directory - if (dst.exists() && !dst.isDirectory()) { - Log.e(TAG, - String.format("Failed to check destionation dir: %s", dst)); //$NON-NLS-1$ - throw new ExecutionException("the path exists but is not a folder"); //$NON-NLS-1$ - } - if (!dst.exists()) { - if (!dst.mkdir()) { - Log.e(TAG, String.format("Failed to create directory: %s", dst)); //$NON-NLS-1$ - return false; - } - } - File[] files = src.listFiles(); - if (files != null) { - for (int i = 0; i < files.length; i++) { - if (!copyRecursive(files[i], new File(dst, files[i].getName()))) { - return false; - } - } - } - } else { - // Copy the directory - if (!bufferedCopy(src, dst)) { - return false; - } - } - return true; - } - - /** - * Method that copies a file - * - * @param src The source file - * @param dst The destination file - * @return boolean If the operation complete successfully - */ - public boolean bufferedCopy(final File src, final File dst) { - BufferedInputStream bis = null; - BufferedOutputStream bos = null; - try { - bis = new BufferedInputStream(new FileInputStream(src), getBufferSize()); - bos = new BufferedOutputStream(new FileOutputStream(dst), getBufferSize()); - int read = 0; - byte[] data = new byte[getBufferSize()]; - while ((read = bis.read(data, 0, getBufferSize())) != -1) { - bos.write(data, 0, read); - } - return true; - - } catch (Throwable e) { - Log.e(TAG, - String.format(TAG, "Failed to copy from %s to %d", src, dst), e); //$NON-NLS-1$ - return false; - } finally { - try { - if (bis != null) { - bis.close(); - } - } catch (Throwable e) {/**NON BLOCK**/} - try { - if (bos != null) { - bos.close(); - } - } catch (Throwable e) {/**NON BLOCK**/} - } - - } } diff --git a/src/com/cyanogenmod/filemanager/commands/java/DeleteDirCommand.java b/src/com/cyanogenmod/filemanager/commands/java/DeleteDirCommand.java index 07e9498..04b8e20 100644 --- a/src/com/cyanogenmod/filemanager/commands/java/DeleteDirCommand.java +++ b/src/com/cyanogenmod/filemanager/commands/java/DeleteDirCommand.java @@ -23,6 +23,7 @@ import com.cyanogenmod.filemanager.console.ExecutionException; import com.cyanogenmod.filemanager.console.InsufficientPermissionsException; import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory; import com.cyanogenmod.filemanager.model.MountPoint; +import com.cyanogenmod.filemanager.util.FileHelper; import com.cyanogenmod.filemanager.util.MountPointHelper; import java.io.File; @@ -84,7 +85,7 @@ public class DeleteDirCommand extends Program implements DeleteDirExecutable { } // Delete the file - if (!deleteFolder(f)) { + if (!FileHelper.deleteFolder(f)) { if (isTrace()) { Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$ } @@ -111,28 +112,4 @@ public class DeleteDirCommand extends Program implements DeleteDirExecutable { public MountPoint getDstWritableMountPoint() { return MountPointHelper.getMountPointFromDirectory(this.mPath); } - - /** - * Method that deletes a folder recursively - * - * @param folder The folder to delete - * @return boolean If the folder was deleted - */ - private boolean deleteFolder(File folder) { - File[] files = folder.listFiles(); - if (files != null) { - for (int i = 0; i < files.length; i++) { - if (files[i].isDirectory()) { - if (!deleteFolder(files[i])) { - return false; - } - } else { - if (!files[i].delete()) { - return false; - } - } - } - } - return folder.delete(); - } } diff --git a/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java b/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java index f94e7f1..b0c85fb 100644 --- a/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java +++ b/src/com/cyanogenmod/filemanager/commands/java/MoveCommand.java @@ -23,6 +23,7 @@ import com.cyanogenmod.filemanager.console.ExecutionException; import com.cyanogenmod.filemanager.console.InsufficientPermissionsException; import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory; import com.cyanogenmod.filemanager.model.MountPoint; +import com.cyanogenmod.filemanager.util.FileHelper; import com.cyanogenmod.filemanager.util.MountPointHelper; import java.io.File; @@ -78,12 +79,34 @@ public class MoveCommand extends Program implements MoveExecutable { throw new NoSuchFileOrDirectory(this.mSrc); } - //Copy recursively - if (!s.renameTo(d)) { - if (isTrace()) { - Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$ + //Move or copy recursively + if (d.exists()) { + if (!FileHelper.copyRecursive(s, d, getBufferSize())) { + if (isTrace()) { + Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$ + } + throw new InsufficientPermissionsException(); + } + if (!FileHelper.deleteFolder(s)) { + if (isTrace()) { + Log.v(TAG, "Result: OK. WARNING. Source not deleted."); //$NON-NLS-1$ + } + } + } else { + // Move between filesystem is not allow. If rename fails then use copy operation + if (!s.renameTo(d)) { + if (!FileHelper.copyRecursive(s, d, getBufferSize())) { + if (isTrace()) { + Log.v(TAG, "Result: FAIL. InsufficientPermissionsException"); //$NON-NLS-1$ + } + throw new InsufficientPermissionsException(); + } + if (!FileHelper.deleteFolder(s)) { + if (isTrace()) { + Log.v(TAG, "Result: OK. WARNING. Source not deleted."); //$NON-NLS-1$ + } + } } - throw new InsufficientPermissionsException(); } if (isTrace()) { diff --git a/src/com/cyanogenmod/filemanager/ui/dialogs/FsoPropertiesDialog.java b/src/com/cyanogenmod/filemanager/ui/dialogs/FsoPropertiesDialog.java index 44c9800..4a5a06a 100644 --- a/src/com/cyanogenmod/filemanager/ui/dialogs/FsoPropertiesDialog.java +++ b/src/com/cyanogenmod/filemanager/ui/dialogs/FsoPropertiesDialog.java @@ -347,7 +347,7 @@ public class FsoPropertiesDialog new AsyncTask<Void, Void, SparseArray<AID>>() { @Override protected SparseArray<AID> doInBackground(Void...params) { - return AIDHelper.getAIDs(FsoPropertiesDialog.this.mContext); + return AIDHelper.getAIDs(FsoPropertiesDialog.this.mContext, true); } @Override diff --git a/src/com/cyanogenmod/filemanager/util/AIDHelper.java b/src/com/cyanogenmod/filemanager/util/AIDHelper.java index c94cf2d..50b3efe 100644 --- a/src/com/cyanogenmod/filemanager/util/AIDHelper.java +++ b/src/com/cyanogenmod/filemanager/util/AIDHelper.java @@ -36,6 +36,8 @@ public final class AIDHelper { private static final String TAG = "AIDHelper"; //$NON-NLS-1$ + private static SparseArray<AID> sAids; + /** * Constructor of <code>AIDHelper</code>. */ @@ -47,45 +49,51 @@ public final class AIDHelper { * Method that returns the Android IDs (system + application AID) * * @param context The current context + * @param force Force the reload of the AIDs * @return SparseArray<AID> The array of {@link AID} */ - public static SparseArray<AID> getAIDs(Context context) { - Properties systemAIDs = null; - try { - // Load the default known system identifiers - systemAIDs = new Properties(); - systemAIDs.load(context.getResources().openRawResource(R.raw.aid)); - } catch (Exception e) { - Log.e(TAG, "Fail to load AID raw file.", e); //$NON-NLS-1$ - return null; - } + public synchronized static SparseArray<AID> getAIDs(Context context, boolean force) { + if (sAids == null || force) { + Properties systemAIDs = null; + try { + // Load the default known system identifiers + systemAIDs = new Properties(); + systemAIDs.load(context.getResources().openRawResource(R.raw.aid)); + } catch (Exception e) { + Log.e(TAG, "Fail to load AID raw file.", e); //$NON-NLS-1$ + return null; + } - // Add the default known system identifiers - SparseArray<AID> aids = new SparseArray<AID>(); - Iterator<Object> it = systemAIDs.keySet().iterator(); - while (it.hasNext()) { - String key = (String)it.next(); - String value = systemAIDs.getProperty(key); - int uid = Integer.parseInt(key); - aids.put(uid, new AID(uid, value)); - } + // Add the default known system identifiers + SparseArray<AID> aids = new SparseArray<AID>(); + Iterator<Object> it = systemAIDs.keySet().iterator(); + while (it.hasNext()) { + String key = (String)it.next(); + String value = systemAIDs.getProperty(key); + int uid = Integer.parseInt(key); + aids.put(uid, new AID(uid, value)); + } - // Now, retrieve all AID of installed applications - final PackageManager pm = context.getPackageManager(); - List<ApplicationInfo> packages = - pm.getInstalledApplications(PackageManager.GET_META_DATA); - int cc = packages.size(); - for (int i = 0; i < cc; i++) { - ApplicationInfo info = packages.get(i); - int uid = info.uid; - if (aids.indexOfKey(uid) < 0) { - String name = pm.getNameForUid(uid); - aids.put(uid, new AID(uid, name)); + // Now, retrieve all AID of installed applications + final PackageManager pm = context.getPackageManager(); + List<ApplicationInfo> packages = + pm.getInstalledApplications(PackageManager.GET_META_DATA); + int cc = packages.size(); + for (int i = 0; i < cc; i++) { + ApplicationInfo info = packages.get(i); + int uid = info.uid; + if (aids.indexOfKey(uid) < 0) { + String name = pm.getNameForUid(uid); + aids.put(uid, new AID(uid, name)); + } } + + // Save to cached aids + sAids = aids; } // Return the list of AIDs found - return aids; + return sAids; } /** @@ -96,7 +104,9 @@ public final class AIDHelper { * @return AID The AID */ public static AID getAIDFromName(Context ctx, String name) { - SparseArray<AID> aids = getAIDs(ctx); + // This method is only used by java console under chrooted mode, so + // is safe to caching aids, because sdcards only allow known aids + SparseArray<AID> aids = getAIDs(ctx, false); int len = aids.size(); for (int i = 0; i < len; i++) { AID aid = aids.valueAt(i); @@ -104,7 +114,7 @@ public final class AIDHelper { return aid; } } - return null; + return new AID(-1, ""); //$NON-NLS-1$ } } diff --git a/src/com/cyanogenmod/filemanager/util/ExceptionUtil.java b/src/com/cyanogenmod/filemanager/util/ExceptionUtil.java index 213f4dc..84821f9 100644 --- a/src/com/cyanogenmod/filemanager/util/ExceptionUtil.java +++ b/src/com/cyanogenmod/filemanager/util/ExceptionUtil.java @@ -256,7 +256,7 @@ public final class ExceptionUtil { } // If console is privileged there is not need to change - // If we are in a ChRooted environment, resolve the error without do anymore + // If we are in a ChRooted environment, resolve the error without doing anymore if (relaunchable instanceof InsufficientPermissionsException && (isPrivileged || FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0)) { diff --git a/src/com/cyanogenmod/filemanager/util/FileHelper.java b/src/com/cyanogenmod/filemanager/util/FileHelper.java index ba6c05e..bd90497 100644 --- a/src/com/cyanogenmod/filemanager/util/FileHelper.java +++ b/src/com/cyanogenmod/filemanager/util/FileHelper.java @@ -24,6 +24,7 @@ import android.util.Log; import com.cyanogenmod.filemanager.FileManagerApplication; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.commands.shell.ResolveLinkCommand; +import com.cyanogenmod.filemanager.console.ExecutionException; import com.cyanogenmod.filemanager.model.AID; import com.cyanogenmod.filemanager.model.BlockDevice; import com.cyanogenmod.filemanager.model.CharacterDevice; @@ -43,7 +44,11 @@ import com.cyanogenmod.filemanager.preferences.NavigationSortMode; import com.cyanogenmod.filemanager.preferences.ObjectIdentifier; import com.cyanogenmod.filemanager.preferences.Preferences; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.util.Collections; import java.util.Comparator; @@ -836,4 +841,108 @@ public final class FileHelper { } return null; } + + /** + * Method that copies recursively to the destination + * + * @param src The source file or folder + * @param dst The destination file or folder + * @param bufferSize The buffer size for the operation + * @return boolean If the operation complete successfully + * @throws ExecutionException If a problem was detected in the operation + */ + public static boolean copyRecursive( + final File src, final File dst, int bufferSize) throws ExecutionException { + if (src.isDirectory()) { + // Create the directory + if (dst.exists() && !dst.isDirectory()) { + Log.e(TAG, + String.format("Failed to check destionation dir: %s", dst)); //$NON-NLS-1$ + throw new ExecutionException("the path exists but is not a folder"); //$NON-NLS-1$ + } + if (!dst.exists()) { + if (!dst.mkdir()) { + Log.e(TAG, String.format("Failed to create directory: %s", dst)); //$NON-NLS-1$ + return false; + } + } + File[] files = src.listFiles(); + if (files != null) { + for (int i = 0; i < files.length; i++) { + if (!copyRecursive(files[i], new File(dst, files[i].getName()), bufferSize)) { + return false; + } + } + } + } else { + // Copy the directory + if (!bufferedCopy(src, dst,bufferSize)) { + return false; + } + } + return true; + } + + /** + * Method that copies a file + * + * @param src The source file + * @param dst The destination file + * @param bufferSize The buffer size for the operation + * @return boolean If the operation complete successfully + */ + public static boolean bufferedCopy(final File src, final File dst, int bufferSize) { + BufferedInputStream bis = null; + BufferedOutputStream bos = null; + try { + bis = new BufferedInputStream(new FileInputStream(src), bufferSize); + bos = new BufferedOutputStream(new FileOutputStream(dst), bufferSize); + int read = 0; + byte[] data = new byte[bufferSize]; + while ((read = bis.read(data, 0, bufferSize)) != -1) { + bos.write(data, 0, read); + } + return true; + + } catch (Throwable e) { + Log.e(TAG, + String.format(TAG, "Failed to copy from %s to %d", src, dst), e); //$NON-NLS-1$ + return false; + } finally { + try { + if (bis != null) { + bis.close(); + } + } catch (Throwable e) {/**NON BLOCK**/} + try { + if (bos != null) { + bos.close(); + } + } catch (Throwable e) {/**NON BLOCK**/} + } + } + + /** + * Method that deletes a folder recursively + * + * @param folder The folder to delete + * @return boolean If the folder was deleted + */ + public static boolean deleteFolder(File folder) { + File[] files = folder.listFiles(); + if (files != null) { + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + if (!deleteFolder(files[i])) { + return false; + } + } else { + if (!files[i].delete()) { + return false; + } + } + } + } + return folder.delete(); + } } diff --git a/src/com/cyanogenmod/filemanager/util/MountPointHelper.java b/src/com/cyanogenmod/filemanager/util/MountPointHelper.java index 9703618..a91affa 100644 --- a/src/com/cyanogenmod/filemanager/util/MountPointHelper.java +++ b/src/com/cyanogenmod/filemanager/util/MountPointHelper.java @@ -45,6 +45,11 @@ public final class MountPointHelper { "ext4" //$NON-NLS-1$ }); + private static final long MAX_CACHED_TIME = 60000L * 5; + + private static List<MountPoint> sMountPoints; + private static long sLastCachedTime; + /** * Constructor of <code>MountPointHelper</code>. */ @@ -84,15 +89,25 @@ public final class MountPointHelper { * @param dir The directory of which recovers his mount point information * @return MountPoint The mount point information */ - public static MountPoint getMountPointFromDirectory(Console console, String dir) { + public synchronized static MountPoint getMountPointFromDirectory(Console console, String dir) { try { - //Retrieve the mount points - List<MountPoint> mps = - CommandHelper.getMountPoints(null, console); + // For non-rooted devices, which console is java and runs under a chrooted + // device, mount point info mustn't be a main objective. Caching the status + // should be enough and operation runs smoothly. + // Refresh mount points after some time (5 minutes should be enough) + long now = System.currentTimeMillis(); + if (sMountPoints == null || (now - sLastCachedTime) > MAX_CACHED_TIME || + FileManagerApplication.isDeviceRooted()) { + //Retrieve the mount points + List<MountPoint> mps = + CommandHelper.getMountPoints(null, console); + sMountPoints = mps; + sLastCachedTime = now; + } //Sort mount points in reverse order, needed for avoid //found an incorrect that matches the name - Collections.sort(mps, new Comparator<MountPoint>() { + Collections.sort(sMountPoints, new Comparator<MountPoint>() { @Override public int compare(MountPoint lhs, MountPoint rhs) { return lhs.compareTo(rhs) * -1; @@ -100,9 +115,9 @@ public final class MountPointHelper { }); //Search for the mount point information - int cc = mps.size(); + int cc = sMountPoints.size(); for (int i = 0; i < cc; i++) { - MountPoint mp = mps.get(i); + MountPoint mp = sMountPoints.get(i); if (dir.startsWith(mp.getMountPoint())) { return mp; } |
