OSDN Git Service

most devices dont support rm -f
[android-x86/external-koush-Superuser.git] / Superuser / src / com / koushikdutta / superuser / MainActivity.java
1 /*
2  * Copyright (C) 2013 Koushik Dutta (@koush)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.koushikdutta.superuser;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.zip.ZipEntry;
25 import java.util.zip.ZipFile;
26 import java.util.zip.ZipOutputStream;
27
28 import android.app.AlertDialog;
29 import android.app.ProgressDialog;
30 import android.content.DialogInterface;
31 import android.content.DialogInterface.OnClickListener;
32 import android.os.Bundle;
33 import android.util.Log;
34 import android.view.Menu;
35 import android.view.MenuItem;
36 import android.view.MenuItem.OnMenuItemClickListener;
37
38 import com.koushikdutta.superuser.util.Settings;
39 import com.koushikdutta.superuser.util.StreamUtility;
40 import com.koushikdutta.widgets.BetterListActivity;
41
42 public class MainActivity extends BetterListActivity {
43     public MainActivity() {
44         super(PolicyFragment.class);
45     }
46
47     public PolicyFragmentInternal getFragment() {
48         return (PolicyFragmentInternal)super.getFragment();
49     }
50     
51     @Override
52     public boolean onCreateOptionsMenu(Menu menu) {
53         MenuItem about = menu.add(R.string.about);
54         about.setOnMenuItemClickListener(new OnMenuItemClickListener() {
55             @Override
56             public boolean onMenuItemClick(MenuItem item) {
57                 getFragment().setContent(new AboutFragment(), true, getString(R.string.about));
58                 return true;
59             }
60         });
61         
62         return super.onCreateOptionsMenu(menu);
63     }
64     
65     void doRecoveryInstall() {
66         final ProgressDialog dlg = new ProgressDialog(this);
67         dlg.setTitle(R.string.installing);
68         dlg.setMessage(getString(R.string.installing_superuser));
69         dlg.setIndeterminate(true);
70         dlg.show();
71         new Thread() {
72             void doEntry(ZipOutputStream zout, String entryName, String dest) throws IOException {
73                 ZipFile zf = new ZipFile(getPackageCodePath());
74                 ZipEntry ze = zf.getEntry(entryName);
75                 zout.putNextEntry(new ZipEntry(dest));
76                 InputStream in;
77                 StreamUtility.copyStream(in = zf.getInputStream(ze), zout);
78                 zout.closeEntry();
79                 in.close();
80                 zf.close();
81             }
82             
83             public void run() {
84                 try {
85                     File zip = getFileStreamPath("superuser.zip");
86                     ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zip));
87                     doEntry(zout, "assets/update-binary", "META-INF/com/google/android/update-binary");
88                     zout.close();
89
90                     final File libsu = new File(getApplicationInfo().dataDir, "lib/libsu.so");
91                     if (!libsu.exists())
92                         throw new Exception(libsu.getAbsolutePath() + " not found");
93
94                     String command =
95                             String.format("cat %s > /cache/superuser.zip\n", zip.getAbsolutePath()) +
96                             String.format("cat %s > /cache/su\n", libsu.getAbsolutePath()) +
97                             String.format("cat %s > /cache/Superuser.apk\n", getPackageCodePath()) +
98                             "mkdir /cache/recovery\n" +
99                             "echo '--update_package=CACHE:superuser.zip' > /cache/recovery/command\n" +
100                             "chmod 644 /cache/superuser.zip\n" +
101                             "chmod 644 /cache/recovery/command\n" +
102                             "sync\n" +
103                             "reboot recovery\n";
104                     Process p = Runtime.getRuntime().exec("su");
105                     p.getOutputStream().write(command.getBytes());
106                     p.getOutputStream().close();
107                     if (p.waitFor() != 0)
108                         throw new Exception("non zero result");
109                 }
110                 catch (Exception ex) {
111                     ex.printStackTrace();
112                     dlg.dismiss();
113
114                     runOnUiThread(new Runnable() {
115                         @Override
116                         public void run() {
117                             AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
118                             builder.setPositiveButton(android.R.string.ok, null);
119                             builder.setTitle(R.string.install);
120                             builder.setMessage(R.string.install_error);
121                             builder.create().show();
122                         }
123                     });
124                 }
125             }
126         }.start();
127     }
128     
129     void doSystemInstall() {
130         final ProgressDialog dlg = new ProgressDialog(this);
131         dlg.setTitle(R.string.installing);
132         dlg.setMessage(getString(R.string.installing_superuser));
133         dlg.setIndeterminate(true);
134         dlg.show();
135         final File libsu = new File(getApplicationInfo().dataDir, "lib/libsu.so");
136         final String command =
137                 "mount -orw,remount /system\n" +
138                 "rm /system/xbin/su\n" +
139                 "rm /system/bin/su\n" +
140                 "rm /system/app/Supersu.*\n" +
141                 "rm /system/app/superuser.*\n" +
142                 "rm /system/app/supersu.*\n" +
143                 "rm /system/app/SuperUser.*\n" +
144                 "rm /system/app/SuperSU.*\n" +
145                 String.format("cat %s > /system/xbin/su\n", libsu.getAbsolutePath()) +
146                 "chmod 6777 /system/xbin/su\n" +
147                 "ln -s /system/xbin/su /system/bin/su\n" +
148                 "mount -oro,remount /system\n" +
149                 "sync\n";
150         new Thread() {
151             public void run() {
152                 boolean _error = false;
153                 try {
154                     if (!libsu.exists())
155                         throw new Exception(libsu.getAbsolutePath() + " not found");
156                     Process p = Runtime.getRuntime().exec("su");
157                     p.getOutputStream().write(command.getBytes());
158                     p.getOutputStream().close();
159                     if (p.waitFor() != 0)
160                         throw new Exception("non zero result");
161                     checkSu();
162                 }
163                 catch (Exception ex) {
164                     _error = true;
165                     ex.printStackTrace();
166                 }
167                 dlg.dismiss();
168                 final boolean error = _error;
169                 runOnUiThread(new Runnable() {
170                     @Override
171                     public void run() {
172                         AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
173                         builder.setPositiveButton(android.R.string.ok, null);
174                         builder.setTitle(R.string.install);
175                         
176                         if (error) {
177                             builder.setMessage(R.string.install_error);
178                         }
179                         else {
180                             builder.setMessage(R.string.install_success);
181                         }
182                         builder.create().show();
183                     }
184                 });
185             };
186         }.start();
187     }
188     
189     void doInstall() {
190         AlertDialog.Builder builder = new AlertDialog.Builder(this);
191         builder.setTitle(R.string.install);
192         builder.setMessage(R.string.install_superuser_info);
193         builder.setPositiveButton(R.string.install, new OnClickListener() {
194             @Override
195             public void onClick(DialogInterface dialog, int which) {
196                 doSystemInstall();
197             }
198         });
199         builder.setNegativeButton(android.R.string.cancel, null);
200         builder.setNeutralButton(R.string.recovery_install, new OnClickListener() {
201             @Override
202             public void onClick(DialogInterface dialog, int which) {
203                 doRecoveryInstall();
204             }
205         });
206         builder.create().show();
207     }
208     
209     void checkSu() throws Exception {
210         Process p = Runtime.getRuntime().exec("su -v");
211         String result = Settings.readToEnd(p.getInputStream());
212         Log.i("Superuser", "Result: " + result);
213         if (0 != p.waitFor())
214             throw new Exception("non zero result");
215         if (result == null)
216             throw new Exception("no data");
217         if (!result.contains(getPackageName()))
218             throw new Exception("unknown su");
219         // TODO: upgrades herp derp
220     }
221
222     @Override
223     protected void onCreate(Bundle savedInstanceState) {
224         super.onCreate(savedInstanceState);
225         
226         final ProgressDialog dlg = new ProgressDialog(this);
227         dlg.setTitle(R.string.superuser);
228         dlg.setMessage(getString(R.string.checking_superuser));
229         dlg.setIndeterminate(true);
230         dlg.show();
231         new Thread() {
232             public void run() {
233                 boolean error = false;
234                 try {
235                     checkSu();
236                 }
237                 catch (Exception e) {
238                     e.printStackTrace();
239                     error = true;
240                 }
241                 dlg.dismiss();
242                 if (error) {
243                     runOnUiThread(new Runnable() {
244                         @Override
245                         public void run() {
246                             doInstall();
247                         }
248                     });
249                 }
250             };
251         }.start();
252     }
253 }