OSDN Git Service

Superuser: UG translation, added Uyghur translation.
[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 android.app.AlertDialog;
20 import android.app.ProgressDialog;
21 import android.content.DialogInterface;
22 import android.content.DialogInterface.OnClickListener;
23 import android.content.Intent;
24 import android.net.Uri;
25 import android.os.Build;
26 import android.os.Bundle;
27 import android.util.Log;
28 import android.view.Menu;
29 import android.view.MenuInflater;
30 import android.view.MenuItem;
31 import android.view.MenuItem.OnMenuItemClickListener;
32
33 import com.koushikdutta.superuser.util.Settings;
34 import com.koushikdutta.superuser.util.StreamUtility;
35 import com.koushikdutta.superuser.util.SuHelper;
36 import com.koushikdutta.widgets.BetterListActivity;
37
38 import java.io.File;
39 import java.io.FileOutputStream;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.util.zip.ZipEntry;
43 import java.util.zip.ZipFile;
44 import java.util.zip.ZipOutputStream;
45
46 public class MainActivity extends BetterListActivity {
47     public MainActivity() {
48         super(PolicyFragment.class);
49     }
50
51     public PolicyFragmentInternal getFragment() {
52         return (PolicyFragmentInternal)super.getFragment();
53     }
54     
55     @Override
56     public boolean onCreateOptionsMenu(Menu menu) {
57         MenuInflater mi = new MenuInflater(this);
58         mi.inflate(R.menu.app, menu);
59         MenuItem about = menu.findItem(R.id.about);
60         about.setOnMenuItemClickListener(new OnMenuItemClickListener() {
61             @Override
62             public boolean onMenuItemClick(MenuItem item) {
63                 getFragment().setContent(new AboutFragment(), true, getString(R.string.about));
64                 return true;
65             }
66         });
67         
68         return super.onCreateOptionsMenu(menu);
69     }
70     
71     File extractSu() throws IOException, InterruptedException {
72         String arch = "armeabi";
73         if (System.getProperty("os.arch").contains("x86") || System.getProperty("os.arch").contains("i686") || System.getProperty("os.arch").contains("i386"))
74             arch = "x86";
75         ZipFile zf = new ZipFile(getPackageCodePath());
76         ZipEntry su = zf.getEntry("assets/" + arch + "/su");
77         InputStream zin = zf.getInputStream(su);
78         File ret = getFileStreamPath("su");
79         FileOutputStream fout = new FileOutputStream(ret);
80         StreamUtility.copyStream(zin, fout);
81         zin.close();
82         zf.close();
83         fout.close();
84         return ret;
85     }
86
87     void doRecoveryInstall() {
88         final ProgressDialog dlg = new ProgressDialog(this);
89         dlg.setTitle(R.string.installing);
90         dlg.setMessage(getString(R.string.installing_superuser));
91         dlg.setIndeterminate(true);
92         dlg.show();
93         new Thread() {
94             void doEntry(ZipOutputStream zout, String entryName, String dest) throws IOException {
95                 ZipFile zf = new ZipFile(getPackageCodePath());
96                 ZipEntry ze = zf.getEntry(entryName);
97                 zout.putNextEntry(new ZipEntry(dest));
98                 InputStream in;
99                 StreamUtility.copyStream(in = zf.getInputStream(ze), zout);
100                 zout.closeEntry();
101                 in.close();
102                 zf.close();
103             }
104             
105             public void run() {
106                 try {
107                     File zip = getFileStreamPath("superuser.zip");
108                     ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zip));
109                     doEntry(zout, "assets/update-binary", "META-INF/com/google/android/update-binary");
110                     doEntry(zout, "assets/install-recovery.sh", "install-recovery.sh");
111                     zout.close();
112
113                     ZipFile zf = new ZipFile(getPackageCodePath());
114                     ZipEntry ze = zf.getEntry("assets/reboot");
115                     InputStream in;
116                     FileOutputStream reboot;
117                     StreamUtility.copyStream(in = zf.getInputStream(ze), reboot = openFileOutput("reboot", MODE_PRIVATE));
118                     reboot.close();
119                     in.close();
120
121                     final File su = extractSu();
122
123                     String command =
124                             String.format("cat %s > /cache/superuser.zip\n", zip.getAbsolutePath()) +
125                             String.format("cat %s > /cache/su\n", su.getAbsolutePath()) +
126                             String.format("cat %s > /cache/Superuser.apk\n", getPackageCodePath()) +
127                             "mkdir /cache/recovery\n" +
128                             "echo '--update_package=CACHE:superuser.zip' > /cache/recovery/command\n" +
129                             "chmod 644 /cache/superuser.zip\n" +
130                             "chmod 644 /cache/recovery/command\n" +
131                             "sync\n" +
132                             String.format("chmod 755 %s\n", getFileStreamPath("reboot").getAbsolutePath()) +
133                             "reboot recovery\n";
134                     Process p = Runtime.getRuntime().exec("su");
135                     p.getOutputStream().write(command.getBytes());
136                     p.getOutputStream().close();
137                     File rebootScript = getFileStreamPath("reboot.sh");
138                     StreamUtility.writeFile(rebootScript, "reboot recovery ; " + getFileStreamPath("reboot").getAbsolutePath() + " recovery ;");
139                     p.waitFor();
140                     Runtime.getRuntime().exec(new String[] { "su", "-c", ". " + rebootScript.getAbsolutePath() });
141                     if (p.waitFor() != 0)
142                         throw new Exception("non zero result");
143                 }
144                 catch (Exception ex) {
145                     ex.printStackTrace();
146                     dlg.dismiss();
147
148                     runOnUiThread(new Runnable() {
149                         @Override
150                         public void run() {
151                             AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
152                             builder.setPositiveButton(android.R.string.ok, null);
153                             builder.setTitle(R.string.install);
154                             builder.setMessage(R.string.install_error);
155                             builder.create().show();
156                         }
157                     });
158                 }
159             }
160         }.start();
161     }
162     
163     void doSystemInstall() {
164         final ProgressDialog dlg = new ProgressDialog(this);
165         dlg.setTitle(R.string.installing);
166         dlg.setMessage(getString(R.string.installing_superuser));
167         dlg.setIndeterminate(true);
168         dlg.show();
169         new Thread() {
170             public void run() {
171                 boolean _error = false;
172                 try {
173                     final File su = extractSu();
174                     final String command =
175                             "mount -orw,remount /system\n" +
176                             "rm /system/xbin/su\n" +
177                             "rm /system/bin/su\n" +
178                             "rm /system/app/Supersu.*\n" +
179                             "rm /system/app/superuser.*\n" +
180                             "rm /system/app/supersu.*\n" +
181                             "rm /system/app/SuperUser.*\n" +
182                             "rm /system/app/SuperSU.*\n" +
183                             String.format("cat %s > /system/xbin/su\n", su.getAbsolutePath()) +
184                             "chmod 6755 /system/xbin/su\n" +
185                             "ln -s /system/xbin/su /system/bin/su\n" +
186                             "mount -oro,remount /system\n" +
187                             "sync\n";
188                     Process p = Runtime.getRuntime().exec("su");
189                     p.getOutputStream().write(command.getBytes());
190                     p.getOutputStream().close();
191                     if (p.waitFor() != 0)
192                         throw new Exception("non zero result");
193                     SuHelper.checkSu(MainActivity.this);
194                 }
195                 catch (Exception ex) {
196                     _error = true;
197                     Log.e("Superuser", "error upgrading", ex);
198                 }
199                 dlg.dismiss();
200                 final boolean error = _error;
201                 runOnUiThread(new Runnable() {
202                     @Override
203                     public void run() {
204                         AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
205                         builder.setPositiveButton(android.R.string.ok, null);
206                         builder.setTitle(R.string.install);
207                         
208                         if (error) {
209                             builder.setMessage(R.string.install_error);
210                         }
211                         else {
212                             builder.setMessage(R.string.install_success);
213                         }
214                         builder.create().show();
215                     }
216                 });
217             };
218         }.start();
219     }
220     
221     void doInstall() {
222         AlertDialog.Builder builder = new AlertDialog.Builder(this);
223         builder.setTitle(R.string.install);
224         builder.setMessage(R.string.install_superuser_info);
225         if (Build.VERSION.SDK_INT < 18) {
226             builder.setPositiveButton(R.string.install, new OnClickListener() {
227                 @Override
228                 public void onClick(DialogInterface dialog, int which) {
229                     doSystemInstall();
230                 }
231             });
232         }
233         builder.setNegativeButton(android.R.string.cancel, null);
234         builder.setNeutralButton(R.string.recovery_install, new OnClickListener() {
235             @Override
236             public void onClick(DialogInterface dialog, int which) {
237                 doRecoveryInstall();
238             }
239         });
240         builder.create().show();
241     }
242     
243     private void saveWhatsNew() {
244         Settings.setString(this, "whats_new", WHATS_NEW);
245     }
246     
247     // this is intentionally not localized as it will change constantly.
248     private static final String WHATS_NEW = "Added support for Android 4.3.";
249     protected void doWhatsNew() {
250         if (WHATS_NEW.equals(Settings.getString(this, "whats_new")))
251             return;
252         saveWhatsNew();
253         AlertDialog.Builder builder = new AlertDialog.Builder(this);
254         builder.setTitle(R.string.whats_new);
255         builder.setIcon(R.drawable.ic_launcher);
256         builder.setMessage(WHATS_NEW);
257         builder.setPositiveButton(R.string.rate, new OnClickListener() {
258             @Override
259             public void onClick(DialogInterface dialog, int which) {
260                 Intent i = new Intent();
261                 i.setData(Uri.parse("market://details?id=com.koushikdutta.superuser"));
262                 startActivity(i);
263             }
264         });
265         builder.setNegativeButton(android.R.string.cancel, null);
266         builder.create().show();
267     }
268
269     @Override
270     protected void onCreate(Bundle savedInstanceState) {
271         Settings.applyDarkThemeSetting(this, R.style.SuperuserDarkActivity);
272         super.onCreate(savedInstanceState);
273         
274         if (Settings.getBoolean(this, "first_run", true)) {
275             saveWhatsNew();
276             Settings.setBoolean(this, "first_run", false);
277         }
278         
279         final ProgressDialog dlg = new ProgressDialog(this);
280         dlg.setTitle(R.string.superuser);
281         dlg.setMessage(getString(R.string.checking_superuser));
282         dlg.setIndeterminate(true);
283         dlg.show();
284         new Thread() {
285             public void run() {
286                 boolean _error = false;
287                 try {
288                     SuHelper.checkSu(MainActivity.this);
289                 }
290                 catch (Exception e) {
291                     e.printStackTrace();
292                     _error = true;
293                 }
294                 final boolean error = _error;
295                 dlg.dismiss();
296                 runOnUiThread(new Runnable() {
297                     @Override
298                     public void run() {
299                         if (error) {
300                             doInstall();
301                         }
302                         else {
303                             doWhatsNew();
304                         }
305                     }
306                 });
307             };
308         }.start();
309     }
310 }