OSDN Git Service

check superuser on boot. but do it nicely... with a notification. and back off if...
authorKoushik Dutta <koushd@gmail.com>
Mon, 4 Mar 2013 00:42:54 +0000 (16:42 -0800)
committerKoushik Dutta <koushd@gmail.com>
Mon, 4 Mar 2013 00:42:54 +0000 (16:42 -0800)
Change-Id: Iae03c53aca95209933b9c80c0761d179208ac97d

Superuser/AndroidManifest.xml
Superuser/res/values/strings.xml
Superuser/src/com/koushikdutta/superuser/MainActivity.java
Superuser/src/com/koushikdutta/superuser/SuCheckerReceiver.java [new file with mode: 0644]
Superuser/src/com/koushikdutta/superuser/util/Settings.java
Superuser/src/com/koushikdutta/superuser/util/SuHelper.java [new file with mode: 0644]

index ff90147..27f8bdb 100644 (file)
@@ -32,6 +32,7 @@
         android:protectionLevel="dangerous" />
 
     <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 
     <application
         android:name=".SuApplication"
         <receiver
             android:name=".SuReceiver"
             android:permission="android.permission.REPORT_SUPERUSER" />
+
+        <receiver android:name=".SuCheckerReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+                <!-- <action android:name="internal.superuser.BOOT_TEST" /> -->
+            </intent-filter>
+        </receiver>
     </application>
 
 </manifest>
\ No newline at end of file
index 8e87dab..a823bbe 100644 (file)
@@ -75,4 +75,5 @@
     <string name="checking_superuser">Checking Superuser...</string>
     <string name="install_error">There was an error installing Superuser. Please send a log of the error to the developer.</string>
     <string name="install_success">Installation of Superuser was successful.</string>
+    <string name="su_binary_outdated">The su binary is out of date.</string>
 </resources>
index 3a8d59a..601f384 100644 (file)
@@ -17,7 +17,6 @@
 package com.koushikdutta.superuser;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,14 +29,13 @@ import android.app.ProgressDialog;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.MenuItem.OnMenuItemClickListener;
 
-import com.koushikdutta.superuser.util.Settings;
 import com.koushikdutta.superuser.util.StreamUtility;
+import com.koushikdutta.superuser.util.SuHelper;
 import com.koushikdutta.widgets.BetterListActivity;
 
 public class MainActivity extends BetterListActivity {
@@ -178,7 +176,7 @@ public class MainActivity extends BetterListActivity {
                     p.getOutputStream().close();
                     if (p.waitFor() != 0)
                         throw new Exception("non zero result");
-                    checkSu();
+                    SuHelper.checkSu(MainActivity.this);
                 }
                 catch (Exception ex) {
                     _error = true;
@@ -225,19 +223,6 @@ public class MainActivity extends BetterListActivity {
         });
         builder.create().show();
     }
-    
-    void checkSu() throws Exception {
-        Process p = Runtime.getRuntime().exec("su -v");
-        String result = Settings.readToEnd(p.getInputStream());
-        Log.i("Superuser", "Result: " + result);
-        if (0 != p.waitFor())
-            throw new Exception("non zero result");
-        if (result == null)
-            throw new Exception("no data");
-        if (!result.contains(getPackageName()))
-            throw new Exception("unknown su");
-        // TODO: upgrades herp derp
-    }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -252,7 +237,7 @@ public class MainActivity extends BetterListActivity {
             public void run() {
                 boolean error = false;
                 try {
-                    checkSu();
+                    SuHelper.checkSu(MainActivity.this);
                 }
                 catch (Exception e) {
                     e.printStackTrace();
diff --git a/Superuser/src/com/koushikdutta/superuser/SuCheckerReceiver.java b/Superuser/src/com/koushikdutta/superuser/SuCheckerReceiver.java
new file mode 100644 (file)
index 0000000..ec82452
--- /dev/null
@@ -0,0 +1,75 @@
+package com.koushikdutta.superuser;
+
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.support.v4.app.NotificationCompat;
+import android.util.Log;
+
+import com.koushikdutta.superuser.util.Settings;
+import com.koushikdutta.superuser.util.SuHelper;
+
+public class SuCheckerReceiver extends BroadcastReceiver {
+    public void doNotification(Context context) {
+        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+        builder.setTicker(context.getString(R.string.install_superuser));
+        builder.setContentTitle(context.getString(R.string.install_superuser));
+        builder.setSmallIcon(R.drawable.ic_stat_notification);
+        builder.setWhen(0);
+        builder.setContentText(context.getString(R.string.su_binary_outdated));
+        builder.setAutoCancel(true);
+        PendingIntent launch = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
+        Intent delIntent = new Intent(context, SuCheckerReceiver.class);
+        delIntent.setAction(ACTION_DELETED);
+        PendingIntent delete = PendingIntent.getBroadcast(context, 0, delIntent, 0);
+        builder.setDeleteIntent(delete);
+        builder.setContentIntent(launch);
+        NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
+        nm.notify(10000, builder.build());
+    }
+    
+    private static final String ACTION_DELETED = "internal.superuser.ACTION_CHECK_DELETED";
+    
+    @Override
+    public void onReceive(final Context context, Intent intent) {
+        if (intent == null)
+            return;
+        
+        
+        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) || "internal.superuser.BOOT_TEST".equals(intent.getAction())) {
+            // if the user deleted the notification in the past, don't bother them again for a while
+            int counter = Settings.getCheckSuQuietCounter(context);
+            if (counter > 0) {
+                Log.i("Superuser", "Not bothering user... su counter set.");
+                counter--;
+                Settings.setCheckSuQuietCounter(context, counter);
+                return;
+            }
+
+            final Handler handler = new Handler();
+            new Thread() {
+                public void run() {
+                    try {
+                        SuHelper.checkSu(context);
+                    }
+                    catch (Exception ex) {
+                        handler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                doNotification(context);
+                            }
+                        });
+                    }
+                };
+            }.start();
+        }
+        else if (ACTION_DELETED.equals(intent.getAction())) {
+            // notification deleted? bother the user in 3 reboots.
+            Log.i("Superuser", "Will not bother the user in the future... su counter set.");
+            Settings.setCheckSuQuietCounter(context, 3);
+        }
+    }
+}
index 5261347..7f1d8eb 100755 (executable)
@@ -306,4 +306,13 @@ public class Settings {
         catch (Exception ex) {
         }
     }
+    
+    private static final String CHECK_SU_QUIET = "check_su_quiet";
+    public static final int getCheckSuQuietCounter(Context context) {
+        return getInt(context, CHECK_SU_QUIET, 0);
+    }
+    
+    public static final void setCheckSuQuietCounter(Context context, int counter) {
+        setInt(context, CHECK_SU_QUIET, counter);
+    }
 }
diff --git a/Superuser/src/com/koushikdutta/superuser/util/SuHelper.java b/Superuser/src/com/koushikdutta/superuser/util/SuHelper.java
new file mode 100644 (file)
index 0000000..3c1573b
--- /dev/null
@@ -0,0 +1,21 @@
+package com.koushikdutta.superuser.util;
+
+import android.content.Context;
+import android.util.Log;
+
+public class SuHelper {
+    
+    public static void checkSu(Context context) throws Exception {
+        Process p = Runtime.getRuntime().exec("su -v");
+        String result = Settings.readToEnd(p.getInputStream());
+        Log.i("Superuser", "Result: " + result);
+        if (0 != p.waitFor())
+            throw new Exception("non zero result");
+        if (result == null)
+            throw new Exception("no data");
+        if (!result.contains(context.getPackageName()))
+            throw new Exception("unknown su");
+        // TODO: upgrades herp derp
+    }
+
+}