OSDN Git Service

cmfm: allow prompt console without su command
authorJorge Ruesga <jorge@ruesga.com>
Fri, 21 Nov 2014 01:03:36 +0000 (02:03 +0100)
committerJorge Ruesga <jorge@ruesga.com>
Fri, 21 Nov 2014 01:03:36 +0000 (02:03 +0100)
Separete shell console commands from su command. This allow to create a shell
console when su command is not present. A warning will be displayed is root
mode is trying to be selected or a elevated operation is required.

Change-Id: I27a2e850aec87026c8dd4b3baacf7ebd0f897a1a
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
res/values/overlay.xml
res/values/strings.xml
src/com/cyanogenmod/filemanager/FileManagerApplication.java
src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
src/com/cyanogenmod/filemanager/activities/preferences/GeneralPreferenceFragment.java
src/com/cyanogenmod/filemanager/console/ConsoleBuilder.java
src/com/cyanogenmod/filemanager/util/ExceptionUtil.java
src/com/cyanogenmod/filemanager/util/MountPointHelper.java

index 88c5d68..6b624ad 100644 (file)
         /system/xbin/pwd,
         /system/xbin/readlink,
         /system/xbin/stat,
-        /system/xbin/su,
         /system/xbin/tar,
         /system/xbin/xargs,
         /system/xbin/md5sum,
         /system/xbin/sha1sum
     </string>
 
+    <!-- The root command -->
+    <string name="root_command" translatable="false">/system/xbin/su</string>
+
     <!-- Optional shell commands in a pair=value format -->
     <string name="shell_optional_commands" translatable="false">
         zip=/system/xbin/zip,
index dc79bc0..766f4fd 100644 (file)
@@ -93,6 +93,8 @@
     <string name="msgs_settings_save_failure">The setting could not be applied or stored.</string>
     <!-- The initial directory has an invalid or inaccessible reference -->
     <string name="msgs_settings_invalid_initial_directory">The initial folder \'<xliff:g id="initial_dir">%1$s</xliff:g>\' is invalid. Changing to root folder.</string>
+    <!-- Root is not available message -->
+    <string name="root_not_available_msg">Root is not available in this device. Cannot perform this operation.</string>
 
     <!-- Success -->
     <string name="msgs_success">The operation was completed successfully.</string>
index 8230c1f..ebf369a 100644 (file)
@@ -71,6 +71,7 @@ public final class FileManagerApplication extends Application {
     private static ConsoleHolder sBackgroundConsole;
 
     private static boolean sIsDebuggable = false;
+    private static boolean sHasShellCommands = false;
     private static boolean sIsDeviceRooted = false;
 
     private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
@@ -237,8 +238,9 @@ public final class FileManagerApplication extends Application {
         // Check if the application is debuggable
         sIsDebuggable = (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE));
 
-        // Check if the device is rooted
-        sIsDeviceRooted = areShellCommandsPresent();
+        // Check if the device has shell commands and if is rooted
+        sHasShellCommands = areShellCommandsPresent();
+        sIsDeviceRooted = isRootPresent();
 
         // Check optional commands
         loadOptionalCommands();
@@ -312,6 +314,15 @@ public final class FileManagerApplication extends Application {
     }
 
     /**
+     * Method that returns if the device has all the required shell commands
+     *
+     * @return boolean If the device has all the required shell commands
+     */
+    public static boolean hasShellCommands() {
+        return sHasShellCommands;
+    }
+
+    /**
      * Method that returns if a command is present in the system
      *
      * @param commandId The command key
@@ -430,7 +441,7 @@ public final class FileManagerApplication extends Application {
      * @return boolean If the access mode of the application
      */
     public static AccessMode getAccessMode() {
-        if (!sIsDeviceRooted) {
+        if (!sHasShellCommands) {
             return AccessMode.SAFE;
         }
         String defaultValue =
@@ -531,6 +542,32 @@ public final class FileManagerApplication extends Application {
         return false;
     }
 
+    /**
+     * Method that check if root command are present in the device
+     *
+     * @return boolean True if root command is present
+     */
+    private boolean isRootPresent() {
+        try {
+            String rootCommand = getString(R.string.root_command);
+            File cmd = new File(rootCommand);
+            if (!cmd.exists() || !cmd.isFile()) {
+                Log.w(TAG,
+                        String.format(
+                                "Command %s not found. Exists: %s; IsFile: %s.", //$NON-NLS-1$
+                                rootCommand,
+                                String.valueOf(cmd.exists()),
+                                String.valueOf(cmd.isFile())));
+                return false;
+            }
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG,
+                    "Failed to read root command.", e); //$NON-NLS-1$
+        }
+        return false;
+    }
+
     @SuppressWarnings("boxing")
     private void loadOptionalCommands() {
         try {
index d23acc6..4728d5d 100644 (file)
@@ -658,7 +658,7 @@ public class NavigationActivity extends Activity
                 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
 
         //Display the welcome message?
-        if (firstUse && FileManagerApplication.isDeviceRooted()) {
+        if (firstUse && FileManagerApplication.hasShellCommands()) {
             // open navigation drawer to show user that it exists
             mDrawerLayout.openDrawer(mDrawer);
 
index 8c5c991..e578dc6 100644 (file)
@@ -26,6 +26,7 @@ import android.preference.Preference;
 import android.preference.PreferenceCategory;
 import android.preference.Preference.OnPreferenceChangeListener;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.cyanogenmod.filemanager.FileManagerApplication;
 import com.cyanogenmod.filemanager.R;
@@ -35,6 +36,7 @@ import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
 import com.cyanogenmod.filemanager.preferences.ObjectStringIdentifier;
 import com.cyanogenmod.filemanager.preferences.Preferences;
 import com.cyanogenmod.filemanager.util.AndroidHelper;
+import com.cyanogenmod.filemanager.util.DialogHelper;
 
 /**
  * A class that manages the commons options of the application
@@ -101,6 +103,14 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment {
                 String value = (String)newValue;
                 AccessMode oldMode = FileManagerApplication.getAccessMode();
                 AccessMode newMode = AccessMode.fromId(value);
+
+                // Denied change to root if su command is not present
+                if (newMode.compareTo(AccessMode.ROOT) == 0 &&
+                        !FileManagerApplication.isDeviceRooted()) {
+                    DialogHelper.showToast(activity, R.string.root_not_available_msg,
+                            Toast.LENGTH_SHORT);
+                    return false;
+                }
                 if (oldMode.compareTo(newMode) != 0) {
                     // The mode was changes. Change the console
                     if (newMode.compareTo(AccessMode.ROOT) == 0) {
@@ -256,8 +266,8 @@ public class GeneralPreferenceFragment extends TitlePreferenceFragment {
         final Context context = getActivity();
         boolean restrictedAccess = AndroidHelper.isSecondaryUser(context) &&
                 FileManagerApplication.isRestrictSecondaryUsersAccess(context);
-        this.mAccessMode.setEnabled(FileManagerApplication.isDeviceRooted() && !restrictedAccess);
-        if (!FileManagerApplication.isDeviceRooted()) {
+        this.mAccessMode.setEnabled(FileManagerApplication.hasShellCommands() && !restrictedAccess);
+        if (!FileManagerApplication.hasShellCommands()) {
             PreferenceCategory category = (PreferenceCategory) findPreference(
                     "general_advanced_settings");
             category.removePreference(mAccessMode);
index 51f2981..f5f7cdd 100644 (file)
@@ -291,7 +291,7 @@ public final class ConsoleBuilder {
         int bufferSize = context.getResources().getInteger(R.integer.buffer_size);
 
         // Is rooted? Then create a shell console
-        if (FileManagerApplication.isDeviceRooted()) {
+        if (FileManagerApplication.hasShellCommands()) {
             NonPriviledgeConsole console = new NonPriviledgeConsole();
             console.setBufferSize(bufferSize);
             console.alloc();
index 7b7ce74..edd876a 100644 (file)
@@ -285,6 +285,17 @@ public final class ExceptionUtil {
             }
             return;
         }
+        if (relaunchable instanceof InsufficientPermissionsException &&
+                !FileManagerApplication.isDeviceRooted()) {
+            DialogHelper.showToast(context, R.string.root_not_available_msg,
+                    Toast.LENGTH_SHORT);
+
+            // Operation failed. Root is not available
+            if (listener != null) {
+                listener.onFailed(relaunchable);
+            }
+            return;
+        }
 
         //Create a yes/no dialog and ask the user
         final DialogInterface.OnClickListener clickListener =
index e2e7b4c..d63c1b5 100644 (file)
@@ -97,7 +97,7 @@ public final class MountPointHelper {
             // 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()) {
+                FileManagerApplication.hasShellCommands()) {
                 //Retrieve the mount points
                 List<MountPoint> mps =
                         CommandHelper.getMountPoints(null, console);