Permalink
Browse files

more fixes.

  • Loading branch information...
1 parent 331ae7f commit 4605e58c14346608ce7102eca4a1b41f2448dfa9 @koush committed Aug 19, 2010
View
@@ -1,17 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.koushikdutta.droidx.bootstrap"
- android:versionCode="1"
- android:versionName="1.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
+ android:versionCode="1000"
+ android:versionName="1.0.0.0">
+ <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
<activity android:name=".Bootstrap"
- android:label="@string/app_name">
+ android:label="@string/app_name"
+ android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <service android:name=".BootService" />
+ <receiver android:name=".BootReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ </intent-filter>
+ </receiver>
</application>
<uses-sdk android:minSdkVersion="7" />
View
Binary file not shown.
View
Binary file not shown.
View
Binary file not shown.
View
Binary file not shown.
View
Binary file not shown.
View
Binary file not shown.
@@ -12,12 +12,18 @@
}
public static final class drawable {
public static final int icon=0x7f020000;
+ public static final int logo=0x7f020001;
+ }
+ public static final class id {
+ public static final int flash=0x7f050000;
+ public static final int reboot=0x7f050001;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
- public static final int app_name=0x7f040001;
- public static final int hello=0x7f040000;
+ public static final int app_name=0x7f040000;
+ public static final int flash=0x7f040001;
+ public static final int reboot_recovery=0x7f040002;
}
}
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -3,10 +3,8 @@
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
+ android:background="@drawable/logo"
>
-<TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/hello"
- />
+<Button android:text="@string/flash" android:id="@+id/flash" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp"></Button>
+<Button android:text="@string/reboot_recovery" android:id="@+id/reboot" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="20sp"></Button>
</LinearLayout>
View
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="hello">Hello World, Bootstrap!</string>
- <string name="app_name">DroidXBootstrap</string>
+ <string name="app_name">Droid X Bootstrapper</string>
+ <string name="flash">Bootstrap Recovery</string>
+ <string name="reboot_recovery">Reboot Recovery</string>
</resources>
@@ -0,0 +1,14 @@
+package com.koushikdutta.droidx.bootstrap;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class BootReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Intent i = new Intent(context, BootService.class);
+ context.startService(i); }
+
+}
@@ -0,0 +1,55 @@
+package com.koushikdutta.droidx.bootstrap;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+
+public class BootService extends Service {
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ super.onStart(intent, startId);
+
+ // wait to make sure the system is sane.
+ mHandler.postDelayed(new Runnable()
+ {
+ @Override
+ public void run() {
+
+ String filesDir = getFilesDir().getAbsolutePath();
+ String busybox = filesDir + "/busybox";
+ String adbd = filesDir + "/adbd";
+
+ StringBuilder command = new StringBuilder();
+ // prevent recovery from booting here
+ command.append("rm /data/.recovery_mode ; ");
+ // restart adbd as root
+ command.append(busybox + " mount -orw,remount / ; ");
+ command.append("mv /sbin/adbd /sbin/adbd.old ; ");
+ command.append(busybox + " cp " + adbd + " /sbin/adbd ; ");
+ command.append(busybox + " mount -oro,remount / ; ");
+ command.append(busybox + " kill $(ps | " + busybox + " grep adbd) ;");
+ try {
+ Helper.runSuCommand(BootService.this, command.toString());
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally
+ {
+ stopSelf();
+ }
+ }
+ },
+ 30000);
+ }
+
+ Handler mHandler = new Handler();
+
+ @Override
+ public IBinder onBind(Intent arg0) {
+ return null;
+ }
+
+}
@@ -1,13 +1,166 @@
package com.koushikdutta.droidx.bootstrap;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
public class Bootstrap extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
+
+ unzipAssets();
+
+ Button flash = (Button)findViewById(R.id.flash);
+ flash.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String filesDir = getFilesDir().getAbsolutePath();
+ String busybox = filesDir + "/busybox";
+ String hijack = filesDir + "/hijack";
+ String logwrapper = filesDir + "/logwrapper.bin";
+ String updatebinary = filesDir + "/update-binary";
+ String recoveryzip = filesDir + "/update.zip";
+ String adbd = filesDir + "/adbd";
+
+ StringBuilder command = new StringBuilder();
+ command.append(busybox + " mount -oremount,rw /system ; ");
+ command.append(busybox + " cp " + logwrapper + " /system/bin/logwrapper.bin ; ");
+ command.append(busybox + " cp " + hijack + " /system/bin/hijack ; ");
+ command.append("cd /system/bin ; rm logwrapper ; ln -s hijack logwrapper ; ");
+ command.append(busybox + " mount -oremount,ro /system ; ");
+ command.append(busybox + " mkdir -p /preinstall/recovery ; ");
+ command.append(busybox + " cp " + updatebinary + " /preinstall/recovery/update-binary ; ");
+ command.append(busybox + " cp " + recoveryzip + " /preinstall/recovery/recovery.zip ; ");
+
+ // restart adbd as root
+ command.append(busybox + " mount -orw,remount / ; ");
+ command.append("mv /sbin/adbd /sbin/adbd.old ; ");
+ command.append(busybox + " cp " + adbd + " /sbin/adbd ; ");
+ command.append(busybox + " mount -oro,remount / ; ");
+ command.append(busybox + " kill $(ps | " + busybox + " grep adbd) ;");
+
+ // prevent recovery from booting here
+ command.append("rm /data/.recovery_mode ; ");
+
+ AlertDialog.Builder builder = new Builder(Bootstrap.this);
+ builder.setPositiveButton(android.R.string.ok, null);
+ try {
+ Helper.runSuCommand(Bootstrap.this, command.toString());
+ builder.setMessage("Success!");
+ }
+ catch (Exception e) {
+ builder.setTitle("Failure");
+ builder.setMessage(e.getMessage());
+ e.printStackTrace();
+ }
+ builder.create().show();
+ }
+ });
+
+ Button reboot = (Button)findViewById(R.id.reboot);
+ reboot.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ StringBuilder command = new StringBuilder();
+ command.append("echo 1 > /data/.recovery_mode ; ");
+ command.append("sync ; reboot ; ");
+ try {
+ Helper.runSuCommand(Bootstrap.this, command.toString());
+ }
+ catch (Exception e) {
+ AlertDialog.Builder builder = new Builder(Bootstrap.this);
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.setTitle("Failure");
+ builder.setMessage(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ final static String LOGTAG = "DroidXBootstrap";
+ final static String ZIP_FILTER = "assets";
+
+ void unzipAssets() {
+ String apkPath = getPackageCodePath();
+ String mAppRoot = getFilesDir().toString();
+ try {
+ File zipFile = new File(apkPath);
+ long zipLastModified = zipFile.lastModified();
+ ZipFile zip = new ZipFile(apkPath);
+ Vector<ZipEntry> files = getAssets(zip);
+ int zipFilterLength = ZIP_FILTER.length();
+
+ Enumeration<?> entries = files.elements();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+ String path = entry.getName().substring(zipFilterLength);
+ File outputFile = new File(mAppRoot, path);
+ outputFile.getParentFile().mkdirs();
+
+ if (outputFile.exists() && entry.getSize() == outputFile.length() && zipLastModified < outputFile.lastModified())
+ continue;
+ FileOutputStream fos = new FileOutputStream(outputFile);
+ copyStreams(zip.getInputStream(entry), fos);
+ Runtime.getRuntime().exec("chmod 755 " + outputFile.getAbsolutePath());
+ }
+ } catch (IOException e) {
+ Log.e(LOGTAG, "Error: " + e.getMessage());
+ }
+ }
+
+ static final int BUFSIZE = 5192;
+
+ void copyStreams(InputStream is, FileOutputStream fos) {
+ BufferedOutputStream os = null;
+ try {
+ byte data[] = new byte[BUFSIZE];
+ int count;
+ os = new BufferedOutputStream(fos, BUFSIZE);
+ while ((count = is.read(data, 0, BUFSIZE)) != -1) {
+ os.write(data, 0, count);
+ }
+ os.flush();
+ } catch (IOException e) {
+ Log.e(LOGTAG, "Exception while copying: " + e);
+ } finally {
+ try {
+ if (os != null) {
+ os.close();
+ }
+ } catch (IOException e2) {
+ Log.e(LOGTAG, "Exception while closing the stream: " + e2);
+ }
+ }
+ }
+
+ public Vector<ZipEntry> getAssets(ZipFile zip) {
+ Vector<ZipEntry> list = new Vector<ZipEntry>();
+ Enumeration<?> entries = zip.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+ if (entry.getName().startsWith(ZIP_FILTER)) {
+ list.add(entry);
+ }
+ }
+ return list;
}
}
@@ -0,0 +1,36 @@
+package com.koushikdutta.droidx.bootstrap;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import android.content.Context;
+
+public class Helper {
+ static final String LOGTAG = "DroidXBootstrap";
+
+ public final static String SCRIPT_NAME = "surunner.sh";
+
+ public static Process runSuCommandAsync(Context context, String command) throws IOException
+ {
+ DataOutputStream fout = new DataOutputStream(context.openFileOutput(SCRIPT_NAME, 0));
+ fout.writeBytes(command);
+ fout.close();
+
+ String[] args = new String[] { "su", "-c", ". " + context.getFilesDir().getAbsolutePath() + "/" + SCRIPT_NAME };
+ Process proc = Runtime.getRuntime().exec(args);
+ return proc;
+ }
+
+ public static int runSuCommand(Context context, String command) throws IOException, InterruptedException
+ {
+ return runSuCommandAsync(context, command).waitFor();
+ }
+
+ public static int runSuCommandNoScriptWrapper(Context context, String command) throws IOException, InterruptedException
+ {
+ String[] args = new String[] { "su", "-c", command };
+ Process proc = Runtime.getRuntime().exec(args);
+ return proc.waitFor();
+ }
+
+}

0 comments on commit 4605e58

Please sign in to comment.