Initial commit for GitHub
diff --git a/FairphoneUpdater/.classpath b/FairphoneUpdater/.classpath
new file mode 100644
index 0000000..26bdfa6
--- /dev/null
+++ b/FairphoneUpdater/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<classpath>

+	<classpathentry kind="src" path="src"/>

+	<classpathentry kind="src" path="gen"/>

+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>

+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>

+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>

+	<classpathentry kind="output" path="bin/classes"/>

+</classpath>

diff --git a/FairphoneUpdater/.project b/FairphoneUpdater/.project
new file mode 100644
index 0000000..7630c9f
--- /dev/null
+++ b/FairphoneUpdater/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>FairphoneUpdater</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/FairphoneUpdater/.settings/org.eclipse.jdt.core.prefs b/FairphoneUpdater/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b080d2d
--- /dev/null
+++ b/FairphoneUpdater/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/FairphoneUpdater/Android.mk b/FairphoneUpdater/Android.mk
new file mode 100644
index 0000000..483a95d
--- /dev/null
+++ b/FairphoneUpdater/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-common android-support-v4
+LOCAL_JAVA_LIBRARIES += mediatek-framework
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+#LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := FairphoneUpdater
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/FairphoneUpdater/AndroidManifest.xml b/FairphoneUpdater/AndroidManifest.xml
new file mode 100644
index 0000000..3f62121
--- /dev/null
+++ b/FairphoneUpdater/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fairphone.updater"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="17"
+        android:targetSdkVersion="17" />
+
+    <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.REBOOT" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/fairphone_updater_app_icon"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.fairphone.updater.FairphoneUpdater"
+            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=".UpdaterService"
+            android:icon="@drawable/fairphone_updater_app_icon_small"
+            android:label="@string/updaterService" />
+
+        <receiver android:name="BootBroadcastReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/FairphoneUpdater/CleanSpec.mk b/FairphoneUpdater/CleanSpec.mk
new file mode 100644
index 0000000..a2b2866
--- /dev/null
+++ b/FairphoneUpdater/CleanSpec.mk
@@ -0,0 +1,56 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneUpdater_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneUpdater_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneUpdater_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneUpdater_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneUpdater_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/FairphoneUpdater.apk)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/FairphoneUpdater/bin/AndroidManifest.xml b/FairphoneUpdater/bin/AndroidManifest.xml
new file mode 100644
index 0000000..3f62121
--- /dev/null
+++ b/FairphoneUpdater/bin/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fairphone.updater"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="17"
+        android:targetSdkVersion="17" />
+
+    <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.REBOOT" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/fairphone_updater_app_icon"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.fairphone.updater.FairphoneUpdater"
+            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=".UpdaterService"
+            android:icon="@drawable/fairphone_updater_app_icon_small"
+            android:label="@string/updaterService" />
+
+        <receiver android:name="BootBroadcastReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/BootBroadcastReceiver.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/BootBroadcastReceiver.class
new file mode 100644
index 0000000..59215d0
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/BootBroadcastReceiver.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/BuildConfig.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/BuildConfig.class
new file mode 100644
index 0000000..a4b4e66
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/BuildConfig.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$1.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$1.class
new file mode 100644
index 0000000..5eb8cc2
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$1.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$2.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$2.class
new file mode 100644
index 0000000..7ff82e8
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$2.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$DownloadBroadCastReceiver.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$DownloadBroadCastReceiver.class
new file mode 100644
index 0000000..2e5f73d
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$DownloadBroadCastReceiver.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$UpdaterState.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$UpdaterState.class
new file mode 100644
index 0000000..9164e62
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater$UpdaterState.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater.class
new file mode 100644
index 0000000..1aeda13
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/FairphoneUpdater.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$attr.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$attr.class
new file mode 100644
index 0000000..6bb9149
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$attr.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$dimen.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$dimen.class
new file mode 100644
index 0000000..8b83e0e
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$dimen.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$drawable.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$drawable.class
new file mode 100644
index 0000000..57672b6
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$drawable.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$id.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$id.class
new file mode 100644
index 0000000..7e81278
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$id.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$layout.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$layout.class
new file mode 100644
index 0000000..a72c62d
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$layout.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$raw.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$raw.class
new file mode 100644
index 0000000..388ea34
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$raw.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$string.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$string.class
new file mode 100644
index 0000000..5793c96
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$string.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R$style.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$style.class
new file mode 100644
index 0000000..62f757d
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R$style.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/R.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/R.class
new file mode 100644
index 0000000..29bed44
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/R.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/RSAUtils.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/RSAUtils.class
new file mode 100644
index 0000000..b31ba53
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/RSAUtils.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/UpdaterService$DownloadBroadCastReceiver.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/UpdaterService$DownloadBroadCastReceiver.class
new file mode 100644
index 0000000..fb68ad2
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/UpdaterService$DownloadBroadCastReceiver.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/UpdaterService.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/UpdaterService.class
new file mode 100644
index 0000000..d51b6b1
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/UpdaterService.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/Version.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/Version.class
new file mode 100644
index 0000000..552d679
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/Version.class
Binary files differ
diff --git a/FairphoneUpdater/bin/classes/com/fairphone/updater/VersionParserHelper.class b/FairphoneUpdater/bin/classes/com/fairphone/updater/VersionParserHelper.class
new file mode 100644
index 0000000..f33d853
--- /dev/null
+++ b/FairphoneUpdater/bin/classes/com/fairphone/updater/VersionParserHelper.class
Binary files differ
diff --git a/FairphoneUpdater/gen/com/fairphone/updater/BuildConfig.java b/FairphoneUpdater/gen/com/fairphone/updater/BuildConfig.java
new file mode 100644
index 0000000..b128dff
--- /dev/null
+++ b/FairphoneUpdater/gen/com/fairphone/updater/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package com.fairphone.updater;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/FairphoneUpdater/gen/com/fairphone/updater/R.java b/FairphoneUpdater/gen/com/fairphone/updater/R.java
new file mode 100644
index 0000000..b05542d
--- /dev/null
+++ b/FairphoneUpdater/gen/com/fairphone/updater/R.java
@@ -0,0 +1,76 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package com.fairphone.updater;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class dimen {
+        /**  Default screen margins, per the Android Design guidelines. 
+         */
+        public static final int activity_horizontal_margin=0x7f050000;
+        public static final int activity_vertical_margin=0x7f050001;
+    }
+    public static final class drawable {
+        public static final int fairphone_updater_app_icon=0x7f020000;
+        public static final int fairphone_updater_app_icon_small=0x7f020001;
+        public static final int fairphone_updater_current_version=0x7f020002;
+        public static final int fairphone_updater_tray_icon=0x7f020003;
+        public static final int fairphone_updater_tray_icon_small=0x7f020004;
+    }
+    public static final class id {
+        public static final int currentVersionDescriptionText=0x7f080005;
+        public static final int currentVersionImage=0x7f080003;
+        public static final int currentVersionSeparator=0x7f080002;
+        public static final int currentVersionTitleSeparator=0x7f080001;
+        public static final int currentVersionTitleText=0x7f080004;
+        public static final int latestVersionGroup=0x7f080006;
+        public static final int messageText=0x7f08000c;
+        public static final int newVersionUpdateButton=0x7f08000d;
+        public static final int nextVersionDescriptionText=0x7f08000b;
+        public static final int nextVersionImage=0x7f080009;
+        public static final int nextVersionSeparator=0x7f080008;
+        public static final int nextVersionTitleSeparator=0x7f080007;
+        public static final int nextVersionTitleText=0x7f08000a;
+        public static final int titleText=0x7f080000;
+    }
+    public static final class layout {
+        public static final int activity_fairphone_updater=0x7f030000;
+    }
+    public static final class raw {
+        public static final int public_key=0x7f040000;
+    }
+    public static final class string {
+        public static final int app_name=0x7f060000;
+        public static final int currentVersion=0x7f06000a;
+        public static final int defaultAndroidVersionNumber=0x7f060008;
+        public static final int defaultVersionName=0x7f060007;
+        public static final int defaultVersionNumber=0x7f060006;
+        public static final int downloadMessage=0x7f060011;
+        public static final int downloadUpdateTitle=0x7f060012;
+        public static final int downloadUrl=0x7f060001;
+        public static final int fairphoneUpdateMessage=0x7f060010;
+        public static final int installVersion=0x7f06000c;
+        public static final int invalidDownloadMessage=0x7f06000f;
+        public static final int messageReadyToInstall=0x7f06000e;
+        public static final int newVersion=0x7f06000b;
+        public static final int rebootDevice=0x7f06000d;
+        public static final int updaterService=0x7f060009;
+        /**  <string name="downloadUrl">http://www.kwamecorp.com/dev/latest.zip</string>  
+         */
+        public static final int versionFilename=0x7f060002;
+        public static final int versionFilename_sig=0x7f060005;
+        public static final int versionFilename_xml=0x7f060004;
+        public static final int versionFilename_zip=0x7f060003;
+        public static final int wifiDiscaimerMessage=0x7f060014;
+        public static final int wifiDiscaimerTitle=0x7f060013;
+    }
+    public static final class style {
+        public static final int AppTheme=0x7f070000;
+    }
+}
diff --git a/FairphoneUpdater/libs/android-support-v4.jar b/FairphoneUpdater/libs/android-support-v4.jar
new file mode 100644
index 0000000..cf12d28
--- /dev/null
+++ b/FairphoneUpdater/libs/android-support-v4.jar
Binary files differ
diff --git a/FairphoneUpdater/proguard-project.txt b/FairphoneUpdater/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/FairphoneUpdater/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/FairphoneUpdater/project.properties b/FairphoneUpdater/project.properties
new file mode 100644
index 0000000..a3ee5ab
--- /dev/null
+++ b/FairphoneUpdater/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-17
diff --git a/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_app_icon.png b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_app_icon.png
new file mode 100644
index 0000000..fe13aef
--- /dev/null
+++ b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_app_icon.png
Binary files differ
diff --git a/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_app_icon_small.png b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_app_icon_small.png
new file mode 100644
index 0000000..ca5dddd
--- /dev/null
+++ b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_app_icon_small.png
Binary files differ
diff --git a/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_current_version.png b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_current_version.png
new file mode 100644
index 0000000..7f4d80d
--- /dev/null
+++ b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_current_version.png
Binary files differ
diff --git a/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_tray_icon.png b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_tray_icon.png
new file mode 100644
index 0000000..f3ccf85
--- /dev/null
+++ b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_tray_icon.png
Binary files differ
diff --git a/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_tray_icon_small.png b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_tray_icon_small.png
new file mode 100644
index 0000000..ccd0b62
--- /dev/null
+++ b/FairphoneUpdater/res/drawable-hdpi/fairphone_updater_tray_icon_small.png
Binary files differ
diff --git a/FairphoneUpdater/res/layout/activity_fairphone_updater.xml b/FairphoneUpdater/res/layout/activity_fairphone_updater.xml
new file mode 100644
index 0000000..0cdc658
--- /dev/null
+++ b/FairphoneUpdater/res/layout/activity_fairphone_updater.xml
@@ -0,0 +1,173 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#000"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/titleText"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="10dp"
+        android:drawableLeft="@drawable/fairphone_updater_app_icon_small"
+        android:drawablePadding="10dp"
+        android:gravity="center_vertical"
+        android:text="@string/app_name"
+        android:textColor="#fff"
+        android:textSize="20sp" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="2dp"
+        android:background="#33b5e5" />
+
+    <TextView
+        android:id="@+id/currentVersionTitleSeparator"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="3dp"
+        android:layout_marginLeft="20dp"
+        android:layout_marginTop="10dp"
+        android:text="@string/currentVersion"
+        android:textAllCaps="true"
+        android:textColor="#d3d3d3"
+        android:textSize="15sp" />
+
+    <View
+        android:id="@+id/currentVersionSeparator"
+        android:layout_width="match_parent"
+        android:layout_height="2dp"
+        android:layout_marginLeft="15dp"
+        android:layout_marginRight="15dp"
+        android:background="#d3d3d3" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="80dp"
+        android:layout_margin="15dp"
+        android:orientation="horizontal" >
+
+        <ImageView
+            android:id="@+id/currentVersionImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fairphone_updater_current_version" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"
+            android:orientation="vertical" >
+
+            <TextView
+                android:id="@+id/currentVersionTitleText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical"
+                android:includeFontPadding="false"
+                android:text="@string/currentVersion"
+                android:textColor="#fff"
+                android:textSize="17sp" />
+
+            <TextView
+                android:id="@+id/currentVersionDescriptionText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical"
+                android:textColor="#fff" />
+        </LinearLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/latestVersionGroup"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="#000"
+        android:orientation="vertical" >
+
+        <TextView
+            android:id="@+id/nextVersionTitleSeparator"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="3dp"
+            android:layout_marginLeft="20dp"
+            android:layout_marginTop="20dp"
+            android:text="@string/newVersion"
+            android:textAllCaps="true"
+            android:textColor="#d3d3d3"
+            android:textSize="15sp" />
+
+        <View
+            android:id="@+id/nextVersionSeparator"
+            android:layout_width="match_parent"
+            android:layout_height="2dp"
+            android:layout_marginLeft="15dp"
+            android:layout_marginRight="15dp"
+            android:background="#d3d3d3" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="80dp"
+            android:layout_margin="15dp"
+            android:orientation="horizontal" >
+
+            <ImageView
+                android:id="@+id/nextVersionImage"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:src="@drawable/fairphone_updater_app_icon" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:orientation="vertical" >
+
+                <TextView
+                    android:id="@+id/nextVersionTitleText"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_vertical"
+                    android:includeFontPadding="false"
+                    android:text="@string/newVersion"
+                    android:textColor="#fff"
+                    android:textSize="17sp" />
+
+                <TextView
+                    android:id="@+id/nextVersionDescriptionText"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_vertical"
+                    android:textColor="#fff" />
+            </LinearLayout>
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+
+        <TextView
+            android:id="@+id/messageText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_margin="15dp"
+            android:gravity="right"
+            android:textColor="#d3d3d3"
+            android:textSize="18.5sp" />
+
+        <Button
+            android:id="@+id/newVersionUpdateButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="right"
+            android:layout_marginBottom="15dp"
+            android:layout_marginRight="15dp"
+            android:paddingLeft="15dp"
+            android:paddingRight="15dp"
+            android:text="@string/installVersion"
+            android:textColor="#ffffff" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/raw/public_key.pem b/FairphoneUpdater/res/raw/public_key.pem
new file mode 100644
index 0000000..e25387d
--- /dev/null
+++ b/FairphoneUpdater/res/raw/public_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0FRWtP59Lq3axya7c48b
+aZgJIc19Welf56rG1oXnJqG3qqVhaAg8OKLW6pLKeg38K/VI8ih5HVuj2fb7u35G
+BsOvSFcPRVbezermyFdnlbCfVgQlTfnVtv9oGRzgofg6dkXYQytObouQKMAW3QSX
+0475+9JFLlyW7aTtafsapP6sqCZX8cgLHT/nPqTPdA/MFB5tDPtBBsOf2LR7h5Kj
+NbU8exLV/6SGqqJq5ZmJOOIdW5W6IxiGUkHJ+uhQ5YDIxYRVsv7IV/PVFzMLD2pe
+9sa0wX1Gj0/h7pguVGorpR5wxK5AWpyXuAYbzyLTXRyIk5AgXlW9bDiP//wHqSlH
+pQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/FairphoneUpdater/res/values-de/strings.xml b/FairphoneUpdater/res/values-de/strings.xml
new file mode 100644
index 0000000..9268890
--- /dev/null
+++ b/FairphoneUpdater/res/values-de/strings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="updaterService">Aktualisierungsservice</string>
+    <string name="currentVersion">Aktuelle Version</string>
+    <string name="newVersion">Neue Version</string>
+    <string name="installVersion">Neue Version installieren</string>
+    <string name="rebootDevice">Gerät neustarten</string>
+    <string name="messageReadyToInstall">Neue Version bereit zur Installation&#8230;</string>
+    <string name="invalidDownloadMessage">Ungültige Datei runtergeladen</string>
+    <string name="fairphoneUpdateMessage">Neues Fairphone Update verfügbar</string>
+    <string name="downloadMessage">Lade Datei, bitte warten&#8230;</string>
+    <string name="downloadUpdateTitle">Neue Fairphone Version</string>
+    <string name="wifiDiscaimerTitle">WLAN deaktiviert</string>
+	<string name="wifiDiscaimerMessage">Die Datei, die Sie herunterladen möchten, ist zu groß für mobile Verbindungen (~200 MB). Bitte aktivieren Sie die WLAN-Verbindung und versuchen Sie es erneut.</string>    
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values-es/strings.xml b/FairphoneUpdater/res/values-es/strings.xml
new file mode 100644
index 0000000..0e7d6b3
--- /dev/null
+++ b/FairphoneUpdater/res/values-es/strings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="updaterService">Servicio de actualización</string>
+    <string name="currentVersion">Versión actual</string>
+    <string name="newVersion">Nueva versión</string>
+    <string name="installVersion">Instalar nueva versión</string>
+    <string name="rebootDevice">Reiniciar dispositivo</string>
+    <string name="messageReadyToInstall">La nueva versión está lista para instalar&#8230;</string>
+    <string name="invalidDownloadMessage">Archivo descargado inválido</string>
+    <string name="fairphoneUpdateMessage">Nueva actualización para Fairphone disponible</string>
+    <string name="downloadMessage">Descargando actualización, ten paciencia&#8230;</string>
+    <string name="downloadUpdateTitle">Nueva actualización para Fairphone</string>
+    <string name="wifiDiscaimerTitle">Wi-Fi desconectado</string>
+	<string name="wifiDiscaimerMessage">El archivo que está intentando descargar es muy largo para conexiones móviles (~200mb). Por favor conéctese al Wi-Fi e intente otra vez.</string>    
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values-fr/strings.xml b/FairphoneUpdater/res/values-fr/strings.xml
new file mode 100644
index 0000000..4611351
--- /dev/null
+++ b/FairphoneUpdater/res/values-fr/strings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="updaterService">Service de mise à jour</string>
+    <string name="currentVersion">Version actuelle</string>
+    <string name="newVersion">Nouvelle version</string>
+    <string name="installVersion">Installer la nouvelle version</string>
+    <string name="rebootDevice">Redémarrer l\'appareil</string>
+    <string name="messageReadyToInstall">Une nouvelle version est prête à installer&#8230;</string>
+    <string name="invalidDownloadMessage">Fichier téléchargé invalide</string>
+    <string name="fairphoneUpdateMessage">Nouvelle mise à jour de Fairphone disponible</string>
+    <string name="downloadMessage">Téléchargement de mise à jour, svp patienter&#8230;</string>
+    <string name="downloadUpdateTitle">Nouvelle mise à jour de Fairphones</string>
+    <string name="wifiDiscaimerTitle">Fonction Wi-Fi désactivée</string>
+	<string name="wifiDiscaimerMessage">Le fichier que vous essayez de télécharger est trop volumineux pour les connexions mobiles (~200 MB). Veuillez activer la connexion Wi-Fi et essayer à nouveau.</string>  
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values-nl/strings.xml b/FairphoneUpdater/res/values-nl/strings.xml
new file mode 100644
index 0000000..24a8f14
--- /dev/null
+++ b/FairphoneUpdater/res/values-nl/strings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="updaterService">Updater Service</string>
+    <string name="currentVersion">Huidige Versie</string>
+    <string name="newVersion">Nieuwe Versie</string>   
+    <string name="installVersion">Installeer nieuwe versie</string>
+    <string name="rebootDevice">Herstart apparaat</string>   
+    <string name="messageReadyToInstall">Nieuwe versie staat klaar om te installeren&#8230;</string>
+    <string name="invalidDownloadMessage">Gedownloade bestand is ongeldig</string>
+    <string name="fairphoneUpdateMessage">Nieuwe Fairphone update beschikbaar</string>
+    <string name="downloadMessage">Downloaden update, een moment geduld&#8230;</string>
+    <string name="downloadUpdateTitle">Nieuwe Fairphone update</string>
+    <string name="wifiDiscaimerTitle">Wi-Fi niet beschikbaar</string>
+	<string name="wifiDiscaimerMessage">Het bestand dat je probeert te downloaden is te groot voor mobiele verbindingen (~200MB). Breng de Wi-Fi verbinding tot stand en probeer het opnieuw.</string>  
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values-pt/strings.xml b/FairphoneUpdater/res/values-pt/strings.xml
new file mode 100644
index 0000000..f996e80
--- /dev/null
+++ b/FairphoneUpdater/res/values-pt/strings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="updaterService">Serviço de actualização</string>
+    <string name="currentVersion">Versão actual</string>
+    <string name="newVersion">Nova versão</string>
+    <string name="installVersion">Instalar nova versão</string>
+    <string name="rebootDevice">Reiniciar dispositivo</string>
+    <string name="messageReadyToInstall">Nova versão pronta para instalar&#8230;</string>
+    <string name="invalidDownloadMessage">Ficheiro descarregado inválido</string>
+    <string name="fairphoneUpdateMessage">Nova actualização Fairphone disponível</string>
+    <string name="downloadMessage">A descarregar nova versão, por favor aguarde&#8230;</string>
+    <string name="downloadUpdateTitle">Nova actualização Fairphone</string>
+    <string name="wifiDiscaimerTitle">Wi-Fi desligado</string>
+	<string name="wifiDiscaimerMessage">O ficheiro que está a tentar descarregar é muito grande para ligações móveis (~200mb). Por favor ligue-se ao Wi-Fi e tente outra vez.</string>
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values/dimens.xml b/FairphoneUpdater/res/values/dimens.xml
new file mode 100644
index 0000000..a6dd140
--- /dev/null
+++ b/FairphoneUpdater/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values/strings.xml b/FairphoneUpdater/res/values/strings.xml
new file mode 100644
index 0000000..31eb25d
--- /dev/null
+++ b/FairphoneUpdater/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Fairphone Updater</string>
+    <string name="downloadUrl">http://www.fairphone.com/ota/latest.zip</string>
+    <!-- <string name="downloadUrl">http://www.kwamecorp.com/dev/latest.zip</string>  -->
+    <string name="versionFilename">latest</string>
+    <string name="versionFilename_zip">.zip</string>
+	<string name="versionFilename_xml">.xml</string>
+	<string name="versionFilename_sig">.sig</string>
+	
+    <string name="defaultVersionNumber">1.0</string>
+    <string name="defaultVersionName">Almond</string>
+    <string name="defaultAndroidVersionNumber">4.2.2</string>
+    
+    <string name="updaterService">Updater Service</string>
+    <string name="currentVersion">Current Version</string>
+    <string name="newVersion">New Version</string>
+    <string name="installVersion">Install new version</string>
+    <string name="rebootDevice">Reboot device</string>
+    <string name="messageReadyToInstall">New version ready to install&#8230;</string>
+    <string name="invalidDownloadMessage">Invalid file downloaded</string>
+    <string name="fairphoneUpdateMessage">New Fairphone update available</string>
+    <string name="downloadMessage">Downloading version, please wait&#8230;</string>
+    <string name="downloadUpdateTitle">New Fairphone update</string>
+    <string name="wifiDiscaimerTitle">Wi-Fi disabled</string>
+	<string name="wifiDiscaimerMessage">The file you’re trying to download is too large for mobile connections (~200MB). Please enable Wi-Fi connection and try again.</string> 
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/res/values/styles.xml b/FairphoneUpdater/res/values/styles.xml
new file mode 100644
index 0000000..fb69874
--- /dev/null
+++ b/FairphoneUpdater/res/values/styles.xml
@@ -0,0 +1,8 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="AppTheme" parent="android:Theme.Holo">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowFullscreen">false</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneUpdater/src/com/fairphone/updater/BootBroadcastReceiver.java b/FairphoneUpdater/src/com/fairphone/updater/BootBroadcastReceiver.java
new file mode 100644
index 0000000..1ea31f5
--- /dev/null
+++ b/FairphoneUpdater/src/com/fairphone/updater/BootBroadcastReceiver.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Fairphone Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fairphone.updater;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.Calendar;
+
+public class BootBroadcastReceiver extends BroadcastReceiver {
+
+    final static long NOTIFICATION_INTERVAL_MILLIS = 1000 * 60 * 60 * 8;
+    
+	@Override
+	public void onReceive(Context context, Intent intent) {
+		
+		AlarmManager service = (AlarmManager) context
+				.getSystemService(Context.ALARM_SERVICE);
+		Intent i = new Intent(context, UpdaterService.class);
+		PendingIntent pending = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
+
+		Calendar cal = Calendar.getInstance();
+		// Start 30 seconds after boot completed
+		cal.add(Calendar.SECOND, 30);
+		
+		// InexactRepeating allows Android to optimize the energy consumption
+		service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), NOTIFICATION_INTERVAL_MILLIS, pending);
+	}
+
+}
diff --git a/FairphoneUpdater/src/com/fairphone/updater/FairphoneUpdater.java b/FairphoneUpdater/src/com/fairphone/updater/FairphoneUpdater.java
new file mode 100644
index 0000000..684ad51
--- /dev/null
+++ b/FairphoneUpdater/src/com/fairphone/updater/FairphoneUpdater.java
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2013 Fairphone Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fairphone.updater;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.PowerManager;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class FairphoneUpdater extends Activity {
+
+	protected static final String PREFERENCE_NEW_VERSION_NAME = "PREFERENCE_NEW_VERSION_NAME";
+	protected static final String PREFERENCE_NEW_VERSION_NUMBER = "PREFERENCE_NEW_VERSION_NUMBER";
+	protected static final String PREFERENCE_NEW_VERSION_MD5_SUM = "PREFERENCE_NEW_VERSION_MD5_SUM";
+	protected static final String PREFERENCE_NEW_VERSION_URL = "PREFERENCE_NEW_VERSION_URL";
+	protected static final String PREFERENCE_NEW_VERSION_ANDROID = "PREFERENCE_NEW_VERSION_ANDROID";
+
+	private static final String ANDROID_LABEL = "Android ";
+	private static final String FAIRPHONE_LABEL = "Fairphone ";
+
+	private static final String TAG = FairphoneUpdater.class.getSimpleName();
+
+	private static final String PREFERENCE_CURRENT_UPDATER_STATE = "CurrentUpdaterState";
+	private static final String PREFERENCE_DOWNLOAD_ID = "LatestUpdateDownloadId";
+	public static final String FAIRPHONE_UPDATER_PREFERENCES = "FairphoneUpdaterPreferences";
+
+	public static enum UpdaterState {
+		NORMAL, DOWNLOAD, PREINSTALL
+	};
+
+	private Version mDeviceVersion;
+	private Version mLatestVersion;
+
+	private UpdaterState mCurrentState;
+
+	private SharedPreferences mSharedPreferences;
+
+	// views
+	private TextView mViewCurrentVersionTitle;
+	private TextView mViewCurrentVersionText;
+
+	private TextView mViewUpdateVersionTitle;
+	private TextView mViewUpdateVersionText;
+
+	private TextView mViewMessageText;
+	private Button mViewUpdateButton;
+
+	private LinearLayout mLatestGroupLla;
+
+	private DownloadManager mDownloadManager;
+	private DownloadBroadCastReceiver mDownloadBroadCastReceiver;
+	private long mLatestUpdateDownloadId;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_fairphone_updater);
+
+		setupLayout();
+
+		mSharedPreferences = getSharedPreferences(
+				FAIRPHONE_UPDATER_PREFERENCES, MODE_PRIVATE);
+
+		// get system data
+		mDeviceVersion = VersionParserHelper.getDeviceVersion(this);
+
+		mLatestVersion = getLastestVersion();
+
+		// check current state
+		mCurrentState = getCurrentUpdaterState();
+
+		setupInstallationReceivers();
+
+		// TODO : remove this
+		Intent i = new Intent(this, UpdaterService.class);
+		startService(i);
+	}
+
+	private Version getLastestVersion() {
+		Version latest = null;
+
+		String newVersionName = mSharedPreferences.getString(
+				PREFERENCE_NEW_VERSION_NAME, null);
+
+		String number = mSharedPreferences.getString(
+				PREFERENCE_NEW_VERSION_NUMBER, null);
+		String url = mSharedPreferences.getString(PREFERENCE_NEW_VERSION_URL,
+				null);
+		String md5 = mSharedPreferences.getString(
+				PREFERENCE_NEW_VERSION_MD5_SUM, null);
+		String android = mSharedPreferences.getString(
+				PREFERENCE_NEW_VERSION_ANDROID, null);
+
+		if (newVersionName != null && number != null && url != null
+				&& md5 != null && android != null) {
+			latest = new Version();
+
+			latest.setName(newVersionName);
+			latest.setNumber(number);
+			latest.setDownloadLink(url);
+			latest.setMd5Sum(md5);
+			latest.setAndroid(android);
+		}
+
+		return latest;
+	}
+
+	private void setupLayout() {
+		mViewCurrentVersionTitle = (TextView) findViewById(R.id.currentVersionTitleText);
+		mViewCurrentVersionTitle.setVisibility(View.VISIBLE);
+		mViewCurrentVersionText = (TextView) findViewById(R.id.currentVersionDescriptionText);
+		mViewCurrentVersionText.setVisibility(View.VISIBLE);
+
+		mViewUpdateVersionTitle = (TextView) findViewById(R.id.nextVersionTitleText);
+		mViewUpdateVersionText = (TextView) findViewById(R.id.nextVersionDescriptionText);
+
+		mViewUpdateButton = (Button) findViewById(R.id.newVersionUpdateButton);
+
+		mViewMessageText = (TextView) findViewById(R.id.messageText);
+
+		mViewUpdateButton.setOnClickListener(new OnClickListener() {
+
+			@Override
+			public void onClick(View v) {
+				if (mCurrentState == UpdaterState.NORMAL) {
+					startUpdateDownload();
+				} else if (mCurrentState == UpdaterState.PREINSTALL) {
+					startPreInstall();
+				}
+			}
+		});
+
+		mLatestGroupLla = (LinearLayout) findViewById(R.id.latestVersionGroup);
+
+		mLatestGroupLla.setVisibility(View.GONE);
+	}
+
+	public String getStringPreference(String key) {
+		return mSharedPreferences.getString(key, null);
+	}
+
+	public long getLongPreference(String key) {
+		return mSharedPreferences.getLong(key, 0);
+	}
+
+	public boolean getBooleanPreference(String key) {
+		return mSharedPreferences.getBoolean(key, false);
+	}
+
+	public void savePreference(String key, String value) {
+		Editor editor = mSharedPreferences.edit();
+
+		editor.putString(key, value);
+
+		editor.commit();
+	}
+
+	public void savePreference(String key, boolean value) {
+		Editor editor = mSharedPreferences.edit();
+
+		editor.putBoolean(key, value);
+
+		editor.commit();
+	}
+
+	public void savePreference(String key, long value) {
+		Editor editor = mSharedPreferences.edit();
+
+		editor.putLong(key, value);
+
+		editor.commit();
+	}
+
+	@Override
+	protected void onResume() {
+		super.onResume();
+
+		registerBroadCastReceiver();
+		// check current state
+		mCurrentState = getCurrentUpdaterState();
+
+		if (mLatestVersion == null) {
+			mLatestVersion = VersionParserHelper.getLastestVersion(this);
+		}
+
+		mViewCurrentVersionTitle.setText(mDeviceVersion.getName());
+		mViewCurrentVersionText.setText(FAIRPHONE_LABEL
+				+ mDeviceVersion.getNumber() + "\n" + ANDROID_LABEL
+				+ mDeviceVersion.getAndroid());
+
+		setupState(mCurrentState);
+	}
+
+	private void setupState(UpdaterState state) {
+		switch (state) {
+		case NORMAL:
+			setupNormalState();
+			break;
+		case DOWNLOAD:
+			setupDownloadState();
+			break;
+		case PREINSTALL:
+			setupPreInstallState();
+			break;
+		}
+	}
+
+	private void changeState(UpdaterState newState) {
+		mCurrentState = newState;
+
+		Editor editor = mSharedPreferences.edit();
+
+		editor.putString(PREFERENCE_CURRENT_UPDATER_STATE, mCurrentState.name());
+
+		editor.commit();
+
+		setupState(mCurrentState);
+	}
+
+	@Override
+	protected void onPause() {
+		super.onPause();
+
+		unregisterBroadCastReceiver();
+	}
+
+	private void setupNormalState() {
+
+		if (mLatestUpdateDownloadId != 0) {
+			// residue download ID
+			mDownloadManager.remove(mLatestUpdateDownloadId);
+
+			mLatestUpdateDownloadId = 0;
+			savePreference(PREFERENCE_DOWNLOAD_ID, mLatestUpdateDownloadId);
+		}
+
+		// check to see if there is a new version to install
+		if (mLatestVersion != null) {
+			mLatestGroupLla.setVisibility(View.VISIBLE);
+			mViewUpdateButton.setVisibility(View.VISIBLE);
+
+			mViewUpdateVersionTitle.setText(mLatestVersion.getName());
+			mViewUpdateVersionText.setText(FAIRPHONE_LABEL
+					+ mLatestVersion.getNumber() + "\n" + ANDROID_LABEL
+					+ mLatestVersion.getAndroid());
+
+			mViewMessageText.setVisibility(View.GONE);
+			mViewUpdateButton.setText(getResources().getString(
+					R.string.installVersion));
+		} else {
+			mLatestGroupLla.setVisibility(View.GONE);
+		}
+	}
+
+	private UpdaterState getCurrentUpdaterState() {
+
+		String currentState = getStringPreference(PREFERENCE_CURRENT_UPDATER_STATE);
+
+		if (currentState == null || currentState.isEmpty()) {
+			currentState = UpdaterState.NORMAL.name();
+
+			Editor editor = mSharedPreferences.edit();
+
+			editor.putString(currentState, currentState);
+
+			editor.commit();
+		}
+
+		return UpdaterState.valueOf(currentState);
+	}
+
+	private static String getVersionDownloadPath(Version version) {
+		return Environment.getExternalStorageDirectory()
+				+ VersionParserHelper.UPDATER_FOLDER
+				+ VersionParserHelper.getNameFromVersion(version);
+	}
+
+	// ************************************************************************************
+	// PRE INSTALL
+	// ************************************************************************************
+
+	private void setupPreInstallState() {
+
+		// the latest version data must exist
+		if (mLatestVersion != null) {
+
+			mViewUpdateVersionTitle.setText(mLatestVersion.getName());
+			mViewUpdateVersionText.setText(FAIRPHONE_LABEL
+					+ mLatestVersion.getNumber() + "\n" + ANDROID_LABEL
+					+ mLatestVersion.getAndroid());
+
+			// check the md5 of the file
+			File file = new File(getVersionDownloadPath(mLatestVersion));
+
+			if (file.exists()) {
+
+				if (FairphoneUpdater.checkMD5(mLatestVersion.getMd5Sum(), file)) {
+					mLatestGroupLla.setVisibility(View.VISIBLE);
+
+					mViewMessageText.setText(getResources().getString(
+							R.string.messageReadyToInstall));
+
+					mViewUpdateButton.setText(getResources().getString(
+							R.string.rebootDevice));
+					mViewUpdateButton.setVisibility(View.VISIBLE);
+
+					mViewMessageText.setVisibility(View.VISIBLE);
+					return;
+				} else {
+					mDownloadManager.remove(mLatestUpdateDownloadId);
+					mLatestUpdateDownloadId = 0;
+
+					savePreference(PREFERENCE_DOWNLOAD_ID,
+							mLatestUpdateDownloadId);
+
+					Toast.makeText(
+							this,
+							getResources().getString(
+									R.string.invalidDownloadMessage),
+							Toast.LENGTH_SHORT).show();
+				}
+			}
+		}
+
+		// remove the updater directory
+		File fileDir = new File(Environment.getExternalStorageDirectory()
+				+ VersionParserHelper.UPDATER_FOLDER);
+		fileDir.delete();
+
+		// else if the perfect case does not happen, reset the download
+		changeState(UpdaterState.NORMAL);
+	}
+
+	private void startPreInstall() {
+		// set the command for the recovery
+		Process p;
+		try {
+			p = Runtime.getRuntime().exec("su");
+
+			DataOutputStream os = new DataOutputStream(p.getOutputStream());
+			os.writeBytes("rm -f /cache/recovery/command\n");
+			os.writeBytes("rm -f /cache/recovery/extendedcommand\n");
+
+			os.writeBytes("echo '--wipe_cache' >> /cache/recovery/command\n");
+
+			os.writeBytes("echo '--update_package=/"
+					+ VersionParserHelper.RECOVERY_PATH
+					+ VersionParserHelper.UPDATER_FOLDER
+					+ VersionParserHelper.getNameFromVersion(mLatestVersion)
+					+ "' >> /cache/recovery/command\n");
+
+			os.writeBytes("sync\n");
+			os.writeBytes("exit\n");
+			os.flush();
+			p.waitFor();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+		// reboot the device into recovery
+		((PowerManager) getSystemService(POWER_SERVICE)).reboot("recovery");
+	}
+
+	// ************************************************************************************
+	// DOWNLOAD UPDATE
+	// ************************************************************************************
+
+	private void startUpdateDownload() {
+		// use only on WiFi
+		if (isWiFiEnabled()) {
+			// set the download for the latest version on the download manager
+			String fileName = VersionParserHelper
+					.getNameFromVersion(mLatestVersion);
+			Request request = createDownloadRequest(
+					mLatestVersion.getDownloadLink(), fileName,
+					mLatestVersion.getName() + " FP Update");
+			mLatestUpdateDownloadId = mDownloadManager.enqueue(request);
+
+			// save it on the shared preferences
+			savePreference(PREFERENCE_DOWNLOAD_ID, mLatestUpdateDownloadId);
+
+			// change state to download
+			changeState(UpdaterState.DOWNLOAD);
+		} else {
+			Resources resources = this.getResources();
+
+			AlertDialog.Builder disclaimerDialog = new AlertDialog.Builder(this);
+
+			disclaimerDialog.setTitle(resources
+					.getString(R.string.wifiDiscaimerTitle));
+
+			// Setting Dialog Message
+			disclaimerDialog.setMessage(resources
+					.getString(R.string.wifiDiscaimerMessage));
+			disclaimerDialog.setPositiveButton(
+					resources.getString(android.R.string.ok),
+					new DialogInterface.OnClickListener() {
+						public void onClick(DialogInterface dialog, int id) {
+							// do nothing, since the state is still the same
+						}
+					});
+			disclaimerDialog.create();
+			disclaimerDialog.show();
+		}
+	}
+
+	private Request createDownloadRequest(String url, String fileName,
+			String downloadTitle) {
+
+		Request request = new Request(Uri.parse(url));
+		Environment.getExternalStoragePublicDirectory(
+				Environment.getExternalStorageDirectory()
+						+ VersionParserHelper.UPDATER_FOLDER).mkdirs();
+
+		request.setDestinationInExternalPublicDir(
+				VersionParserHelper.UPDATER_FOLDER, fileName);
+		request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
+		request.setAllowedOverRoaming(false);
+
+		request.setTitle(downloadTitle);
+
+		return request;
+	}
+
+	private boolean isWiFiEnabled() {
+
+		ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+
+		boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
+				.isConnectedOrConnecting();
+
+		return isWifi;
+	}
+
+	private void setupDownloadState() {
+		// setup the download state views
+		if (mLatestVersion == null) {
+			// we don't have the lastest.xml so get back to initial state
+			File updateDir = new File(Environment.getExternalStorageDirectory()
+					+ VersionParserHelper.UPDATER_FOLDER);
+
+			updateDir.delete();
+
+			changeState(UpdaterState.NORMAL);
+
+			return;
+		}
+
+		mViewUpdateVersionTitle.setText(mLatestVersion.getName());
+		mViewUpdateVersionText.setText(FAIRPHONE_LABEL
+				+ mLatestVersion.getNumber() + "\n" + ANDROID_LABEL
+				+ mLatestVersion.getAndroid());
+
+		// if there is a download ID on the shared preferences
+		if (mLatestUpdateDownloadId == 0) {
+			mLatestUpdateDownloadId = getLongPreference(PREFERENCE_DOWNLOAD_ID);
+
+			// invalid download Id
+			if (mLatestUpdateDownloadId == 0) {
+
+				changeState(UpdaterState.NORMAL);
+
+				return;
+			}
+		}
+
+		mLatestGroupLla.setVisibility(View.VISIBLE);
+		mViewUpdateButton.setVisibility(View.GONE);
+		mViewMessageText.setVisibility(View.VISIBLE);
+		mViewMessageText.setText(getResources().getString(
+				R.string.downloadMessage));
+
+		updateDownloadFile();
+
+	}
+
+	private void updateDownloadFile() {
+
+		DownloadManager.Query query = new DownloadManager.Query();
+
+		query.setFilterById(mLatestUpdateDownloadId);
+
+		Cursor cursor = mDownloadManager.query(query);
+
+		if (cursor.moveToFirst()) {
+			int columnIndex = cursor
+					.getColumnIndex(DownloadManager.COLUMN_STATUS);
+			int status = cursor.getInt(columnIndex);
+
+			switch (status) {
+			case DownloadManager.STATUS_SUCCESSFUL:
+				changeState(UpdaterState.PREINSTALL);
+				break;
+			case DownloadManager.STATUS_RUNNING:
+				break;
+			case DownloadManager.STATUS_FAILED:
+			case DownloadManager.STATUS_PAUSED:
+			default:
+				changeState(UpdaterState.NORMAL);
+
+				mLatestUpdateDownloadId = 0;
+				savePreference(PREFERENCE_DOWNLOAD_ID, mLatestUpdateDownloadId);
+
+				break;
+			}
+		} else {
+			changeState(UpdaterState.NORMAL);
+		}
+	}
+
+	private void setupInstallationReceivers() {
+		mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+
+		mDownloadBroadCastReceiver = new DownloadBroadCastReceiver();
+	}
+
+	private void registerBroadCastReceiver() {
+		registerReceiver(mDownloadBroadCastReceiver, new IntentFilter(
+				DownloadManager.ACTION_DOWNLOAD_COMPLETE));
+	}
+
+	private void unregisterBroadCastReceiver() {
+		unregisterReceiver(mDownloadBroadCastReceiver);
+	}
+
+	private class DownloadBroadCastReceiver extends BroadcastReceiver {
+
+		@Override
+		public void onReceive(Context context, Intent intent) {
+
+			if (mLatestUpdateDownloadId == 0) {
+				mLatestUpdateDownloadId = getLongPreference(PREFERENCE_DOWNLOAD_ID);
+			}
+
+			updateDownloadFile();
+
+		}
+	}
+
+	// **************************************************************************************************************
+	// HELPERS
+	// **************************************************************************************************************
+
+	public static boolean checkMD5(String md5, File updateFile) {
+
+		if (!updateFile.exists()) {
+			return false;
+		}
+
+		if (md5 == null || md5.equals("") || updateFile == null) {
+			Log.e(TAG, "MD5 String NULL or UpdateFile NULL");
+			return false;
+		}
+
+		String calculatedDigest = calculateMD5(updateFile);
+		if (calculatedDigest == null) {
+			Log.e(TAG, "calculatedDigest NULL");
+			return false;
+		}
+
+		return calculatedDigest.equalsIgnoreCase(md5);
+	}
+
+	public static String calculateMD5(File updateFile) {
+		MessageDigest digest;
+		try {
+			digest = MessageDigest.getInstance("MD5");
+		} catch (NoSuchAlgorithmException e) {
+			Log.e(TAG, "Exception while getting Digest", e);
+			return null;
+		}
+
+		InputStream is;
+		try {
+			is = new FileInputStream(updateFile);
+		} catch (FileNotFoundException e) {
+			Log.e(TAG, "Exception while getting FileInputStream", e);
+			return null;
+		}
+
+		byte[] buffer = new byte[8192];
+		int read;
+		try {
+			while ((read = is.read(buffer)) > 0) {
+				digest.update(buffer, 0, read);
+			}
+			byte[] md5sum = digest.digest();
+			BigInteger bigInt = new BigInteger(1, md5sum);
+			String output = bigInt.toString(16);
+			// Fill to 32 chars
+			output = String.format("%32s", output).replace(' ', '0');
+			return output;
+		} catch (IOException e) {
+			throw new RuntimeException("Unable to process file for MD5", e);
+		} finally {
+			try {
+				is.close();
+			} catch (IOException e) {
+				Log.e(TAG, "Exception on closing MD5 input stream", e);
+			}
+		}
+	}
+}
diff --git a/FairphoneUpdater/src/com/fairphone/updater/RSAUtils.java b/FairphoneUpdater/src/com/fairphone/updater/RSAUtils.java
new file mode 100644
index 0000000..4a9b334
--- /dev/null
+++ b/FairphoneUpdater/src/com/fairphone/updater/RSAUtils.java
@@ -0,0 +1,182 @@
+package com.fairphone.updater;

+

+import android.content.Context;

+import android.util.Base64;

+import android.util.Log;

+

+import java.io.BufferedReader;

+import java.io.ByteArrayInputStream;

+import java.io.ByteArrayOutputStream;

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.FileOutputStream;

+import java.io.IOException;

+import java.io.InputStream;

+import java.io.InputStreamReader;

+import java.security.KeyFactory;

+import java.security.NoSuchAlgorithmException;

+import java.security.PublicKey;

+import java.security.Signature;

+import java.security.cert.Certificate;

+import java.security.cert.CertificateException;

+import java.security.cert.CertificateFactory;

+import java.security.spec.InvalidKeySpecException;

+import java.security.spec.X509EncodedKeySpec;

+import java.util.zip.ZipEntry;

+import java.util.zip.ZipInputStream;

+

+public class RSAUtils {

+

+    private static final String TAG = RSAUtils.class

+            .getSimpleName();

+    

+    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

+    

+    public static PublicKey readPublicKeyFormCertificate(Context context, int certificateResourceId) throws IOException, CertificateException{

+        InputStream in = context.getResources().openRawResource(certificateResourceId);

+        byte[] buff = new byte[4000];

+        int bytesRead;

+        ByteArrayOutputStream out = new ByteArrayOutputStream();

+        while((bytesRead = in.read(buff)) != -1) {

+            out.write(buff, 0, bytesRead);

+            Log.i(TAG, "bytes read: " + bytesRead);

+        }

+

+        byte[] publicKeyBytes = out.toByteArray();

+

+        CertificateFactory cf = CertificateFactory.getInstance("X509");

+        Certificate cert = cf.generateCertificate(new ByteArrayInputStream(publicKeyBytes));

+

+        PublicKey pubKey = cert.getPublicKey();

+        Log.i(TAG, "Public Key Info: ");

+        Log.i(TAG, "Algorithm = " + pubKey.getAlgorithm());

+        Log.i(TAG, "toString = " + pubKey.toString());

+        return pubKey;

+    }

+    

+    public static PublicKey readPublicKeyFromPemFormat(Context context, int publicKeyId)

+            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

+

+        InputStream in = context.getResources().openRawResource(publicKeyId);

+        BufferedReader pemReader = new BufferedReader(new InputStreamReader(in));

+

+        StringBuffer content = new StringBuffer();

+        String line = null;

+        while ((line = pemReader.readLine()) != null) {

+            if (line.indexOf("-----BEGIN PUBLIC KEY-----") != -1) {

+                while ((line = pemReader.readLine()) != null) {

+                    if (line.indexOf("-----END PUBLIC KEY") != -1) {

+                        break;

+                    }

+                    content.append(line.trim());

+                }

+                break;

+            }

+        }

+        if (line == null) {

+            throw new IOException("PUBLIC KEY" + " not found");

+        }

+        Log.i("PUBLIC KEY: ", "PEM content = : " + content.toString());

+

+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

+        

+        return keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decode(content.toString(),

+                Base64.DEFAULT)));

+    }

+

+    public static byte[] readSignature(String input) throws IOException{

+        FileInputStream signStream = new FileInputStream(input);

+        byte[] signBytes = new byte[signStream.available()];

+        signStream.read(signBytes);

+        signStream.close();

+        return signBytes;

+    }

+

+    public static boolean verifySignature(String input, String algorithm, byte[] sign, PublicKey pubKey) throws Exception{

+        Signature sg = Signature.getInstance(algorithm);

+        sg.initVerify(pubKey);

+        Log.i(TAG, "Signature Object Info: ");

+        Log.i(TAG, "Algorithm = "+sg.getAlgorithm());

+        Log.i(TAG, "Provider = "+sg.getProvider());

+

+        FileInputStream in = new FileInputStream(input);

+        byte[] buff = new byte[in.available()];

+        in.read(buff);

+        in.close();

+        

+        sg.update(buff);

+

+        boolean ok = sg.verify(sign);

+        Log.i(TAG, "Verify Processing Info: ");

+        Log.i(TAG, "Verification result = "+ok);

+        return ok;

+    }

+    

+    public static boolean checkFileSignature(Context context, String filePath, String targetPath){

+        boolean valid = false;

+

+        unzip(filePath, targetPath);

+        

+        try {

+            String filename = context.getResources().getString(R.string.versionFilename);

+            String fileXmlExt = context.getResources().getString(R.string.versionFilename_xml);

+            String fileSigExt = context.getResources().getString(R.string.versionFilename_sig);

+            

+            PublicKey pubKey = RSAUtils.readPublicKeyFromPemFormat(context, R.raw.public_key);

+            byte[] sign = RSAUtils.readSignature(targetPath + filename + fileSigExt);

+            valid =  RSAUtils.verifySignature(targetPath + filename + fileXmlExt, RSAUtils.SIGNATURE_ALGORITHM, sign, pubKey);

+        } catch (CertificateException e) {

+            // TODO Auto-generated catch block

+            e.printStackTrace();

+        } catch (IOException e) {

+            // TODO Auto-generated catch block

+            e.printStackTrace();

+        } catch (Exception e) {

+            // TODO Auto-generated catch block

+            e.printStackTrace();

+        }

+        return valid;

+    }

+    

+    private static void unzip(String filePath, String targetPath) {

+        new File(targetPath).mkdirs();

+        try {

+            FileInputStream fin = new FileInputStream(filePath);

+            ZipInputStream zin = new ZipInputStream(fin);

+            ZipEntry ze = null;

+

+            while ((ze = zin.getNextEntry()) != null) {

+                Log.d(TAG, "Unzipping " + ze.getName());

+

+                if (ze.isDirectory()) {

+                    _dirChecker(ze.getName(), targetPath);

+                } else {

+                    FileOutputStream fout = new FileOutputStream(targetPath + ze.getName());

+                    byte buffer[] = new byte[2048];

+

+                    int count = 0;

+

+                    while ((count = zin.read(buffer)) != -1) {

+                        fout.write(buffer, 0, count);

+                    }

+

+                    zin.closeEntry();

+                    fout.close();

+                }

+            }

+            zin.close();

+            fin.close();

+        } catch (Exception e) {

+            Log.e("Decompress", "unzip", e);

+        }

+    }

+    

+    private static void _dirChecker(String dir, String location) {

+        File f = new File(location + dir);

+

+        if (!f.isDirectory()) {

+            f.mkdirs();

+        }

+    }

+

+}

diff --git a/FairphoneUpdater/src/com/fairphone/updater/UpdaterService.java b/FairphoneUpdater/src/com/fairphone/updater/UpdaterService.java
new file mode 100644
index 0000000..45290ec
--- /dev/null
+++ b/FairphoneUpdater/src/com/fairphone/updater/UpdaterService.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2013 Fairphone Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fairphone.updater;
+
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.app.TaskStackBuilder;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.BitmapFactory;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.IBinder;
+import android.support.v4.app.NotificationCompat;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+public class UpdaterService extends Service {
+
+	private static final String TAG = UpdaterService.class.getSimpleName();
+	private static final String PREFERENCE_DATE_LAST_TIME_CHECKED = "LastTimeUpdateChecked";
+	private DownloadManager mDownloadManager;
+	private DownloadBroadCastReceiver mDownloadBroadCastReceiver;
+
+	private long mLatestFileDownloadId;
+
+	private SharedPreferences mSharedPreferences;
+	private SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
+	
+	final static long DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
+	private static final int MAX_DAYS_BEFORE_CHECKING = 8;
+	
+	@Override
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		
+		mSharedPreferences = getApplicationContext().getSharedPreferences(FairphoneUpdater.FAIRPHONE_UPDATER_PREFERENCES, MODE_PRIVATE);
+		
+		if(isFileStillValid()){
+			checkVersionValidation(getApplicationContext());
+		} else if(hasInternetConnection() ){
+			// remove the old file if its still there for some reason
+			removeLatestFile(getApplicationContext());
+	
+			setupDownloadManager();
+	
+			// start the download of the latest file
+			startDownloadLatest();
+		}
+		
+		return Service.START_NOT_STICKY;
+	}
+
+	private void removeLatestFile(Context context) {
+        VersionParserHelper.removeFiles(context);
+        
+		updateLastChecked("2013.01.01 00:00:00");
+	}
+
+	private boolean isFileStillValid() {
+		Date lastTimeChecked = getLastTimeCheckedDate();
+		
+		int diffInDays = (int) ((System.currentTimeMillis() - lastTimeChecked.getTime())/ DAY_IN_MILLIS );
+		
+		return diffInDays < MAX_DAYS_BEFORE_CHECKING;
+	}
+
+	private Date getLastTimeCheckedDate() {
+		
+		String lastTimeDatePreference = mSharedPreferences.getString(PREFERENCE_DATE_LAST_TIME_CHECKED, "2013.01.01 00:00:00");
+		
+		Date lastTimeDate = null;
+		try {
+			lastTimeDate = mDateFormat.parse(lastTimeDatePreference);
+		} catch (ParseException e) {
+			Calendar cal = Calendar.getInstance();
+			cal.add(Calendar.YEAR, -1);
+			
+			lastTimeDate = cal.getTime();
+		}
+		
+		return lastTimeDate;
+	}
+
+	@Override
+	public IBinder onBind(Intent intent) {
+		return null;
+	}
+
+	public void startDownloadLatest() {    
+	    Resources resources = getApplicationContext().getResources();
+	            
+		// set the download for the latest version on the download manager
+		Request request = createDownloadRequest(resources.getString(R.string.downloadUrl), resources.getString(R.string.versionFilename) + resources.getString(R.string.versionFilename_zip));
+		mLatestFileDownloadId = mDownloadManager.enqueue(request);
+	}
+
+	private void setNotification() {
+
+		Context context = getApplicationContext();
+
+		NotificationManager manager = (NotificationManager) context
+				.getSystemService(Context.NOTIFICATION_SERVICE);
+
+		NotificationCompat.Builder builder = new NotificationCompat.Builder(
+				context)
+				.setSmallIcon(R.drawable.fairphone_updater_tray_icon_small)
+				.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.fairphone_updater_tray_icon))
+				.setContentTitle(
+						context.getResources().getString(R.string.app_name))
+				.setContentText(getResources().getString(R.string.fairphoneUpdateMessage));
+
+		Intent resultIntent = new Intent(context, FairphoneUpdater.class);
+		TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
+
+		stackBuilder.addParentStack(FairphoneUpdater.class);
+
+		stackBuilder.addNextIntent(resultIntent);
+		PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
+				PendingIntent.FLAG_UPDATE_CURRENT);
+
+		builder.setContentIntent(resultPendingIntent);
+
+		Notification notificationWhileRunnig = builder.build();
+		
+		// Add notification
+		manager.notify(0, notificationWhileRunnig);
+
+	}
+
+	private Request createDownloadRequest(String url, String fileName) {
+
+	    
+		Request request = new Request(Uri.parse(url));
+		Environment.getExternalStoragePublicDirectory(
+				Environment.getExternalStorageDirectory()
+						+ VersionParserHelper.UPDATER_FOLDER).mkdirs();
+
+		request.setDestinationInExternalPublicDir(
+				VersionParserHelper.UPDATER_FOLDER, fileName);
+		request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
+		request.setAllowedOverRoaming(false);
+		
+		Resources resources = getApplicationContext().getResources();
+		request.setTitle(resources.getString(R.string.downloadUpdateTitle));
+
+		return request;
+	}
+
+	private boolean hasInternetConnection() {
+
+		ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+
+		boolean is3g = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
+				.isConnectedOrConnecting();
+
+		boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
+				.isConnectedOrConnecting();
+
+		return isWifi || is3g;
+	}
+
+	private void setupDownloadManager() {
+		mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+
+		mDownloadBroadCastReceiver = new DownloadBroadCastReceiver();
+
+		getApplicationContext().registerReceiver(mDownloadBroadCastReceiver,
+				new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
+	}
+
+	private void removeBroadcastReceiver() {
+		getApplicationContext().unregisterReceiver(mDownloadBroadCastReceiver);
+	}
+	
+	private void checkVersionValidation(Context context){
+	    
+		Version latestVersion = VersionParserHelper
+				.getLastestVersion(getApplicationContext());
+		Version currentVersion = VersionParserHelper
+				.getDeviceVersion(getApplicationContext());
+		
+		if(latestVersion != null){
+			
+			String versionName = null;
+			String versionNumber = null;
+			String versionUrl = null;
+			String versionMd5 = null;
+			String versionAndroid = null;
+			
+			if(latestVersion.isNewerVersionThan(currentVersion)){
+				// save the version in the share preferences
+				versionName = latestVersion.getName();
+				versionNumber = latestVersion.getNumber();
+				versionUrl = latestVersion.getDownloadLink();
+				versionMd5 = latestVersion.getMd5Sum();
+				versionAndroid = latestVersion.getAndroid();
+				
+				setNotification();
+			} else {
+				VersionParserHelper.removeLatestVersionFile(getApplicationContext());
+			}
+			
+			Editor editor = mSharedPreferences.edit();
+			
+			editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_NAME, versionName);
+			editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_NUMBER, versionNumber);
+			editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_MD5_SUM, versionMd5);
+			editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_URL, versionUrl);
+			editor.putString(FairphoneUpdater.PREFERENCE_NEW_VERSION_ANDROID, versionAndroid);
+			
+			editor.commit();
+    		
+    		removeLatestFileDownload(context);
+		}
+	}
+
+    private void removeLatestFileDownload(Context context) {
+        if(mLatestFileDownloadId != 0){
+        	mDownloadManager.remove(mLatestFileDownloadId);
+        	mLatestFileDownloadId = 0;
+        }
+        VersionParserHelper.removeFiles(context);
+    }
+
+	private float parseVersion(String number) {
+		String finalNumber = number.replaceAll("\\.", "");
+		return Float.parseFloat(finalNumber);
+	}
+
+	private void updateLastChecked(String date) {
+        Editor editor = mSharedPreferences.edit();
+        editor.putString(PREFERENCE_DATE_LAST_TIME_CHECKED, date);
+        
+        editor.commit();
+    }
+
+    private class DownloadBroadCastReceiver extends BroadcastReceiver {
+
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			DownloadManager.Query query = new DownloadManager.Query();
+
+			query.setFilterById(mLatestFileDownloadId);
+			Cursor cursor = mDownloadManager.query(query);
+			
+			if (cursor.moveToFirst()) {
+				int columnIndex = cursor
+						.getColumnIndex(DownloadManager.COLUMN_STATUS);
+				int status = cursor.getInt(columnIndex);
+
+				if (status == DownloadManager.STATUS_SUCCESSFUL) {
+				    
+				    String filePath = mDownloadManager.getUriForDownloadedFile(
+				            mLatestFileDownloadId).getPath();
+				    
+				    String targetPath = Environment.getExternalStorageDirectory()
+		                    + VersionParserHelper.UPDATER_FOLDER;
+                    
+				    if(RSAUtils.checkFileSignature(context, filePath, targetPath)){
+    				    updateLastChecked(mDateFormat.format(Calendar.getInstance().getTime()));
+    					checkVersionValidation(context);
+					}else{
+					    //invalid file
+					    removeLatestFileDownload(context);
+					}
+				}
+			}
+
+			cursor.close();
+
+			removeBroadcastReceiver();
+		}
+	}
+}
\ No newline at end of file
diff --git a/FairphoneUpdater/src/com/fairphone/updater/Version.java b/FairphoneUpdater/src/com/fairphone/updater/Version.java
new file mode 100644
index 0000000..d129eb4
--- /dev/null
+++ b/FairphoneUpdater/src/com/fairphone/updater/Version.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2013 Fairphone Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fairphone.updater;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Resources;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class Version {
+	public static final String FAIRPHONE_UPDATE_VERSION_NUMBER = "FairphoneUpdateVersionNumber";
+	public static final String FAIRPHONE_UPDATE_VERSION_NAME = "FairphoneUpdateVersionName";
+	public static final String FAIRPHONE_UPDATE_VERSION_ANDROID = "FairphoneUpdateVersionAndroid";
+	public static final String FAIRPHONE_UPDATE_VERSION_DOWNLOAD_LINK = "FairphoneUpdateVersionDownloadLink";
+	public static final String FAIRPHONE_UPDATE_VERSION_MD5 = "FairphoneUpdateVersionMD5";
+
+	private String mNumber;
+	private String mName;
+	private String mAndroid;
+	private String mDownloadLink;
+	private String mMd5Sum;
+	private String mChangeLog;
+
+	public static Version getVersionFromSharedPreferences(Context context) {
+		Version version = new Version();
+		SharedPreferences sharedPrefs = context.getSharedPreferences(
+				FairphoneUpdater.FAIRPHONE_UPDATER_PREFERENCES,
+				Context.MODE_PRIVATE);
+		Resources resources = context.getResources();
+
+		String defaultVersionNumber = resources
+				.getString(R.string.defaultVersionNumber);
+		version.setNumber(sharedPrefs.getString(
+				FAIRPHONE_UPDATE_VERSION_NUMBER, defaultVersionNumber));
+
+		String defaultVersionName = resources
+				.getString(R.string.defaultVersionName);
+		version.setName(sharedPrefs.getString(FAIRPHONE_UPDATE_VERSION_NAME,
+				defaultVersionName));
+
+		String defaultVersionAndroid = resources
+				.getString(R.string.defaultAndroidVersionNumber);
+		version.setAndroid(sharedPrefs.getString(
+				FAIRPHONE_UPDATE_VERSION_ANDROID, defaultVersionAndroid));
+
+		version.setDownloadLink(sharedPrefs.getString(
+				FAIRPHONE_UPDATE_VERSION_DOWNLOAD_LINK, ""));
+		version.setMd5Sum(sharedPrefs.getString(FAIRPHONE_UPDATE_VERSION_MD5,
+				""));
+
+		if (TextUtils.isEmpty(version.getMd5Sum())
+				|| TextUtils.isEmpty(version.getMd5Sum())) {
+			return null;
+		}
+		return version;
+	}
+
+	public void saveToSharedPreferences(Context context) {
+		SharedPreferences sharedPrefs = context.getSharedPreferences(
+				FairphoneUpdater.FAIRPHONE_UPDATER_PREFERENCES,
+				Context.MODE_PRIVATE);
+
+		Editor editor = sharedPrefs.edit();
+		editor.putString(FAIRPHONE_UPDATE_VERSION_NUMBER, getNumber());
+		editor.putString(FAIRPHONE_UPDATE_VERSION_NAME, getName());
+		editor.putString(FAIRPHONE_UPDATE_VERSION_ANDROID, getAndroid());
+		editor.putString(FAIRPHONE_UPDATE_VERSION_DOWNLOAD_LINK,
+				getDownloadLink());
+		editor.putString(FAIRPHONE_UPDATE_VERSION_MD5, getMd5Sum());
+		editor.commit();
+	}
+
+	public String getNumber() {
+		return mNumber;
+	}
+
+	public void setNumber(String number) {
+		this.mNumber = number;
+	}
+
+	public String getName() {
+		return mName;
+	}
+
+	public void setName(String mName) {
+		this.mName = mName;
+	}
+
+	public String getDownloadLink() {
+		return mDownloadLink;
+	}
+
+	public void setDownloadLink(String mDownloadLink) {
+		this.mDownloadLink = mDownloadLink;
+	}
+
+	public String getMd5Sum() {
+		return mMd5Sum;
+	}
+
+	public void setMd5Sum(String mMd5Sum) {
+		this.mMd5Sum = mMd5Sum;
+	}
+
+	public String getChangeLog() {
+		return mChangeLog;
+	}
+
+	public void setChangeLog(String mChangeLog) {
+		this.mChangeLog = mChangeLog;
+	}
+
+	public String getAndroid() {
+		return mAndroid;
+	}
+
+	public void setAndroid(String mAndroid) {
+		this.mAndroid = mAndroid;
+	}
+
+	public boolean isNewerVersionThan(Version version) {
+
+		boolean result = false;
+
+		try {
+			result = Version
+					.isNewVersion(version.getNumber(), this.getNumber());
+		} catch (Throwable t) {
+			Log.e(Version.class.getSimpleName(), "Invalid Number for Version",
+					t);
+		}
+
+		return result;
+	}
+
+	private static boolean isNewVersion(String versionA, String versionB)
+			throws IllegalArgumentException {
+
+		int[] versionAints = getVersionInt(versionA);
+		int[] versionBints = getVersionInt(versionB);
+
+		if (versionAints[0] == versionBints[0]) {
+			return versionAints[1] < versionBints[1];
+		}
+
+		return versionAints[0] < versionBints[0];
+	}
+
+	private static int[] getVersionInt(String version) {
+
+		if (version == null) {
+			throw new IllegalArgumentException("String is null");
+		}
+
+		String[] intStrs = version.split("\\.");
+
+		if (intStrs == null || intStrs.length != 2) {
+			throw new IllegalArgumentException("String " + version
+					+ " not have the correct format [X.Y]");
+		}
+
+		int[] ints = new int[2];
+
+		try {
+			ints[0] = Integer.parseInt(intStrs[0]);
+			ints[1] = Integer.parseInt(intStrs[1]);
+		} catch (Throwable t) {
+			throw new IllegalArgumentException(
+					"String "
+							+ version
+							+ " should contain numbers separated by a dot [ReleaseNumber.VersionNumber]");
+		}
+
+		return ints;
+	}
+}
diff --git a/FairphoneUpdater/src/com/fairphone/updater/VersionParserHelper.java b/FairphoneUpdater/src/com/fairphone/updater/VersionParserHelper.java
new file mode 100644
index 0000000..e1b6e4e
--- /dev/null
+++ b/FairphoneUpdater/src/com/fairphone/updater/VersionParserHelper.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2013 Fairphone Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.fairphone.updater;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import android.content.Context;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.NoSuchElementException;
+import java.util.Scanner;
+
+public class VersionParserHelper {
+
+	private static final String TAG = VersionParserHelper.class.getSimpleName();
+	
+	public static final String RECOVERY_PATH = "sdcard";
+	public static final String UPDATER_FOLDER = "/updater/";
+	
+	private static final String CURRENT_FAIRPHONE_VERSION_NAME = "fairphone.ota.version.name";
+	private static final String CURRENT_FAIRPHONE_VERSION = "fairphone.ota.version";
+	private static final String CURRENT_ANDROID_VERSION = "fairphone.ota.android";
+	
+	public static String getNameFromVersion(Version version) {
+		return "fp_update_" + version.getNumber() + ".zip";
+	}
+	
+	public static Version getDeviceVersion(Context context) {
+
+		Version version = new Version();
+		version.setNumber(getSystemData(context, CURRENT_FAIRPHONE_VERSION));
+		version.setName(getSystemData(context, CURRENT_FAIRPHONE_VERSION_NAME));
+		version.setAndroid(getSystemData(context, CURRENT_ANDROID_VERSION));
+
+		return version;
+	}
+	
+	public static String getSystemData(Context context, String property) {
+
+		if (property.equals(CURRENT_FAIRPHONE_VERSION)){
+			return getprop(CURRENT_FAIRPHONE_VERSION, context.getResources().getString(R.string.defaultVersionNumber));
+		}
+		if (property.equals(CURRENT_FAIRPHONE_VERSION_NAME)){
+			return getprop(CURRENT_FAIRPHONE_VERSION_NAME, context.getResources().getString(R.string.defaultVersionName));
+		}
+		if (property.equals(CURRENT_ANDROID_VERSION)){
+			return getprop(CURRENT_ANDROID_VERSION, context.getResources().getString(R.string.defaultAndroidVersionNumber));
+		}
+
+		return null;
+	}
+	
+	public static void removeLatestVersionFile(Context context){
+		File file = new File(Environment.getExternalStorageDirectory() + UPDATER_FOLDER + context.getResources().getString(R.string.versionFilename));
+		
+		if(file.exists()){
+			file.delete();
+		}
+	}
+	
+	public static Version getLastestVersion(Context context) {
+
+		Version latest = Version.getVersionFromSharedPreferences(context);
+        
+		if(latest == null){
+		    
+		    String filePath = Environment.getExternalStorageDirectory()
+	                + VersionParserHelper.UPDATER_FOLDER
+	                + context.getResources().getString(R.string.versionFilename);
+    		// check the /storage/sdcard0/updater/latest.xml
+    		File file = new File(filePath + context.getResources().getString(R.string.versionFilename_xml));
+    
+    		if (file.exists()) {
+    			try {
+    				latest = parseLatestXML(context, file);
+    			} catch (XmlPullParserException e) {
+    				Log.e(TAG, "Could not start the XML parser", e);
+    			} catch (IOException e) {
+    				Log.e(TAG, "Invalid data in File", e);
+    				// remove the files
+    				removeFiles(context);
+    			}
+    		}
+		}
+
+		return latest;
+	}
+	
+	private static Version parseLatestXML(Context context, File latestFile)
+			throws XmlPullParserException, IOException {
+
+		Version version = null;
+
+		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+		factory.setNamespaceAware(true);
+
+		FileInputStream fis = new FileInputStream(latestFile);
+
+		XmlPullParser xpp = factory.newPullParser();
+
+		xpp.setInput(new InputStreamReader(fis));
+
+		int eventType = xpp.getEventType();
+
+		while (eventType != XmlPullParser.END_DOCUMENT) {
+			String tagName = null;
+			switch (eventType) {
+			case XmlPullParser.START_DOCUMENT:
+				break;
+			case XmlPullParser.START_TAG:
+				tagName = xpp.getName();
+
+				if (tagName.equalsIgnoreCase("version")) {
+					version = new Version();
+					version.setNumber(xpp.getAttributeValue(0));
+				} else if (version != null) {
+					if (tagName.equalsIgnoreCase("name")) {
+						version.setName(xpp.nextText());
+					} else if (tagName.equalsIgnoreCase("android")) {
+						version.setAndroid(xpp.nextText());
+					} else if (tagName.equalsIgnoreCase("md5sum")) {
+						version.setMd5Sum(xpp.nextText());
+					} else if (tagName.equalsIgnoreCase("link")) {
+						version.setDownloadLink(xpp.nextText());
+					}
+				}
+
+				break;
+			}
+			
+			eventType = xpp.next();
+		}
+
+		if (version == null 
+				|| version.getNumber() == null
+				|| version.getName() == null
+				|| version.getAndroid() == null
+				|| version.getDownloadLink() == null) {
+			
+			Log.i(TAG, "Invalid data in version file");
+			
+			version = null;
+		}else {
+		    version.saveToSharedPreferences(context);
+		}
+
+		return version;
+	}
+	
+	private static String getprop(String name, String defaultValue) {
+        ProcessBuilder pb = new ProcessBuilder("/system/bin/getprop", name);
+        pb.redirectErrorStream(true);
+        
+        Process p = null;
+        InputStream is = null;
+        try {
+            p = pb.start();
+            is = p.getInputStream();
+            Scanner scan = new Scanner(is);
+            scan.useDelimiter("\n");
+            String prop = scan.next();
+            if (prop.length() == 0) {
+                return defaultValue;
+            }
+            return prop;
+        } catch (NoSuchElementException e) {
+            return defaultValue;
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (is != null) {
+                try { is.close(); }
+                catch (Exception e) { }
+            }
+        }
+        return defaultValue;
+    }
+	
+	public static void removeFiles(Context context) {
+        String filePath = Environment.getExternalStorageDirectory()
+                + VersionParserHelper.UPDATER_FOLDER
+                + context.getResources().getString(R.string.versionFilename);
+
+        removeFile(filePath + context.getResources().getString(R.string.versionFilename_zip));
+        removeFile(filePath + context.getResources().getString(R.string.versionFilename_xml));
+        removeFile(filePath + context.getResources().getString(R.string.versionFilename_sig));
+    }
+
+    private static void removeFile(String filePath) {
+        File file = new File(filePath);
+        if(file.exists()){
+            file.delete();
+        }
+    }
+    
+    
+    
+}