├── .idea ├── .name ├── copyright │ └── profiles_settings.xml ├── scopes │ └── scope_settings.xml ├── encodings.xml ├── vcs.xml ├── modules.xml ├── misc.xml ├── compiler.xml └── workspace.xml ├── assets └── .gitignore ├── libs └── android-support-v4.jar ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── values │ └── strings.xml └── layout │ └── main.xml ├── .gitignore ├── project.properties ├── .classpath ├── Safestrap.iml ├── AndroidManifest.xml ├── .project ├── proguard.cfg └── src └── com └── hashcode └── safestrap └── ics ├── UninstallDialogThread.java ├── InstallDialogThread.java ├── ExecuteAsRootBase.java ├── AssetControl.java └── SafestrapActivity.java /.idea/.name: -------------------------------------------------------------------------------- 1 | Safestrap -------------------------------------------------------------------------------- /assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stargo/android_packages_apps_Safestrap/HEAD/libs/android-support-v4.jar -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stargo/android_packages_apps_Safestrap/HEAD/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stargo/android_packages_apps_Safestrap/HEAD/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stargo/android_packages_apps_Safestrap/HEAD/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stargo/android_packages_apps_Safestrap/HEAD/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stargo/android_packages_apps_Safestrap/HEAD/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | bin/ 12 | gen/ 13 | out/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-19 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Safestrap.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Safestrap 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Safestrap 4 | Install Recovery 5 | Uninstall Recovery 6 | Reboot to Recovery 7 | Upgrade Recovery 8 | State: 9 | Installed 10 | Not Installed 11 | Safe System: 12 | Not Active 13 | Recovery Disabled 14 | 15 | 3.75 16 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 17 | #66FF99 18 | #FF0000 19 | #FFFF00 20 | Reboot to Write Protect Off Mode 21 | 22 | -------------------------------------------------------------------------------- /src/com/hashcode/safestrap/ics/UninstallDialogThread.java: -------------------------------------------------------------------------------- 1 | package com.hashcode.safestrap.ics; 2 | 3 | import java.io.File; 4 | 5 | import android.os.Handler; 6 | import android.os.Message; 7 | 8 | public class UninstallDialogThread extends Thread implements Runnable { 9 | public Handler handler = null; 10 | public String packageCodePath = ""; 11 | public File mAppRoot = null; 12 | public String LOGTAG = ""; 13 | 14 | protected void pause(int milli) { 15 | try { 16 | Thread.sleep(milli); 17 | } 18 | catch(Exception ex) { } 19 | } 20 | 21 | protected void reply(int arg1, int arg2, String text) { 22 | Message msg = new Message(); 23 | msg.arg1 = arg1; 24 | msg.arg2 = arg2; 25 | msg.obj = (Object)text; 26 | if (handler != null) { handler.sendMessage(msg); } 27 | } 28 | 29 | @Override 30 | public void run() { 31 | try { 32 | reply(1,0,"Preparing Uninstall..."); 33 | pause(2000); 34 | AssetControl unzip = new AssetControl(); 35 | unzip.apkPath= packageCodePath; 36 | unzip.mAppRoot = mAppRoot.toString(); 37 | unzip.LOGTAG = LOGTAG; 38 | reply(1,0,"Unpacking Files..."); 39 | unzip.unzipAssets(); 40 | reply(1,50,"Checking Busybox..."); 41 | String filesDir = mAppRoot.getAbsolutePath(); 42 | ExecuteAsRootBase.executecmd("chmod 755 " + filesDir + "/busybox"); 43 | ExecuteAsRootBase.executecmd("chmod 755 " + filesDir + "/*.sh"); 44 | reply(1,60,"Uninstalling..."); 45 | ExecuteAsRootBase.executecmd("sh " + filesDir + "/recovery-uninstall.sh " + filesDir); 46 | reply(1,90,"Cleaning Up..."); 47 | ExecuteAsRootBase.executecmd(filesDir + "/busybox rm -r " + filesDir + "/install-files"); 48 | reply(0,0,"Uninstall Complete."); 49 | } 50 | catch(Exception ex) { 51 | reply(0,1,ex.getMessage()); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hashcode/safestrap/ics/InstallDialogThread.java: -------------------------------------------------------------------------------- 1 | package com.hashcode.safestrap.ics; 2 | 3 | import java.io.File; 4 | 5 | import android.os.Handler; 6 | import android.os.Message; 7 | 8 | public class InstallDialogThread extends Thread { 9 | 10 | 11 | public Handler handler = null; 12 | public String packageCodePath = ""; 13 | public File mAppRoot = null; 14 | public String LOGTAG = ""; 15 | 16 | protected void pause(int milli) { 17 | try { 18 | Thread.sleep(milli); 19 | } 20 | catch(Exception ex) { } 21 | } 22 | 23 | protected void reply(int arg1, int arg2, String text) { 24 | Message msg = new Message(); 25 | msg.arg1 = arg1; 26 | msg.arg2 = arg2; 27 | msg.obj = (Object)text; 28 | if (handler != null) { handler.sendMessage(msg); } 29 | } 30 | 31 | @Override 32 | public void run() { 33 | try { 34 | reply(1,0,"Preparing Installation..."); 35 | pause(2000); 36 | AssetControl unzip = new AssetControl(); 37 | unzip.apkPath= packageCodePath; 38 | unzip.mAppRoot = mAppRoot.toString(); 39 | unzip.LOGTAG = LOGTAG; 40 | reply(1,0,"Unpacking Files..."); 41 | unzip.unzipAssets(); 42 | reply(1,50,"Checking Busybox..."); 43 | String filesDir = mAppRoot.getAbsolutePath(); 44 | ExecuteAsRootBase.executecmd("chmod 755 " + filesDir + "/busybox"); 45 | ExecuteAsRootBase.executecmd("chmod 755 " + filesDir + "/*.sh"); 46 | reply(1,60,"Running Installation Script..."); 47 | ExecuteAsRootBase.executecmd("sh " + filesDir + "/recovery-install.sh " + filesDir); 48 | reply(1,90,"Cleaning Up..."); 49 | ExecuteAsRootBase.executecmd(filesDir + "/busybox rm -r " + filesDir + "/install-files"); 50 | pause(1000); 51 | reply(0,0,"Installation Complete."); 52 | } 53 | catch(Exception ex) { 54 | reply(0,1,ex.getMessage()); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/com/hashcode/safestrap/ics/ExecuteAsRootBase.java: -------------------------------------------------------------------------------- 1 | package com.hashcode.safestrap.ics; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStreamWriter; 8 | import java.util.ArrayList; 9 | import android.util.Log; 10 | 11 | public abstract class ExecuteAsRootBase 12 | { 13 | public static boolean canRunRootCommands() 14 | { 15 | boolean retval = false; 16 | Process suProcess; 17 | 18 | try 19 | { 20 | suProcess = Runtime.getRuntime().exec("su"); 21 | 22 | DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); 23 | BufferedReader osRes = new BufferedReader(new InputStreamReader(suProcess.getInputStream())); 24 | 25 | if (null != os && null != osRes) 26 | { 27 | // Getting the id of the current user to check if this is root 28 | os.writeBytes("id\n"); 29 | os.flush(); 30 | 31 | String currUid = osRes.readLine(); 32 | boolean exitSu = false; 33 | if (null == currUid) 34 | { 35 | retval = false; 36 | exitSu = false; 37 | Log.d("ROOT", "Can't get root access or denied by user"); 38 | } 39 | else if (true == currUid.contains("uid=0")) 40 | { 41 | retval = true; 42 | exitSu = true; 43 | Log.d("ROOT", "Root access granted"); 44 | } 45 | else 46 | { 47 | retval = false; 48 | exitSu = true; 49 | Log.d("ROOT", "Root access rejected: " + currUid); 50 | } 51 | 52 | if (exitSu) 53 | { 54 | os.writeBytes("exit\n"); 55 | os.flush(); 56 | } 57 | } 58 | } 59 | catch (Exception e) 60 | { 61 | // Can't get root ! 62 | // Probably broken pipe exception on trying to write to output stream (os) after su failed, meaning that the device is not rooted 63 | 64 | retval = false; 65 | Log.d("ROOT", "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage()); 66 | } 67 | 68 | return retval; 69 | } 70 | 71 | public static final String executecmd(String cmd) { 72 | String result = ""; 73 | try { 74 | Process zuul = Runtime.getRuntime().exec("su"); 75 | OutputStreamWriter osw = new OutputStreamWriter(zuul.getOutputStream()); 76 | osw.write(cmd + "\n"); 77 | osw.flush(); 78 | osw.close(); 79 | BufferedReader in = new BufferedReader(new InputStreamReader(zuul.getInputStream())); 80 | if (in != null) { result = in.readLine(); } 81 | } catch(Exception e){ e.printStackTrace(); } 82 | return result; 83 | } 84 | 85 | public final boolean execute() 86 | { 87 | boolean retval = false; 88 | 89 | try 90 | { 91 | ArrayList commands = getCommandsToExecute(); 92 | if (null != commands && commands.size() > 0) 93 | { 94 | Process suProcess = Runtime.getRuntime().exec("su"); 95 | 96 | DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); 97 | 98 | // Execute commands that require root access 99 | for (String currCommand : commands) 100 | { 101 | os.writeBytes(currCommand + "\n"); 102 | os.flush(); 103 | } 104 | 105 | os.writeBytes("exit\n"); 106 | os.flush(); 107 | 108 | try 109 | { 110 | int suProcessRetval = suProcess.waitFor(); 111 | if (255 != suProcessRetval) 112 | { 113 | // Root access granted 114 | retval = true; 115 | } 116 | else 117 | { 118 | // Root access denied 119 | retval = false; 120 | } 121 | } 122 | catch (Exception ex) 123 | { 124 | Log.e("Error executing root action", ex.getMessage()); 125 | } 126 | } 127 | } 128 | catch (IOException ex) 129 | { 130 | Log.w("ROOT", "Can't get root access", ex); 131 | } 132 | catch (SecurityException ex) 133 | { 134 | Log.w("ROOT", "Can't get root access", ex); 135 | } 136 | catch (Exception ex) 137 | { 138 | Log.w("ROOT", "Error executing internal operation", ex); 139 | } 140 | 141 | return retval; 142 | } 143 | 144 | protected abstract ArrayList getCommandsToExecute(); 145 | } 146 | -------------------------------------------------------------------------------- /src/com/hashcode/safestrap/ics/AssetControl.java: -------------------------------------------------------------------------------- 1 | package com.hashcode.safestrap.ics; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Enumeration; 9 | import java.util.Vector; 10 | import java.util.zip.ZipEntry; 11 | import java.util.zip.ZipFile; 12 | import android.util.Log; 13 | 14 | public class AssetControl { 15 | public String LOGTAG = "Unknown App"; 16 | public String apkPath = ""; 17 | public String mAppRoot = ""; 18 | final static String ZIP_FILTER = "assets"; 19 | 20 | void unzipAsset(String filename) { 21 | try { 22 | File zipFile = new File(apkPath); 23 | long zipLastModified = zipFile.lastModified(); 24 | ZipFile zip = new ZipFile(apkPath); 25 | Vector files = getAssets(zip); 26 | int zipFilterLength = ZIP_FILTER.length(); 27 | 28 | Enumeration entries = files.elements(); 29 | while (entries.hasMoreElements()) { 30 | ZipEntry entry = (ZipEntry) entries.nextElement(); 31 | String path = entry.getName().substring(zipFilterLength); 32 | if (filename.equals(path)) { 33 | File outputFile = new File(mAppRoot, path); 34 | outputFile.getParentFile().mkdirs(); 35 | 36 | if (outputFile.exists() && entry.getSize() == outputFile.length() && zipLastModified < outputFile.lastModified()) 37 | continue; 38 | FileOutputStream fos = new FileOutputStream(outputFile); 39 | copyStreams(zip.getInputStream(entry), fos); 40 | Runtime.getRuntime().exec("chmod 755 " + outputFile.getAbsolutePath()); 41 | } 42 | } 43 | } catch (IOException e) { 44 | Log.e(LOGTAG, "Error: " + e.getMessage()); 45 | } 46 | } 47 | 48 | void unzipAssets() { 49 | try { 50 | File zipFile = new File(apkPath); 51 | long zipLastModified = zipFile.lastModified(); 52 | ZipFile zip = new ZipFile(apkPath); 53 | Vector files = getAssets(zip); 54 | int zipFilterLength = ZIP_FILTER.length(); 55 | 56 | Enumeration entries = files.elements(); 57 | while (entries.hasMoreElements()) { 58 | ZipEntry entry = (ZipEntry) entries.nextElement(); 59 | String path = entry.getName().substring(zipFilterLength); 60 | File outputFile = new File(mAppRoot, path); 61 | outputFile.getParentFile().mkdirs(); 62 | 63 | if (outputFile.exists() && entry.getSize() == outputFile.length() && zipLastModified < outputFile.lastModified()) 64 | continue; 65 | FileOutputStream fos = new FileOutputStream(outputFile); 66 | copyStreams(zip.getInputStream(entry), fos); 67 | Runtime.getRuntime().exec("chmod 755 " + outputFile.getAbsolutePath()); 68 | } 69 | } catch (IOException e) { 70 | Log.e(LOGTAG, "Error: " + e.getMessage()); 71 | } 72 | } 73 | 74 | static final int BUFSIZE = 5192; 75 | 76 | void copyStreams(InputStream is, FileOutputStream fos) { 77 | BufferedOutputStream os = null; 78 | try { 79 | byte data[] = new byte[BUFSIZE]; 80 | int count; 81 | os = new BufferedOutputStream(fos, BUFSIZE); 82 | while ((count = is.read(data, 0, BUFSIZE)) != -1) { 83 | os.write(data, 0, count); 84 | } 85 | os.flush(); 86 | } catch (IOException e) { 87 | Log.e(LOGTAG, "Exception while copying: " + e); 88 | } finally { 89 | try { 90 | if (os != null) { 91 | os.close(); 92 | } 93 | } catch (IOException e2) { 94 | Log.e(LOGTAG, "Exception while closing the stream: " + e2); 95 | } 96 | } 97 | } 98 | 99 | public Vector getAssets(ZipFile zip) { 100 | Vector list = new Vector(); 101 | Enumeration entries = zip.entries(); 102 | while (entries.hasMoreElements()) { 103 | ZipEntry entry = (ZipEntry) entries.nextElement(); 104 | if (entry.getName().startsWith(ZIP_FILTER)) { 105 | list.add(entry); 106 | } 107 | } 108 | return list; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/com/hashcode/safestrap/ics/SafestrapActivity.java: -------------------------------------------------------------------------------- 1 | package com.hashcode.safestrap.ics; 2 | 3 | import com.hashcode.safestrap.R; 4 | import com.hashcode.safestrap.ics.AssetControl; 5 | import com.hashcode.safestrap.ics.ExecuteAsRootBase; 6 | import com.hashcode.safestrap.ics.InstallDialogThread; 7 | import com.hashcode.safestrap.ics.UninstallDialogThread; 8 | 9 | import android.app.Activity; 10 | import android.app.AlertDialog; 11 | import android.app.Dialog; 12 | import android.app.ProgressDialog; 13 | import android.content.DialogInterface; 14 | import android.content.SharedPreferences; 15 | import android.os.Bundle; 16 | import android.os.Handler; 17 | import android.os.Message; 18 | import android.view.View; 19 | import android.widget.Button; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import java.util.Properties; 24 | 25 | public class SafestrapActivity extends Activity { 26 | final static public String PREFS_NAME = "disclaimer"; 27 | 28 | private TextView statusText = null; 29 | private TextView messageText = null; 30 | private TextView textSystemStatus = null; 31 | private Button buttonInstall = null; 32 | private Button buttonUninstall = null; 33 | private Button buttonReboot = null; 34 | private Button buttonRebootWriteProtect = null; 35 | private InstallDialogThread installDialogThread = null; 36 | private UninstallDialogThread uninstallDialogThread = null; 37 | private ProgressDialog pDialog = null; 38 | private Boolean rootCheck = false; 39 | private Boolean writeProtect = false; 40 | 41 | /** Setup the Widgets */ 42 | protected void setupControls() { 43 | /* Setup button */ 44 | try { 45 | buttonRebootWriteProtect.setVisibility(View.GONE); 46 | if (rootCheck) { 47 | /* Check Version */ 48 | String inText = ExecuteAsRootBase.executecmd("sh " + getFilesDir().toString() + "/recovery-check.sh " + getFilesDir().toString()); 49 | String parts[] = inText.split(":"); 50 | String vers_s = null; 51 | float vers = 0; 52 | Boolean altbootmode = false; 53 | if (parts != null) { 54 | if (parts.length >= 1) { vers_s = parts[0]; } 55 | if (parts.length >= 2) { 56 | if (parts[1].equals("1")) 57 | altbootmode = true; 58 | } 59 | if (parts.length >=3) { 60 | if (parts[2].equals("1")) { 61 | writeProtect = true; 62 | } 63 | } 64 | } 65 | if (vers_s != null) { 66 | vers = Float.valueOf(vers_s); 67 | } 68 | buttonUninstall.setEnabled(true); 69 | buttonInstall.setEnabled(true); 70 | buttonReboot.setEnabled(true); 71 | if (vers == 0) { 72 | statusText.setText("Not installed"); 73 | buttonReboot.setEnabled(false); 74 | } else { 75 | float check_vers = Float.valueOf(this.getString(R.string.version)); 76 | if (vers == check_vers) { 77 | statusText.setText("Installed"); 78 | } else if (vers > check_vers) { 79 | statusText.setText("Newer Version Installed"); 80 | buttonInstall.setEnabled(false); 81 | } else { 82 | statusText.setText("Old Version"); 83 | } 84 | } 85 | textSystemStatus.setText("Not Active"); 86 | /* setMessage(check); */ 87 | if (altbootmode) { 88 | textSystemStatus.setText("Active"); 89 | } 90 | if (writeProtect) { 91 | statusText.setText("Write Protect Enabled"); 92 | buttonUninstall.setEnabled(false); 93 | buttonInstall.setEnabled(false); 94 | buttonReboot.setEnabled(true); 95 | buttonRebootWriteProtect.setVisibility(View.VISIBLE); 96 | } 97 | } 98 | else { 99 | statusText.setText("Not Rooted"); 100 | buttonUninstall.setEnabled(false); 101 | buttonInstall.setEnabled(false); 102 | buttonReboot.setEnabled(false); 103 | } 104 | } 105 | finally { 106 | } 107 | } 108 | 109 | protected Dialog onCreateDialog(int id) { 110 | // show disclaimer.... 111 | // for example, you can show a dialog box... 112 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 113 | builder.setMessage(R.string.disclaimer); 114 | builder.setCancelable(false); 115 | builder.setPositiveButton("Agree", new DialogInterface.OnClickListener() { 116 | public void onClick(DialogInterface dialog, int id) { 117 | // and, if the user accept, you can execute something like this: 118 | // We need an Editor object to make preference changes. 119 | // All objects are from android.context.Context 120 | SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); 121 | SharedPreferences.Editor editor = settings.edit(); 122 | editor.putBoolean("accepted", true); 123 | // Commit the edits! 124 | editor.commit(); 125 | } 126 | }) 127 | .setNegativeButton("Disagree", new DialogInterface.OnClickListener() { 128 | public void onClick(DialogInterface dialog, int id) { 129 | //nm.cancel(R.notification.running); // cancel the NotificationManager (icon) 130 | System.exit(0); 131 | } 132 | }); 133 | AlertDialog alert = builder.create(); 134 | return alert; 135 | } 136 | 137 | /** Called when the activity is first created. */ 138 | @Override 139 | public void onCreate(Bundle savedInstanceState) { 140 | statusText = (TextView)findViewById(R.id.textInstallStatus); 141 | super.onCreate(savedInstanceState); 142 | setContentView(R.layout.main); 143 | 144 | SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); 145 | if ( settings.getBoolean("accepted", false) == false ) { 146 | showDialog(0); 147 | } 148 | 149 | buttonInstall = (Button)findViewById(R.id.buttonInstall); 150 | buttonUninstall = (Button)findViewById(R.id.buttonUninstall); 151 | buttonReboot = (Button)findViewById(R.id.buttonReboot); 152 | buttonRebootWriteProtect = (Button)findViewById(R.id.buttonRebootWriteProtect); 153 | statusText = (TextView)findViewById(R.id.textInstallStatus); 154 | messageText = (TextView)findViewById(R.id.textView1); 155 | textSystemStatus = (TextView)findViewById(R.id.textSystemStatus); 156 | 157 | rootCheck = ExecuteAsRootBase.canRunRootCommands(); 158 | if (rootCheck) { 159 | /* For new MotoX we need to check write_protect=1 in cmdline */ 160 | AssetControl unzip = new AssetControl(); 161 | unzip.apkPath= getPackageCodePath(); 162 | unzip.mAppRoot = getFilesDir().toString(); 163 | unzip.unzipAsset("/busybox"); 164 | unzip.unzipAsset("/recovery-check.sh"); 165 | unzip.unzipAsset("/recovery-reboot.sh"); 166 | unzip.unzipAsset("/ss_function.sh"); 167 | unzip.unzipAsset("/ss.config"); 168 | unzip = null; 169 | ExecuteAsRootBase.executecmd("chmod 755 " + getFilesDir() + "/busybox"); 170 | ExecuteAsRootBase.executecmd("chmod 755 " + getFilesDir() + "/*.sh"); 171 | 172 | buttonInstall.setOnClickListener(new View.OnClickListener() { 173 | public void onClick(View v) { 174 | try { 175 | pDialog = new ProgressDialog(v.getRootView().getContext()); 176 | pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 177 | pDialog.setMessage("Installing..."); 178 | pDialog.setCancelable(false); 179 | pDialog.show(); 180 | pDialog.getCurrentFocus(); 181 | installDialogThread = new InstallDialogThread(); 182 | installDialogThread.packageCodePath = getPackageCodePath(); 183 | installDialogThread.mAppRoot = getFilesDir(); 184 | installDialogThread.LOGTAG = "Safestrap"; 185 | installDialogThread.handler = new Handler() { 186 | @Override 187 | public void handleMessage(Message msg) { 188 | if (msg.arg1 == 0) { 189 | pDialog.dismiss(); 190 | pDialog = null; 191 | Toast.makeText(buttonInstall.getRootView().getContext(), (String)msg.obj, Toast.LENGTH_LONG).show(); 192 | setupControls(); 193 | } else { 194 | pDialog.setProgress(msg.arg2); 195 | pDialog.setMessage((String)msg.obj); 196 | } 197 | } 198 | }; 199 | installDialogThread.start(); 200 | } catch(Exception ex) { 201 | messageText.setText(ex.getMessage()); 202 | } 203 | } 204 | }); 205 | 206 | buttonUninstall.setOnClickListener(new View.OnClickListener() { 207 | public void onClick(View v) { 208 | try { 209 | pDialog = new ProgressDialog(v.getRootView().getContext()); 210 | pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 211 | pDialog.setMessage("Loading..."); 212 | pDialog.setCancelable(false); 213 | pDialog.show(); 214 | pDialog.getCurrentFocus(); 215 | uninstallDialogThread = new UninstallDialogThread(); 216 | uninstallDialogThread.packageCodePath = getPackageCodePath(); 217 | uninstallDialogThread.mAppRoot = getFilesDir(); 218 | uninstallDialogThread.LOGTAG = "Safestrap"; 219 | uninstallDialogThread.handler = new Handler() { 220 | @Override 221 | public void handleMessage(Message msg) { 222 | if (msg.arg1 == 0) { 223 | pDialog.dismiss(); 224 | pDialog = null; 225 | Toast.makeText(buttonUninstall.getRootView().getContext(), (String)msg.obj, Toast.LENGTH_LONG).show(); 226 | setupControls(); 227 | } else { 228 | pDialog.setProgress(msg.arg2); 229 | pDialog.setMessage((String)msg.obj); 230 | } 231 | } 232 | }; 233 | uninstallDialogThread.start(); 234 | } catch(Exception ex) { 235 | messageText.setText(ex.getMessage()); 236 | } 237 | } 238 | }); 239 | 240 | buttonReboot.setOnClickListener(new View.OnClickListener() { 241 | public void onClick(View v) { 242 | try { 243 | ExecuteAsRootBase.executecmd("sh " + getFilesDir().toString() + "/recovery-reboot.sh " + getFilesDir().toString()); 244 | Runtime.getRuntime().exec(new String[]{"su","-c","reboot now"}); 245 | } catch(Exception ex) { 246 | messageText.setText(ex.getMessage()); 247 | } 248 | } 249 | }); 250 | 251 | buttonRebootWriteProtect.setOnClickListener(new View.OnClickListener() { 252 | public void onClick(View v) { 253 | try { 254 | ExecuteAsRootBase.executecmd("reboot recovery"); 255 | } catch(Exception ex) { 256 | messageText.setText(ex.getMessage()); 257 | } 258 | } 259 | }); 260 | } 261 | 262 | setupControls(); 263 | } 264 | } -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | android-17 12 | 13 | 14 | 15 | 16 | 17 | Galaxy Nexus 18 | @android:style/Theme.DeviceDefault 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 67 | 68 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 126 | 127 | 128 | 129 | 130 | 131 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 169 | 170 | 173 | 174 | 175 | 176 | 179 | 180 | 183 | 184 | 185 | 186 | 189 | 190 | 193 | 194 | 197 | 198 | 201 | 202 | 203 | 204 | 207 | 208 | 211 | 212 | 215 | 216 | 219 | 220 | 221 | 222 | 225 | 226 | 229 | 230 | 233 | 234 | 235 | 236 | 239 | 240 | 243 | 244 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 287 | 288 | 295 | 296 | 297 | 308 | 309 | 322 | 323 | 324 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 358 | 359 | 360 | 376 | 377 | 378 | 379 | 380 | 385 | 386 | 388 | 389 | localhost 390 | 5050 391 | 392 | 393 | 394 | 395 | 396 | 397 | 1368649641987 398 | 1368649641987 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 441 | 442 | 453 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 591 | 592 | 593 | 594 | 595 | 596 | Android 597 | 598 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 614 | 615 | 616 | 617 | 618 | 619 | 1.6 620 | 621 | 626 | 627 | 628 | 629 | 630 | 631 | Safestrap 632 | 633 | 639 | 640 | 641 | 642 | 643 | 644 | Android 4.0 Platform 645 | 646 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | --------------------------------------------------------------------------------