Initial commit for GitHub
diff --git a/FairphoneHome/.classpath b/FairphoneHome/.classpath
new file mode 100644
index 0000000..55d52a8
--- /dev/null
+++ b/FairphoneHome/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry exported="true" kind="lib" path="libs/RootTools-3.3.jar"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry exported="true" 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/FairphoneHome/.project b/FairphoneHome/.project
new file mode 100644
index 0000000..26f37c3
--- /dev/null
+++ b/FairphoneHome/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>FairPhoneHome</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/FairphoneHome/.settings/org.eclipse.jdt.core.prefs b/FairphoneHome/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b080d2d
--- /dev/null
+++ b/FairphoneHome/.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/FairphoneHome/Android.mk b/FairphoneHome/Android.mk
new file mode 100644
index 0000000..2924826
--- /dev/null
+++ b/FairphoneHome/Android.mk
@@ -0,0 +1,43 @@
+#
+# 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 fairphonelib roottoolslib
+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 := FairPhoneHome
+LOCAL_CERTIFICATE := platform
+
+LOCAL_OVERRIDES_PACKAGES := Launcher2
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+include $(BUILD_PACKAGE)
+##################################################
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := fairphonelib:libs/acra-4.4.0.jar roottoolslib:libs/RootTools-3.3.jar
+
+include $(BUILD_MULTI_PREBUILT)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/FairphoneHome/AndroidManifest.xml b/FairphoneHome/AndroidManifest.xml
new file mode 100644
index 0000000..d67800d
--- /dev/null
+++ b/FairphoneHome/AndroidManifest.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.fairphone.launcher">
+    
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="17"/>
+
+    <!-- <original-package android:name="com.android.launcher2" />  -->
+    
+    <uses-permission android:name="android.permission.GET_TASKS"/>
+    
+    <permission
+        android:name="com.android.launcher.permission.PRELOAD_WORKSPACE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="system|signature" />
+    <permission
+        android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_install_shortcut"
+        android:description="@string/permdesc_install_shortcut" />
+    <permission
+        android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_uninstall_shortcut"
+        android:description="@string/permdesc_uninstall_shortcut"/>
+    <permission
+        android:name="com.android.launcher.permission.READ_SETTINGS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_read_settings"
+        android:description="@string/permdesc_read_settings"/>
+    <permission
+        android:name="com.android.launcher.permission.WRITE_SETTINGS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_write_settings"
+        android:description="@string/permdesc_write_settings"/>
+
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
+    <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    
+    <uses-permission android:name="android.permission.ACCESS_SUPERUSER"/>
+	<uses-permission android:name="android.permission.REBOOT"/>
+    <!-- Internet access is required for sending crash reports with ACRA -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    
+    <application
+        android:name="org.fairphone.launcher.FairphoneApplication"
+        android:label="@string/application_name"
+        android:taskAffinity="org.fairphone.launcher.Launcher"
+        android:icon="@mipmap/icon_launcher_home"
+        android:hardwareAccelerated="true"
+        android:largeHeap="@bool/config_largeHeap"
+        android:supportsRtl="true">
+        
+        <activity
+            android:name="org.fairphone.launcher.Launcher"
+            android:label="@string/application_name"
+            android:launchMode="singleTask"
+            android:clearTaskOnLaunch="true"
+            android:stateNotNeeded="true"
+            android:theme="@style/Theme"
+            android:windowSoftInputMode="adjustPan"
+            android:taskAffinity="org.fairphone.launcher.Launcher"
+            android:screenOrientation="nosensor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.HOME" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY"/>
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="org.fairphone.launcher.WallpaperChooser"
+            android:theme="@style/Theme.WallpaperPicker"
+            android:label="@string/pick_wallpaper"
+            android:icon="@mipmap/ic_launcher_wallpaper"
+            android:finishOnCloseSystemDialogs="true"
+            android:process=":wallpaper_chooser">
+            <intent-filter>
+                <action android:name="android.intent.action.SET_WALLPAPER" />
+                <category android:name="android.intent.category.DEFAULT" />
+                
+            </intent-filter>
+            <meta-data android:name="android.wallpaper.preview"
+                android:resource="@xml/wallpaper_picker_preview" />
+        </activity>
+        
+        <activity
+            android:name="org.fairphone.launcher.edgeswipe.edit.EditFavoritesActivity"
+            android:theme="@style/Theme"
+            android:screenOrientation="portrait" />
+        
+        <activity
+            android:name="org.fairphone.settings.SettingsActivity"
+            android:screenOrientation="portrait" />
+        
+        <activity
+            android:name="org.fairphone.oobe.OOBEActivity"
+            android:theme="@style/OOBETheme"
+            android:screenOrientation="portrait" />
+               
+        <activity android:name="DialogAppSwitcherActivity" android:label="@string/app_switcher_dialog_name" android:theme="@android:style/Theme.Dialog"/>
+    
+        <!-- Widget -->
+	    <receiver android:icon="@drawable/all_apps_button_icon"
+	              android:label="@string/app_switcher_name"
+	              android:name="org.fairphone.widgets.appswitcher.WidgetProvider">
+	      
+	      <intent-filter>
+	        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+	      </intent-filter>
+	      
+	      <meta-data android:name="android.appwidget.provider"
+	                 android:resource="@xml/widget_provider" />
+	    </receiver>
+	    
+	    <receiver android:icon="@drawable/all_apps_button_icon"
+	              android:label="@string/google_apps_installer_name"
+	              android:name="org.fairphone.widgets.gapps.GoogleAppsInstallerWidget">
+	      
+	       <intent-filter>
+	        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+	      </intent-filter>
+	      
+	      <meta-data android:name="android.appwidget.provider"
+	                 android:resource="@xml/google_apps_widget" />
+	    </receiver>
+	    
+	    <!-- Service 
+	    <service android:name="org.fairphone.widgets.appswitcher.TimerService" 
+	        	 android:permission="android.permission.BIND_REMOTEVIEWS" />
+	    <service android:name="org.fairphone.widgets.appswitcher.WidgetServiceRecentApps"
+	             android:permission="android.permission.BIND_REMOTEVIEWS" />
+	    <service android:name="org.fairphone.widgets.appswitcher.WidgetServiceMostUsedApps"
+	             android:permission="android.permission.BIND_REMOTEVIEWS" />
+        -->
+        <!-- Intent received used to prepopulate the default workspace. -->
+        <receiver
+            android:name="org.fairphone.launcher.PreloadReceiver"
+            android:permission="com.android.launcher.permission.PRELOAD_WORKSPACE">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.PRELOAD_WORKSPACE" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intent received used to install shortcuts from other applications -->
+        <receiver
+            android:name="org.fairphone.launcher.InstallShortcutReceiver"
+            android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intent received used to uninstall shortcuts from other applications -->
+        <receiver
+            android:name="org.fairphone.launcher.UninstallShortcutReceiver"
+            android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT" />
+            </intent-filter>
+        </receiver>
+
+        <!-- New user initialization; set up initial wallpaper -->
+        <receiver
+            android:name="org.fairphone.launcher.UserInitializeReceiver"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="android.intent.action.USER_INITIALIZE" />
+            </intent-filter>
+        </receiver>
+        
+        <!-- The settings provider contains Home's data, like the workspace favorites -->
+        <provider
+            android:name="org.fairphone.launcher.LauncherProvider"
+            android:authorities="org.fairphone.launcher.settings"
+            android:exported="true"
+            android:writePermission="com.android.launcher.permission.WRITE_SETTINGS"
+            android:readPermission="com.android.launcher.permission.READ_SETTINGS" />
+
+        <meta-data android:name="android.nfc.disable_beam_default"
+                       android:value="true" />
+    </application>
+</manifest>
diff --git a/FairphoneHome/CleanSpec.mk b/FairphoneHome/CleanSpec.mk
new file mode 100644
index 0000000..d043660
--- /dev/null
+++ b/FairphoneHome/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/FairphoneHome_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneHome_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneHome_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneHome_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FairphoneHome_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/FairphoneHome.apk)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/FairphoneHome/MODULE_LICENSE_APACHE2 b/FairphoneHome/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/FairphoneHome/MODULE_LICENSE_APACHE2
diff --git a/FairphoneHome/NOTICE b/FairphoneHome/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/FairphoneHome/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/FairphoneHome/assets/fonts/YWFT-Hannah-Regular.ttf b/FairphoneHome/assets/fonts/YWFT-Hannah-Regular.ttf
new file mode 100644
index 0000000..ea8eed7
--- /dev/null
+++ b/FairphoneHome/assets/fonts/YWFT-Hannah-Regular.ttf
Binary files differ
diff --git a/FairphoneHome/bin/AndroidManifest.xml b/FairphoneHome/bin/AndroidManifest.xml
new file mode 100644
index 0000000..d67800d
--- /dev/null
+++ b/FairphoneHome/bin/AndroidManifest.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.fairphone.launcher">
+    
+    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="17"/>
+
+    <!-- <original-package android:name="com.android.launcher2" />  -->
+    
+    <uses-permission android:name="android.permission.GET_TASKS"/>
+    
+    <permission
+        android:name="com.android.launcher.permission.PRELOAD_WORKSPACE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="system|signature" />
+    <permission
+        android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_install_shortcut"
+        android:description="@string/permdesc_install_shortcut" />
+    <permission
+        android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="dangerous"
+        android:label="@string/permlab_uninstall_shortcut"
+        android:description="@string/permdesc_uninstall_shortcut"/>
+    <permission
+        android:name="com.android.launcher.permission.READ_SETTINGS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_read_settings"
+        android:description="@string/permdesc_read_settings"/>
+    <permission
+        android:name="com.android.launcher.permission.WRITE_SETTINGS"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_write_settings"
+        android:description="@string/permdesc_write_settings"/>
+
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
+    <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    
+    <uses-permission android:name="android.permission.ACCESS_SUPERUSER"/>
+	<uses-permission android:name="android.permission.REBOOT"/>
+    <!-- Internet access is required for sending crash reports with ACRA -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    
+    <application
+        android:name="org.fairphone.launcher.FairphoneApplication"
+        android:label="@string/application_name"
+        android:taskAffinity="org.fairphone.launcher.Launcher"
+        android:icon="@mipmap/icon_launcher_home"
+        android:hardwareAccelerated="true"
+        android:largeHeap="@bool/config_largeHeap"
+        android:supportsRtl="true">
+        
+        <activity
+            android:name="org.fairphone.launcher.Launcher"
+            android:label="@string/application_name"
+            android:launchMode="singleTask"
+            android:clearTaskOnLaunch="true"
+            android:stateNotNeeded="true"
+            android:theme="@style/Theme"
+            android:windowSoftInputMode="adjustPan"
+            android:taskAffinity="org.fairphone.launcher.Launcher"
+            android:screenOrientation="nosensor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.HOME" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY"/>
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="org.fairphone.launcher.WallpaperChooser"
+            android:theme="@style/Theme.WallpaperPicker"
+            android:label="@string/pick_wallpaper"
+            android:icon="@mipmap/ic_launcher_wallpaper"
+            android:finishOnCloseSystemDialogs="true"
+            android:process=":wallpaper_chooser">
+            <intent-filter>
+                <action android:name="android.intent.action.SET_WALLPAPER" />
+                <category android:name="android.intent.category.DEFAULT" />
+                
+            </intent-filter>
+            <meta-data android:name="android.wallpaper.preview"
+                android:resource="@xml/wallpaper_picker_preview" />
+        </activity>
+        
+        <activity
+            android:name="org.fairphone.launcher.edgeswipe.edit.EditFavoritesActivity"
+            android:theme="@style/Theme"
+            android:screenOrientation="portrait" />
+        
+        <activity
+            android:name="org.fairphone.settings.SettingsActivity"
+            android:screenOrientation="portrait" />
+        
+        <activity
+            android:name="org.fairphone.oobe.OOBEActivity"
+            android:theme="@style/OOBETheme"
+            android:screenOrientation="portrait" />
+               
+        <activity android:name="DialogAppSwitcherActivity" android:label="@string/app_switcher_dialog_name" android:theme="@android:style/Theme.Dialog"/>
+    
+        <!-- Widget -->
+	    <receiver android:icon="@drawable/all_apps_button_icon"
+	              android:label="@string/app_switcher_name"
+	              android:name="org.fairphone.widgets.appswitcher.WidgetProvider">
+	      
+	      <intent-filter>
+	        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+	      </intent-filter>
+	      
+	      <meta-data android:name="android.appwidget.provider"
+	                 android:resource="@xml/widget_provider" />
+	    </receiver>
+	    
+	    <receiver android:icon="@drawable/all_apps_button_icon"
+	              android:label="@string/google_apps_installer_name"
+	              android:name="org.fairphone.widgets.gapps.GoogleAppsInstallerWidget">
+	      
+	       <intent-filter>
+	        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+	      </intent-filter>
+	      
+	      <meta-data android:name="android.appwidget.provider"
+	                 android:resource="@xml/google_apps_widget" />
+	    </receiver>
+	    
+	    <!-- Service 
+	    <service android:name="org.fairphone.widgets.appswitcher.TimerService" 
+	        	 android:permission="android.permission.BIND_REMOTEVIEWS" />
+	    <service android:name="org.fairphone.widgets.appswitcher.WidgetServiceRecentApps"
+	             android:permission="android.permission.BIND_REMOTEVIEWS" />
+	    <service android:name="org.fairphone.widgets.appswitcher.WidgetServiceMostUsedApps"
+	             android:permission="android.permission.BIND_REMOTEVIEWS" />
+        -->
+        <!-- Intent received used to prepopulate the default workspace. -->
+        <receiver
+            android:name="org.fairphone.launcher.PreloadReceiver"
+            android:permission="com.android.launcher.permission.PRELOAD_WORKSPACE">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.PRELOAD_WORKSPACE" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intent received used to install shortcuts from other applications -->
+        <receiver
+            android:name="org.fairphone.launcher.InstallShortcutReceiver"
+            android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Intent received used to uninstall shortcuts from other applications -->
+        <receiver
+            android:name="org.fairphone.launcher.UninstallShortcutReceiver"
+            android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT" />
+            </intent-filter>
+        </receiver>
+
+        <!-- New user initialization; set up initial wallpaper -->
+        <receiver
+            android:name="org.fairphone.launcher.UserInitializeReceiver"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="android.intent.action.USER_INITIALIZE" />
+            </intent-filter>
+        </receiver>
+        
+        <!-- The settings provider contains Home's data, like the workspace favorites -->
+        <provider
+            android:name="org.fairphone.launcher.LauncherProvider"
+            android:authorities="org.fairphone.launcher.settings"
+            android:exported="true"
+            android:writePermission="com.android.launcher.permission.WRITE_SETTINGS"
+            android:readPermission="com.android.launcher.permission.READ_SETTINGS" />
+
+        <meta-data android:name="android.nfc.disable_beam_default"
+                       android:value="true" />
+    </application>
+</manifest>
diff --git a/FairphoneHome/bin/FairPhoneHome.apk b/FairphoneHome/bin/FairPhoneHome.apk
new file mode 100644
index 0000000..67b92f3
--- /dev/null
+++ b/FairphoneHome/bin/FairPhoneHome.apk
Binary files differ
diff --git a/FairphoneHome/bin/classes.dex b/FairphoneHome/bin/classes.dex
new file mode 100644
index 0000000..2f40492
--- /dev/null
+++ b/FairphoneHome/bin/classes.dex
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AccessibleTabView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AccessibleTabView.class
new file mode 100644
index 0000000..b8f62f9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AccessibleTabView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AddAdapter$ListItem.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AddAdapter$ListItem.class
new file mode 100644
index 0000000..a7b923d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AddAdapter$ListItem.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AddAdapter.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AddAdapter.class
new file mode 100644
index 0000000..e2fbe93
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AddAdapter.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Alarm.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Alarm.class
new file mode 100644
index 0000000..af932b9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Alarm.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AllAppsList.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AllAppsList.class
new file mode 100644
index 0000000..99d7164
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AllAppsList.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame$1.class
new file mode 100644
index 0000000..0a4d0f2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame$2.class
new file mode 100644
index 0000000..e4ade11
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame.class
new file mode 100644
index 0000000..a0c4285
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppWidgetResizeFrame.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/ApplicationInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/ApplicationInfo.class
new file mode 100644
index 0000000..d1a0f29
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/ApplicationInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeAsyncTask.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeAsyncTask.class
new file mode 100644
index 0000000..e78173c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeAsyncTask.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$1.class
new file mode 100644
index 0000000..fffea21
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$2.class
new file mode 100644
index 0000000..34d4235
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$3.class
new file mode 100644
index 0000000..2830558
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$4.class
new file mode 100644
index 0000000..fa356c8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$5.class
new file mode 100644
index 0000000..3f371c8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$6.class
new file mode 100644
index 0000000..dea129a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$7.class
new file mode 100644
index 0000000..33daead
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$ContentType.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$ContentType.class
new file mode 100644
index 0000000..2343e34
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView$ContentType.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView.class
new file mode 100644
index 0000000..194e126
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizePagedView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$1.class
new file mode 100644
index 0000000..ff198db
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$2.class
new file mode 100644
index 0000000..32d649a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$1.class
new file mode 100644
index 0000000..41d394b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$2.class
new file mode 100644
index 0000000..02037be
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$3.class
new file mode 100644
index 0000000..68c8542
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3.class
new file mode 100644
index 0000000..3386663
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost.class
new file mode 100644
index 0000000..93414c6
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabHost.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabKeyEventListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabKeyEventListener.class
new file mode 100644
index 0000000..fd89c4a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AppsCustomizeTabKeyEventListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskCallback.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskCallback.class
new file mode 100644
index 0000000..6b40b11
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskCallback.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskPageData$Type.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskPageData$Type.class
new file mode 100644
index 0000000..a23707f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskPageData$Type.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskPageData.class b/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskPageData.class
new file mode 100644
index 0000000..3c0c049
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/AsyncTaskPageData.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/BitmapCache.class b/FairphoneHome/bin/classes/org/fairphone/launcher/BitmapCache.class
new file mode 100644
index 0000000..481a739
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/BitmapCache.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/BubbleTextView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/BubbleTextView.class
new file mode 100644
index 0000000..b2319bc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/BubbleTextView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/BuildConfig.class b/FairphoneHome/bin/classes/org/fairphone/launcher/BuildConfig.class
new file mode 100644
index 0000000..6ffcd55
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/BuildConfig.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/ButtonDropTarget.class b/FairphoneHome/bin/classes/org/fairphone/launcher/ButtonDropTarget.class
new file mode 100644
index 0000000..abb48f3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/ButtonDropTarget.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CanvasCache.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CanvasCache.class
new file mode 100644
index 0000000..435d67f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CanvasCache.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$1.class
new file mode 100644
index 0000000..aa6cc38
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$2.class
new file mode 100644
index 0000000..dab6ecd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$3.class
new file mode 100644
index 0000000..25d9582
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$4.class
new file mode 100644
index 0000000..615c886
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellAndSpan.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellAndSpan.class
new file mode 100644
index 0000000..2c1bf5b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellAndSpan.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellInfo.class
new file mode 100644
index 0000000..b7d68c4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellLayoutAnimationController.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellLayoutAnimationController.class
new file mode 100644
index 0000000..c91621f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$CellLayoutAnimationController.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ItemConfiguration.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ItemConfiguration.class
new file mode 100644
index 0000000..2504ddd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ItemConfiguration.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$LayoutParams.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$LayoutParams.class
new file mode 100644
index 0000000..3b1240a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$LayoutParams.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation$1.class
new file mode 100644
index 0000000..1925e7e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation$2.class
new file mode 100644
index 0000000..cd61da4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation.class
new file mode 100644
index 0000000..638806a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ReorderHintAnimation.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ViewCluster$PositionComparator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ViewCluster$PositionComparator.class
new file mode 100644
index 0000000..7faa3b5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ViewCluster$PositionComparator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ViewCluster.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ViewCluster.class
new file mode 100644
index 0000000..fa41fab
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout$ViewCluster.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout.class
new file mode 100644
index 0000000..5ccd770
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CellLayout.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CheckLongPressHelper$CheckForLongPress.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CheckLongPressHelper$CheckForLongPress.class
new file mode 100644
index 0000000..e365605
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CheckLongPressHelper$CheckForLongPress.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/CheckLongPressHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/CheckLongPressHelper.class
new file mode 100644
index 0000000..397a1b7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/CheckLongPressHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Cling.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Cling.class
new file mode 100644
index 0000000..26a24d2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Cling.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler$IdleRunnable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler$IdleRunnable.class
new file mode 100644
index 0000000..33d302e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler$IdleRunnable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler$Impl.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler$Impl.class
new file mode 100644
index 0000000..6f86ce7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler$Impl.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler.class
new file mode 100644
index 0000000..59a9ce9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeferredHandler.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$1.class
new file mode 100644
index 0000000..26ed0eb
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$2.class
new file mode 100644
index 0000000..6293c54
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$3.class
new file mode 100644
index 0000000..db2b19f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$4.class
new file mode 100644
index 0000000..34a13eb
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$5.class
new file mode 100644
index 0000000..0ffeb59
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$6.class
new file mode 100644
index 0000000..23e9bcc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$FlingAlongVectorAnimatorUpdateListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$FlingAlongVectorAnimatorUpdateListener.class
new file mode 100644
index 0000000..d6f7c24
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget$FlingAlongVectorAnimatorUpdateListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget.class
new file mode 100644
index 0000000..0be38b3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DeleteDropTarget.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$DragListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$DragListener.class
new file mode 100644
index 0000000..06b4349
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$DragListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$MovementState.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$MovementState.class
new file mode 100644
index 0000000..7c9a371
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$MovementState.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$ScrollRunnable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$ScrollRunnable.class
new file mode 100644
index 0000000..8cdaf02
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController$ScrollRunnable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragController.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController.class
new file mode 100644
index 0000000..eae2edd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragController.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$1.class
new file mode 100644
index 0000000..efd2c10
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$2.class
new file mode 100644
index 0000000..526fce5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$3.class
new file mode 100644
index 0000000..485e94a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$4.class
new file mode 100644
index 0000000..20f2e92
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$5.class
new file mode 100644
index 0000000..326c03a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$LayoutParams.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$LayoutParams.class
new file mode 100644
index 0000000..fd1375a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer$LayoutParams.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer.class
new file mode 100644
index 0000000..b6880fe
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragLayer.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragScroller.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragScroller.class
new file mode 100644
index 0000000..88f008e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragScroller.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragSource.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragSource.class
new file mode 100644
index 0000000..8fb92b7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragSource.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$1.class
new file mode 100644
index 0000000..1ccf3a4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$2.class
new file mode 100644
index 0000000..12b1028
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$3.class
new file mode 100644
index 0000000..77f42c0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DragView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView.class
new file mode 100644
index 0000000..4250e02
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DragView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DrawableStateProxyView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DrawableStateProxyView.class
new file mode 100644
index 0000000..10dfbca
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DrawableStateProxyView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget$DragEnforcer.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget$DragEnforcer.class
new file mode 100644
index 0000000..4254edf
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget$DragEnforcer.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget$DragObject.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget$DragObject.class
new file mode 100644
index 0000000..f00c171
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget$DragObject.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget.class b/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget.class
new file mode 100644
index 0000000..9f92548
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/DropTarget.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FairphoneApplication.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FairphoneApplication.class
new file mode 100644
index 0000000..b3e807a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FairphoneApplication.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FastBitmapDrawable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FastBitmapDrawable.class
new file mode 100644
index 0000000..570de28
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FastBitmapDrawable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FocusHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FocusHelper$1.class
new file mode 100644
index 0000000..1c48a02
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FocusHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FocusHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FocusHelper.class
new file mode 100644
index 0000000..668e632
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FocusHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FocusOnlyTabWidget.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FocusOnlyTabWidget.class
new file mode 100644
index 0000000..193f208
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FocusOnlyTabWidget.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$1.class
new file mode 100644
index 0000000..e7139f3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$2.class
new file mode 100644
index 0000000..f626369
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$3.class
new file mode 100644
index 0000000..e1167b2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$4.class
new file mode 100644
index 0000000..9238e90
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$5.class
new file mode 100644
index 0000000..5ab218b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$6.class
new file mode 100644
index 0000000..1ff5566
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$7.class
new file mode 100644
index 0000000..0b244b7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$8.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$8.class
new file mode 100644
index 0000000..c53a0f5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$GridComparator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$GridComparator.class
new file mode 100644
index 0000000..744ef9f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder$GridComparator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Folder.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder.class
new file mode 100644
index 0000000..4d0e0bd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Folder.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderEditText.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderEditText.class
new file mode 100644
index 0000000..c54f0da
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderEditText.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$1.class
new file mode 100644
index 0000000..1c1245e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$2.class
new file mode 100644
index 0000000..062b9c3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$3.class
new file mode 100644
index 0000000..d0bd6b3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$1.class
new file mode 100644
index 0000000..5c98823
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$2.class
new file mode 100644
index 0000000..01ce2d5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$3.class
new file mode 100644
index 0000000..2bb4528
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$4.class
new file mode 100644
index 0000000..fe1ce16
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator.class
new file mode 100644
index 0000000..1db40dd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$FolderRingAnimator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$PreviewItemDrawingParams.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$PreviewItemDrawingParams.class
new file mode 100644
index 0000000..0c85128
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon$PreviewItemDrawingParams.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon.class
new file mode 100644
index 0000000..5af2788
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderIcon.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderInfo$FolderListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderInfo$FolderListener.class
new file mode 100644
index 0000000..bf48a27
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderInfo$FolderListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderInfo.class
new file mode 100644
index 0000000..d096cad
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/FolderKeyEventListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderKeyEventListener.class
new file mode 100644
index 0000000..9f50d6c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/FolderKeyEventListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HandleView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HandleView.class
new file mode 100644
index 0000000..739c0f4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HandleView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HideFromAccessibilityHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HideFromAccessibilityHelper.class
new file mode 100644
index 0000000..020a39b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HideFromAccessibilityHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicImageView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicImageView.class
new file mode 100644
index 0000000..3bd0d2e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicImageView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicLinearLayout.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicLinearLayout.class
new file mode 100644
index 0000000..a6cd54e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicLinearLayout.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicOutlineHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicOutlineHelper.class
new file mode 100644
index 0000000..2c9e907
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicOutlineHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicViewHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicViewHelper.class
new file mode 100644
index 0000000..1eff939
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HolographicViewHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat$1.class
new file mode 100644
index 0000000..3da673d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat$2.class
new file mode 100644
index 0000000..3659869
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat.class
new file mode 100644
index 0000000..1bed633
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Hotseat.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/HotseatIconKeyEventListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/HotseatIconKeyEventListener.class
new file mode 100644
index 0000000..0c7ec0c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/HotseatIconKeyEventListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/IconCache$CacheEntry.class b/FairphoneHome/bin/classes/org/fairphone/launcher/IconCache$CacheEntry.class
new file mode 100644
index 0000000..8a99dfa
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/IconCache$CacheEntry.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/IconCache.class b/FairphoneHome/bin/classes/org/fairphone/launcher/IconCache.class
new file mode 100644
index 0000000..355a8c8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/IconCache.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/IconKeyEventListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/IconKeyEventListener.class
new file mode 100644
index 0000000..df832b4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/IconKeyEventListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InfoDropTarget.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InfoDropTarget.class
new file mode 100644
index 0000000..d421bcd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InfoDropTarget.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver$1.class
new file mode 100644
index 0000000..6a5d599
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver$PendingInstallShortcutInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver$PendingInstallShortcutInfo.class
new file mode 100644
index 0000000..17da330
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver$PendingInstallShortcutInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver.class
new file mode 100644
index 0000000..6c5fb1b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallShortcutReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver$WidgetListAdapter.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver$WidgetListAdapter.class
new file mode 100644
index 0000000..1fb538c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver$WidgetListAdapter.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver$WidgetMimeTypeHandlerData.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver$WidgetMimeTypeHandlerData.class
new file mode 100644
index 0000000..283bc21
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver$WidgetMimeTypeHandlerData.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver.class
new file mode 100644
index 0000000..d894e5f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InstallWidgetReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InterruptibleInOutAnimator$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InterruptibleInOutAnimator$1.class
new file mode 100644
index 0000000..9cbb6b3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InterruptibleInOutAnimator$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/InterruptibleInOutAnimator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/InterruptibleInOutAnimator.class
new file mode 100644
index 0000000..349af1b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/InterruptibleInOutAnimator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/ItemInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/ItemInfo.class
new file mode 100644
index 0000000..a8174cf
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/ItemInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$1.class
new file mode 100644
index 0000000..1ac6ae6
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$10.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$10.class
new file mode 100644
index 0000000..1bedc87
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$10.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$11.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$11.class
new file mode 100644
index 0000000..6119152
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$11.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$12.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$12.class
new file mode 100644
index 0000000..667f120
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$12.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$13.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$13.class
new file mode 100644
index 0000000..f7ab258
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$13.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$14.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$14.class
new file mode 100644
index 0000000..21766fa
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$14.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$15.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$15.class
new file mode 100644
index 0000000..ab536de
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$15.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$16.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$16.class
new file mode 100644
index 0000000..3606f88
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$16.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$17$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$17$1.class
new file mode 100644
index 0000000..808f2ae
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$17$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$17.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$17.class
new file mode 100644
index 0000000..2912e3d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$17.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$18.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$18.class
new file mode 100644
index 0000000..68041eb
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$18.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$19.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$19.class
new file mode 100644
index 0000000..fcd88ef
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$19.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$2.class
new file mode 100644
index 0000000..f3da036
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$20.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$20.class
new file mode 100644
index 0000000..af74363
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$20.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$21.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$21.class
new file mode 100644
index 0000000..e6d3931
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$21.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$22.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$22.class
new file mode 100644
index 0000000..f502e33
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$22.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$23.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$23.class
new file mode 100644
index 0000000..f491ed6
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$23.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$24.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$24.class
new file mode 100644
index 0000000..abf687d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$24.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$25.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$25.class
new file mode 100644
index 0000000..adb6fed
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$25.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$26.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$26.class
new file mode 100644
index 0000000..46ab558
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$26.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$27.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$27.class
new file mode 100644
index 0000000..ce01d59
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$27.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$28.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$28.class
new file mode 100644
index 0000000..efc4ea0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$28.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$29.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$29.class
new file mode 100644
index 0000000..9f296bd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$29.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$3$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$3$1.class
new file mode 100644
index 0000000..b27a274
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$3$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$3.class
new file mode 100644
index 0000000..b603ab4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$30.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$30.class
new file mode 100644
index 0000000..fe4fc3b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$30.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$31$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$31$1.class
new file mode 100644
index 0000000..df2e9b5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$31$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$31.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$31.class
new file mode 100644
index 0000000..fcc9626
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$31.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$32.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$32.class
new file mode 100644
index 0000000..0c46e69
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$32.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$4.class
new file mode 100644
index 0000000..15712b5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$5.class
new file mode 100644
index 0000000..57f666d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$6.class
new file mode 100644
index 0000000..fb5ae64
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$7.class
new file mode 100644
index 0000000..2a9be44
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$8.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$8.class
new file mode 100644
index 0000000..0b7b5b2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$9.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$9.class
new file mode 100644
index 0000000..f6e9022
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$9.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$AppWidgetResetObserver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$AppWidgetResetObserver.class
new file mode 100644
index 0000000..0ffc9f4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$AppWidgetResetObserver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$CloseSystemDialogsIntentReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$CloseSystemDialogsIntentReceiver.class
new file mode 100644
index 0000000..21676f0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$CloseSystemDialogsIntentReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$LocaleConfiguration.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$LocaleConfiguration.class
new file mode 100644
index 0000000..b9f3ab4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$LocaleConfiguration.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$PendingAddArguments.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$PendingAddArguments.class
new file mode 100644
index 0000000..02116d9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$PendingAddArguments.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment$1.class
new file mode 100644
index 0000000..526cd0a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment$2.class
new file mode 100644
index 0000000..a252dd2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment.class
new file mode 100644
index 0000000..4036c2a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$ResetDialogFragment.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$State.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$State.class
new file mode 100644
index 0000000..214cc46
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher$State.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher.class
new file mode 100644
index 0000000..862f24d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Launcher.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimUtils$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimUtils$1.class
new file mode 100644
index 0000000..2368eb7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimUtils$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimUtils.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimUtils.class
new file mode 100644
index 0000000..5024a35
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimUtils.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimatorUpdateListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimatorUpdateListener.class
new file mode 100644
index 0000000..4c01cc4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAnimatorUpdateListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetHost.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetHost.class
new file mode 100644
index 0000000..94ff1eb
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetHost.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetHostView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetHostView.class
new file mode 100644
index 0000000..1762157
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetHostView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetInfo.class
new file mode 100644
index 0000000..684f99e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherAppWidgetInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherApplication$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherApplication$1.class
new file mode 100644
index 0000000..ea6b411
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherApplication$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherApplication.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherApplication.class
new file mode 100644
index 0000000..6893022
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherApplication.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$1.class
new file mode 100644
index 0000000..5268535
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$2.class
new file mode 100644
index 0000000..364f655
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$3.class
new file mode 100644
index 0000000..1a49221
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$4.class
new file mode 100644
index 0000000..c13d491
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$5.class
new file mode 100644
index 0000000..a2ea9ac
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$6.class
new file mode 100644
index 0000000..2ebacc5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$7.class
new file mode 100644
index 0000000..971574a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$8.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$8.class
new file mode 100644
index 0000000..f04eb1b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$9.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$9.class
new file mode 100644
index 0000000..7eb0dff
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$9.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$Callbacks.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$Callbacks.class
new file mode 100644
index 0000000..52d294a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$Callbacks.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$1.class
new file mode 100644
index 0000000..a326a22
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$10.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$10.class
new file mode 100644
index 0000000..f6a51bd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$10.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$11.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$11.class
new file mode 100644
index 0000000..5e069a1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$11.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$2.class
new file mode 100644
index 0000000..4be0640
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$3.class
new file mode 100644
index 0000000..5fddf9c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$4.class
new file mode 100644
index 0000000..c5d798c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$5.class
new file mode 100644
index 0000000..2816bfc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$6.class
new file mode 100644
index 0000000..6f59d39
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$7.class
new file mode 100644
index 0000000..5e9bdce
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$8.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$8.class
new file mode 100644
index 0000000..a4f671c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$9.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$9.class
new file mode 100644
index 0000000..ea8ec0e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask$9.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask.class
new file mode 100644
index 0000000..384d023
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$LoaderTask.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$1.class
new file mode 100644
index 0000000..dafbabc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$2.class
new file mode 100644
index 0000000..ac26e45
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$3.class
new file mode 100644
index 0000000..3ebf337
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$4.class
new file mode 100644
index 0000000..3466de0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask.class
new file mode 100644
index 0000000..dc4a6dc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$PackageUpdatedTask.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$ShortcutNameComparator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$ShortcutNameComparator.class
new file mode 100644
index 0000000..a21e1da
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$ShortcutNameComparator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$WidgetAndShortcutNameComparator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$WidgetAndShortcutNameComparator.class
new file mode 100644
index 0000000..8798ed1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel$WidgetAndShortcutNameComparator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel.class
new file mode 100644
index 0000000..922a356
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherModel.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider$DatabaseHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider$DatabaseHelper.class
new file mode 100644
index 0000000..c32520a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider$DatabaseHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider$SqlArguments.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider$SqlArguments.class
new file mode 100644
index 0000000..9523593
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider$SqlArguments.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider.class
new file mode 100644
index 0000000..33c53ba
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherProvider.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings$BaseLauncherColumns.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings$BaseLauncherColumns.class
new file mode 100644
index 0000000..d0d05d5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings$BaseLauncherColumns.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings$Favorites.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings$Favorites.class
new file mode 100644
index 0000000..4eca492
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings$Favorites.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings.class
new file mode 100644
index 0000000..06e7fad
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherSettings.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherTransitionable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherTransitionable.class
new file mode 100644
index 0000000..019ce45
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherTransitionable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherViewPropertyAnimator$Properties.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherViewPropertyAnimator$Properties.class
new file mode 100644
index 0000000..5c3b77d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherViewPropertyAnimator$Properties.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherViewPropertyAnimator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherViewPropertyAnimator.class
new file mode 100644
index 0000000..bfbf56f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/LauncherViewPropertyAnimator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Manifest$permission.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Manifest$permission.class
new file mode 100644
index 0000000..c429c15
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Manifest$permission.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Manifest.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Manifest.class
new file mode 100644
index 0000000..1995b46
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Manifest.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/OnAlarmListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/OnAlarmListener.class
new file mode 100644
index 0000000..c1b7bd3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/OnAlarmListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Page.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Page.class
new file mode 100644
index 0000000..b0d0eb1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Page.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$1.class
new file mode 100644
index 0000000..a337563
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$2.class
new file mode 100644
index 0000000..57dd448
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$PageSwitchListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$PageSwitchListener.class
new file mode 100644
index 0000000..fa5277b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$PageSwitchListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$SavedState$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$SavedState$1.class
new file mode 100644
index 0000000..7e0c022
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$SavedState$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$SavedState.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$SavedState.class
new file mode 100644
index 0000000..312836e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$SavedState.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$ScrollInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$ScrollInterpolator.class
new file mode 100644
index 0000000..4bb6611
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView$ScrollInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView.class
new file mode 100644
index 0000000..d1582fa
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayout$LayoutParams.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayout$LayoutParams.class
new file mode 100644
index 0000000..4bbfbc7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayout$LayoutParams.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayout.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayout.class
new file mode 100644
index 0000000..537e5ed
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayout.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayoutChildren.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayoutChildren.class
new file mode 100644
index 0000000..0d3af29
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewCellLayoutChildren.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewGridLayout$LayoutParams.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewGridLayout$LayoutParams.class
new file mode 100644
index 0000000..f65127f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewGridLayout$LayoutParams.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewGridLayout.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewGridLayout.class
new file mode 100644
index 0000000..a766d3d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewGridLayout.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon$1.class
new file mode 100644
index 0000000..be36c60
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon$PressedCallback.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon$PressedCallback.class
new file mode 100644
index 0000000..0365d5d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon$PressedCallback.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon.class
new file mode 100644
index 0000000..acf1032
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIcon.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache$Key$Type.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache$Key$Type.class
new file mode 100644
index 0000000..6376d95
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache$Key$Type.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache$Key.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache$Key.class
new file mode 100644
index 0000000..a62170b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache$Key.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache.class
new file mode 100644
index 0000000..e43f183
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewIconCache.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget$CheckForShortPress.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget$CheckForShortPress.class
new file mode 100644
index 0000000..c186128
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget$CheckForShortPress.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget$ShortPressListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget$ShortPressListener.class
new file mode 100644
index 0000000..295c6c8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget$ShortPressListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget.class
new file mode 100644
index 0000000..2498b93
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidget.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidgetImageView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidgetImageView.class
new file mode 100644
index 0000000..0bcd28f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWidgetImageView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWithDraggableItems.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWithDraggableItems.class
new file mode 100644
index 0000000..012c395
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PagedViewWithDraggableItems.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PaintCache.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PaintCache.class
new file mode 100644
index 0000000..c00cc69
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PaintCache.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddItemInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddItemInfo.class
new file mode 100644
index 0000000..d8e1764
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddItemInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddShortcutInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddShortcutInfo.class
new file mode 100644
index 0000000..f490dc9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddShortcutInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddWidgetInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddWidgetInfo.class
new file mode 100644
index 0000000..15b176b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PendingAddWidgetInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PreloadReceiver$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PreloadReceiver$1.class
new file mode 100644
index 0000000..4ac5f27
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PreloadReceiver$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/PreloadReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/PreloadReceiver.class
new file mode 100644
index 0000000..0e8b484
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/PreloadReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$anim.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$anim.class
new file mode 100644
index 0000000..eba4d5c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$anim.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$array.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$array.class
new file mode 100644
index 0000000..1610df4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$array.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$attr.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$attr.class
new file mode 100644
index 0000000..87bbdad
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$attr.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$bool.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$bool.class
new file mode 100644
index 0000000..352b3dc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$bool.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$color.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$color.class
new file mode 100644
index 0000000..fa6a374
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$color.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$dimen.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$dimen.class
new file mode 100644
index 0000000..2139949
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$dimen.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$drawable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$drawable.class
new file mode 100644
index 0000000..f7bfb10
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$drawable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$id.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$id.class
new file mode 100644
index 0000000..f6c89ec
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$id.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$integer.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$integer.class
new file mode 100644
index 0000000..7e037af
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$integer.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$layout.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$layout.class
new file mode 100644
index 0000000..45e2aa5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$layout.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$mipmap.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$mipmap.class
new file mode 100644
index 0000000..5b485bb
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$mipmap.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$raw.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$raw.class
new file mode 100644
index 0000000..7d09f0a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$raw.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$string.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$string.class
new file mode 100644
index 0000000..624b582
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$string.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$style.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$style.class
new file mode 100644
index 0000000..cc88751
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$style.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$styleable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$styleable.class
new file mode 100644
index 0000000..3f802a9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$styleable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R$xml.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R$xml.class
new file mode 100644
index 0000000..245cd4c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R$xml.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/R.class b/FairphoneHome/bin/classes/org/fairphone/launcher/R.class
new file mode 100644
index 0000000..a0a67a4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/R.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/RectCache.class b/FairphoneHome/bin/classes/org/fairphone/launcher/RectCache.class
new file mode 100644
index 0000000..3063da6
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/RectCache.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SearchDropTargetBar$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SearchDropTargetBar$1.class
new file mode 100644
index 0000000..b182ed9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SearchDropTargetBar$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SearchDropTargetBar.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SearchDropTargetBar.class
new file mode 100644
index 0000000..9faaeb0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SearchDropTargetBar.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/ShortcutAndWidgetContainer.class b/FairphoneHome/bin/classes/org/fairphone/launcher/ShortcutAndWidgetContainer.class
new file mode 100644
index 0000000..311e752
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/ShortcutAndWidgetContainer.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/ShortcutInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/ShortcutInfo.class
new file mode 100644
index 0000000..d7bcf36
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/ShortcutInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SmoothPagedView$OvershootInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SmoothPagedView$OvershootInterpolator.class
new file mode 100644
index 0000000..d02532c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SmoothPagedView$OvershootInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SmoothPagedView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SmoothPagedView.class
new file mode 100644
index 0000000..b79b31a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SmoothPagedView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SpringLoadedDragController.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SpringLoadedDragController.class
new file mode 100644
index 0000000..959d0c1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SpringLoadedDragController.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/StrokedTextView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/StrokedTextView.class
new file mode 100644
index 0000000..b908589
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/StrokedTextView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SymmetricalLinearTween$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SymmetricalLinearTween$1.class
new file mode 100644
index 0000000..82d56af
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SymmetricalLinearTween$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/SymmetricalLinearTween.class b/FairphoneHome/bin/classes/org/fairphone/launcher/SymmetricalLinearTween.class
new file mode 100644
index 0000000..976f078
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/SymmetricalLinearTween.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/TweenCallback.class b/FairphoneHome/bin/classes/org/fairphone/launcher/TweenCallback.class
new file mode 100644
index 0000000..48eb518
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/TweenCallback.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver$1.class
new file mode 100644
index 0000000..86a305f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver$PendingUninstallShortcutInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver$PendingUninstallShortcutInfo.class
new file mode 100644
index 0000000..d0cb60e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver$PendingUninstallShortcutInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver.class
new file mode 100644
index 0000000..6e106a8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/UninstallShortcutReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/UserInitializeReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/UserInitializeReceiver.class
new file mode 100644
index 0000000..f51d74c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/UserInitializeReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Utilities.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Utilities.class
new file mode 100644
index 0000000..0e339d9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Utilities.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooser.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooser.class
new file mode 100644
index 0000000..bb2841a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooser.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$1.class
new file mode 100644
index 0000000..300910d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$ImageAdapter.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$ImageAdapter.class
new file mode 100644
index 0000000..76164a0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$ImageAdapter.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$WallpaperDrawable.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$WallpaperDrawable.class
new file mode 100644
index 0000000..4f9d411
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$WallpaperDrawable.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$WallpaperLoader.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$WallpaperLoader.class
new file mode 100644
index 0000000..5af51db
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment$WallpaperLoader.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment.class
new file mode 100644
index 0000000..4405a98
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WallpaperChooserDialogFragment.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/WeakReferenceThreadLocal.class b/FairphoneHome/bin/classes/org/fairphone/launcher/WeakReferenceThreadLocal.class
new file mode 100644
index 0000000..7d48889
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/WeakReferenceThreadLocal.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$1.class
new file mode 100644
index 0000000..b0469ba
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$10.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$10.class
new file mode 100644
index 0000000..8d6d268
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$10.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$11.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$11.class
new file mode 100644
index 0000000..84f7283
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$11.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$12.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$12.class
new file mode 100644
index 0000000..3285e85
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$12.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$2.class
new file mode 100644
index 0000000..4018012
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$3.class
new file mode 100644
index 0000000..ae76c19
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$4.class
new file mode 100644
index 0000000..f0b0be6
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$5.class
new file mode 100644
index 0000000..88e9619
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$6.class
new file mode 100644
index 0000000..edf7018
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$7.class
new file mode 100644
index 0000000..94d1ddd
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$8.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$8.class
new file mode 100644
index 0000000..82ff4eb
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$9.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$9.class
new file mode 100644
index 0000000..9f21271
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$9.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$FolderCreationAlarmListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$FolderCreationAlarmListener.class
new file mode 100644
index 0000000..edbd5e1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$FolderCreationAlarmListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$InverseZInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$InverseZInterpolator.class
new file mode 100644
index 0000000..74af9af
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$InverseZInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ReorderAlarmListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ReorderAlarmListener.class
new file mode 100644
index 0000000..28e3334
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ReorderAlarmListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$State.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$State.class
new file mode 100644
index 0000000..f74d3c3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$State.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$WallpaperOffsetInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$WallpaperOffsetInterpolator.class
new file mode 100644
index 0000000..a0cf0c8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$WallpaperOffsetInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$WallpaperVerticalOffset.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$WallpaperVerticalOffset.class
new file mode 100644
index 0000000..ad8e5e5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$WallpaperVerticalOffset.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZInterpolator.class
new file mode 100644
index 0000000..470c106
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZoomInInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZoomInInterpolator.class
new file mode 100644
index 0000000..96e5d94
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZoomInInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZoomOutInterpolator.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZoomOutInterpolator.class
new file mode 100644
index 0000000..9902b6f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace$ZoomOutInterpolator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace.class b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace.class
new file mode 100644
index 0000000..f9eb136
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/Workspace.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$1.class
new file mode 100644
index 0000000..cbf6097
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$2.class
new file mode 100644
index 0000000..50992ca
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$3.class
new file mode 100644
index 0000000..ff09798
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$IconEndPositions.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$IconEndPositions.class
new file mode 100644
index 0000000..93471ef
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$IconEndPositions.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$ItemIcon.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$ItemIcon.class
new file mode 100644
index 0000000..463a6b5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$ItemIcon.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$Side.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$Side.class
new file mode 100644
index 0000000..8dc93db
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper$Side.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper.class
new file mode 100644
index 0000000..2fb7727
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter$ViewHolder.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter$ViewHolder.class
new file mode 100644
index 0000000..395b2d4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter$ViewHolder.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter.class
new file mode 100644
index 0000000..e79fa6c
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AppDiscoverer.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AppDiscoverer.class
new file mode 100644
index 0000000..0311df2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/AppDiscoverer.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/DragDropItemLayoutListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/DragDropItemLayoutListener.class
new file mode 100644
index 0000000..6970235
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/DragDropItemLayoutListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EdgeSwipeApplicationInfo.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EdgeSwipeApplicationInfo.class
new file mode 100644
index 0000000..2b2b0d9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EdgeSwipeApplicationInfo.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$1.class
new file mode 100644
index 0000000..01b9bec
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$2.class
new file mode 100644
index 0000000..4378fc8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$3.class
new file mode 100644
index 0000000..d3ec4af
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$DropDragEventListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$DropDragEventListener.class
new file mode 100644
index 0000000..ae0d2b9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$DropDragEventListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$IconDragShadowBuilder.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$IconDragShadowBuilder.class
new file mode 100644
index 0000000..89e77a8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$IconDragShadowBuilder.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$IdLongClickListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$IdLongClickListener.class
new file mode 100644
index 0000000..f79cfe3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity$IdLongClickListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity.class
new file mode 100644
index 0000000..b069518
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/FavoritesStorageHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/FavoritesStorageHelper.class
new file mode 100644
index 0000000..e5d0712
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/edit/FavoritesStorageHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView$CircularCountdownListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView$CircularCountdownListener.class
new file mode 100644
index 0000000..cd3934a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView$CircularCountdownListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView.class
new file mode 100644
index 0000000..ec5b06b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EdgeSwipeInterceptorViewListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EdgeSwipeInterceptorViewListener.class
new file mode 100644
index 0000000..ecd9582
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EdgeSwipeInterceptorViewListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView$OnEditFavouritesIconDraggedListener.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView$OnEditFavouritesIconDraggedListener.class
new file mode 100644
index 0000000..8e02717
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView$OnEditFavouritesIconDraggedListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView.class b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView.class
new file mode 100644
index 0000000..4dfa556
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallationAssets.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallationAssets.class
new file mode 100644
index 0000000..ed7d18f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallationAssets.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1$1.class
new file mode 100644
index 0000000..abbd779
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1$2.class
new file mode 100644
index 0000000..28aef7d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1.class
new file mode 100644
index 0000000..1c6ebad
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$2$1.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$2$1.class
new file mode 100644
index 0000000..3c31cc5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$2$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$2.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$2.class
new file mode 100644
index 0000000..7bfc5cf
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$3.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$3.class
new file mode 100644
index 0000000..6ae263d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$4.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$4.class
new file mode 100644
index 0000000..51aa954
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$5.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$5.class
new file mode 100644
index 0000000..e309ca7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$6.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$6.class
new file mode 100644
index 0000000..82ba7d4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$7.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$7.class
new file mode 100644
index 0000000..118153e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$8.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$8.class
new file mode 100644
index 0000000..b586ec0
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$DownloadBroadCastReceiver.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$DownloadBroadCastReceiver.class
new file mode 100644
index 0000000..bdeb32b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper$DownloadBroadCastReceiver.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper.class b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper.class
new file mode 100644
index 0000000..3292a2b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/rsa/utils/RSAUtils.class b/FairphoneHome/bin/classes/org/fairphone/launcher/rsa/utils/RSAUtils.class
new file mode 100644
index 0000000..6aaffc9
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/rsa/utils/RSAUtils.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/launcher/util/KWMathUtils.class b/FairphoneHome/bin/classes/org/fairphone/launcher/util/KWMathUtils.class
new file mode 100644
index 0000000..7d3b58d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/launcher/util/KWMathUtils.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$1.class
new file mode 100644
index 0000000..e81d7f2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$10.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$10.class
new file mode 100644
index 0000000..d59cbe1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$10.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$2.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$2.class
new file mode 100644
index 0000000..02fc57a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$3.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$3.class
new file mode 100644
index 0000000..82665f1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$4.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$4.class
new file mode 100644
index 0000000..bcb403e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$4.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$5.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$5.class
new file mode 100644
index 0000000..92ba617
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$5.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$6.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$6.class
new file mode 100644
index 0000000..9920f33
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$6.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$7.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$7.class
new file mode 100644
index 0000000..fea865e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$7.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$8.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$8.class
new file mode 100644
index 0000000..19e4ed2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$8.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$9.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$9.class
new file mode 100644
index 0000000..c6bafb5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$9.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$OOBESteps.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$OOBESteps.class
new file mode 100644
index 0000000..1c4708d
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity$OOBESteps.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity.class b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity.class
new file mode 100644
index 0000000..50c4ad3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/OOBEActivity.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper$1.class
new file mode 100644
index 0000000..d8e3d34
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper$TutorialViewAnimationListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper$TutorialViewAnimationListener.class
new file mode 100644
index 0000000..c16a6e2
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper$TutorialViewAnimationListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper.class
new file mode 100644
index 0000000..abb0604
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper$1.class
new file mode 100644
index 0000000..eb0bb50
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper$TutorialViewAnimationListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper$TutorialViewAnimationListener.class
new file mode 100644
index 0000000..727ae93
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper$TutorialViewAnimationListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper.class
new file mode 100644
index 0000000..5c4df43
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$1.class
new file mode 100644
index 0000000..b8fd835
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$2.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$2.class
new file mode 100644
index 0000000..7d338df
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$3.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$3.class
new file mode 100644
index 0000000..50eff8f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$3.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$EditFavsTutorialAnimationViewListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$EditFavsTutorialAnimationViewListener.class
new file mode 100644
index 0000000..580c608
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView$EditFavsTutorialAnimationViewListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView.class
new file mode 100644
index 0000000..fbf2dab
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/EditFavsTutorialAnimationView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$1.class
new file mode 100644
index 0000000..e1bce9a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$2.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$2.class
new file mode 100644
index 0000000..bd486fc
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$2.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$MenuTutorialAnimationViewListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$MenuTutorialAnimationViewListener.class
new file mode 100644
index 0000000..1ba6a21
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView$MenuTutorialAnimationViewListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView.class
new file mode 100644
index 0000000..88ed1a8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MenuTutorialAnimationView.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper$1.class
new file mode 100644
index 0000000..47dd744
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper$TutorialViewAnimationListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper$TutorialViewAnimationListener.class
new file mode 100644
index 0000000..e468114
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper$TutorialViewAnimationListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper.class
new file mode 100644
index 0000000..065c212
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper$1.class
new file mode 100644
index 0000000..c7f0a69
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper$TutorialViewAnimationListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper$TutorialViewAnimationListener.class
new file mode 100644
index 0000000..4a935e3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper$TutorialViewAnimationListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper.class
new file mode 100644
index 0000000..ae0d950
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper$1.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper$1.class
new file mode 100644
index 0000000..7e1f20b
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper$1.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper$TutorialViewAnimationListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper$TutorialViewAnimationListener.class
new file mode 100644
index 0000000..99657d3
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper$TutorialViewAnimationListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper.class
new file mode 100644
index 0000000..6528e35
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper$TutorialAnimationHelperListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper$TutorialAnimationHelperListener.class
new file mode 100644
index 0000000..d474d10
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper$TutorialAnimationHelperListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper$TutorialState.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper$TutorialState.class
new file mode 100644
index 0000000..1395346
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper$TutorialState.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper.class b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper.class
new file mode 100644
index 0000000..7192bf4
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/animation/TutorialAnimationHelper.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWAnimationListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWAnimationListener.class
new file mode 100644
index 0000000..15a1a2a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWAnimationListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWKeyComparator.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWKeyComparator.class
new file mode 100644
index 0000000..906ec97
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWKeyComparator.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWKeyframe.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWKeyframe.class
new file mode 100644
index 0000000..4fb6eef
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWKeyframe.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWValueAnimation.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWValueAnimation.class
new file mode 100644
index 0000000..3c098ac
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWValueAnimation.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWValueType.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWValueType.class
new file mode 100644
index 0000000..aba6fcf
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation$KWValueType.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation.class
new file mode 100644
index 0000000..8487da7
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimation.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationGroup$KWAnimationGroupListener.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationGroup$KWAnimationGroupListener.class
new file mode 100644
index 0000000..372f12a
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationGroup$KWAnimationGroupListener.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationGroup.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationGroup.class
new file mode 100644
index 0000000..b0c665f
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationGroup.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationManager.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationManager.class
new file mode 100644
index 0000000..95fd551
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWAnimationManager.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWFontsManager.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWFontsManager.class
new file mode 100644
index 0000000..257164e
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWFontsManager.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWMathUtils.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWMathUtils.class
new file mode 100644
index 0000000..0d8fbe8
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWMathUtils.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWSprite.class b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWSprite.class
new file mode 100644
index 0000000..7d13db6
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/oobe/utils/KWSprite.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/settings/SettingsActivity.class b/FairphoneHome/bin/classes/org/fairphone/settings/SettingsActivity.class
new file mode 100644
index 0000000..6a9ed60
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/settings/SettingsActivity.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/settings/SettingsFragment.class b/FairphoneHome/bin/classes/org/fairphone/settings/SettingsFragment.class
new file mode 100644
index 0000000..a526785
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/settings/SettingsFragment.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/AppDiscoverer.class b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/AppDiscoverer.class
new file mode 100644
index 0000000..4800fe1
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/AppDiscoverer.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager$LimitedQueue.class b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager$LimitedQueue.class
new file mode 100644
index 0000000..5babb28
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager$LimitedQueue.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager.class b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager.class
new file mode 100644
index 0000000..5e53919
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInformation.class b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInformation.class
new file mode 100644
index 0000000..9427790
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/ApplicationRunInformation.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/WidgetProvider.class b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/WidgetProvider.class
new file mode 100644
index 0000000..dc7d1e5
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/widgets/appswitcher/WidgetProvider.class
Binary files differ
diff --git a/FairphoneHome/bin/classes/org/fairphone/widgets/gapps/GoogleAppsInstallerWidget.class b/FairphoneHome/bin/classes/org/fairphone/widgets/gapps/GoogleAppsInstallerWidget.class
new file mode 100644
index 0000000..476a1cf
--- /dev/null
+++ b/FairphoneHome/bin/classes/org/fairphone/widgets/gapps/GoogleAppsInstallerWidget.class
Binary files differ
diff --git a/FairphoneHome/bin/dexedLibs/RootTools-3.3-0888001aa3f51faee0e49f23fd7da678.jar b/FairphoneHome/bin/dexedLibs/RootTools-3.3-0888001aa3f51faee0e49f23fd7da678.jar
new file mode 100644
index 0000000..32175cf
--- /dev/null
+++ b/FairphoneHome/bin/dexedLibs/RootTools-3.3-0888001aa3f51faee0e49f23fd7da678.jar
Binary files differ
diff --git a/FairphoneHome/bin/dexedLibs/acra-4.4.0-f4098fca9db05b63072011dbd996c51e.jar b/FairphoneHome/bin/dexedLibs/acra-4.4.0-f4098fca9db05b63072011dbd996c51e.jar
new file mode 100644
index 0000000..ce74177
--- /dev/null
+++ b/FairphoneHome/bin/dexedLibs/acra-4.4.0-f4098fca9db05b63072011dbd996c51e.jar
Binary files differ
diff --git a/FairphoneHome/bin/dexedLibs/android-support-v4-89fc231524b48a92d5a9777501e42393.jar b/FairphoneHome/bin/dexedLibs/android-support-v4-89fc231524b48a92d5a9777501e42393.jar
new file mode 100644
index 0000000..eebd418
--- /dev/null
+++ b/FairphoneHome/bin/dexedLibs/android-support-v4-89fc231524b48a92d5a9777501e42393.jar
Binary files differ
diff --git a/FairphoneHome/bin/jarlist.cache b/FairphoneHome/bin/jarlist.cache
new file mode 100644
index 0000000..0565465
--- /dev/null
+++ b/FairphoneHome/bin/jarlist.cache
@@ -0,0 +1,3 @@
+# cache for current jar dependency. DO NOT EDIT.
+# format is <lastModified> <length> <SHA-1> <path>
+# Encoding is UTF-8
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_background_right.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_background_right.png
new file mode 100644
index 0000000..e121746
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_background_right.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_background_right_item.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_background_right_item.png
new file mode 100644
index 0000000..2bf0e21
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_background_right_item.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_disabled.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_disabled.png
new file mode 100644
index 0000000..0ba6d40
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_disabled.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_press.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_press.png
new file mode 100644
index 0000000..963eb34
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_press.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_up.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_up.png
new file mode 100644
index 0000000..6d4d67f
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_button_reset_up.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_divider.9.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_divider.9.png
new file mode 100644
index 0000000..59a5fd3
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_divider.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_icon_all_apps.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_icon_all_apps.png
new file mode 100644
index 0000000..6565b28
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_icon_all_apps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_icon_apps.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_icon_apps.png
new file mode 100644
index 0000000..9f71a9f
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_icon_apps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_list_background.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_list_background.png
new file mode 100644
index 0000000..49758c2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_list_background.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/app_switcher_separator.9.png b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_separator.9.png
new file mode 100644
index 0000000..70291d7
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/app_switcher_separator.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/apps_customize_bg.png b/FairphoneHome/bin/res/drawable-hdpi/apps_customize_bg.png
new file mode 100644
index 0000000..775e6e8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/apps_customize_bg.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/apps_widgets_bg.png b/FairphoneHome/bin/res/drawable-hdpi/apps_widgets_bg.png
new file mode 100644
index 0000000..17ef322
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/apps_widgets_bg.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/appswicther_widget_icon.png b/FairphoneHome/bin/res/drawable-hdpi/appswicther_widget_icon.png
new file mode 100644
index 0000000..ee25352
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/appswicther_widget_icon.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/bg_appwidget_error.9.png b/FairphoneHome/bin/res/drawable-hdpi/bg_appwidget_error.9.png
new file mode 100644
index 0000000..717b665
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/bg_appwidget_error.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/bg_cling1.png b/FairphoneHome/bin/res/drawable-hdpi/bg_cling1.png
new file mode 100644
index 0000000..c6a3026
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/bg_cling1.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/bg_cling2.png b/FairphoneHome/bin/res/drawable-hdpi/bg_cling2.png
new file mode 100644
index 0000000..bfe69fa
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/bg_cling2.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/bg_cling3.png b/FairphoneHome/bin/res/drawable-hdpi/bg_cling3.png
new file mode 100644
index 0000000..7466bf8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/bg_cling3.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/bg_cling4.png b/FairphoneHome/bin/res/drawable-hdpi/bg_cling4.png
new file mode 100644
index 0000000..f137d9c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/bg_cling4.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/bg_gradient.png b/FairphoneHome/bin/res/drawable-hdpi/bg_gradient.png
new file mode 100644
index 0000000..d821f93
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/bg_gradient.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/btn_cling_normal.9.png b/FairphoneHome/bin/res/drawable-hdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..8cbfb9d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/btn_cling_pressed.9.png b/FairphoneHome/bin/res/drawable-hdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..82b9771
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/cling.png b/FairphoneHome/bin/res/drawable-hdpi/cling.png
new file mode 100644
index 0000000..ce59978
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/cling.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/divider_launcher_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/divider_launcher_holo.9.png
new file mode 100644
index 0000000..1b30aa4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edge_swipe_menu_highlight.png b/FairphoneHome/bin/res/drawable-hdpi/edge_swipe_menu_highlight.png
new file mode 100644
index 0000000..7b8bfc4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edge_swipe_menu_highlight.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_holder.png b/FairphoneHome/bin/res/drawable-hdpi/edit_holder.png
new file mode 100644
index 0000000..e0e9b51
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_holder.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_all_apps_faded.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_all_apps_faded.png
new file mode 100644
index 0000000..4a04baa
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_all_apps_faded.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_circle.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_circle.png
new file mode 100644
index 0000000..007f782
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_circle.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_circle_faded.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_circle_faded.png
new file mode 100644
index 0000000..34db2bc
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_circle_faded.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_icon_remove.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_icon_remove.png
new file mode 100644
index 0000000..840bee4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_icon_remove.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_background.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_background.png
new file mode 100644
index 0000000..66cd311
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_background.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_separator.9.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_separator.9.png
new file mode 100644
index 0000000..e440fc2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_separator.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_shadow_bottom.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_shadow_bottom.png
new file mode 100644
index 0000000..4bc11ed
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_shadow_bottom.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_shadow_top.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_shadow_top.png
new file mode 100644
index 0000000..eb1a0ac
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_list_shadow_top.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/edit_menu_separator.9.png b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_separator.9.png
new file mode 100644
index 0000000..a96869c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/edit_menu_separator.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/flying_icon_bg_pressed.9.png b/FairphoneHome/bin/res/drawable-hdpi/flying_icon_bg_pressed.9.png
new file mode 100644
index 0000000..69796a8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/flying_icon_bg_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/focused_bg.9.png b/FairphoneHome/bin/res/drawable-hdpi/focused_bg.9.png
new file mode 100644
index 0000000..5fe1de8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/focused_bg.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_edit_favs_remove_red_bg.png b/FairphoneHome/bin/res/drawable-hdpi/fp_edit_favs_remove_red_bg.png
new file mode 100644
index 0000000..16cc68f
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_edit_favs_remove_red_bg.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_fav_icon_ring.png b/FairphoneHome/bin/res/drawable-hdpi/fp_fav_icon_ring.png
new file mode 100644
index 0000000..007f782
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_fav_icon_ring.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_alert_background.9.png b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_alert_background.9.png
new file mode 100644
index 0000000..a30e51d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_alert_background.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_installer_icon.png b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_installer_icon.png
new file mode 100644
index 0000000..c64c2bf
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_installer_icon.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_widget_install.png b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_widget_install.png
new file mode 100644
index 0000000..556942c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_widget_install.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_widget_uninstall.png b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_widget_uninstall.png
new file mode 100644
index 0000000..4f1d8b3
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_gapps_widget_uninstall.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/fp_oobe_background.png b/FairphoneHome/bin/res/drawable-hdpi/fp_oobe_background.png
new file mode 100644
index 0000000..36bbca6
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/fp_oobe_background.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/grid_focused.9.png b/FairphoneHome/bin/res/drawable-hdpi/grid_focused.9.png
new file mode 100644
index 0000000..06e59d8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/grid_focused.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/grid_pressed.9.png b/FairphoneHome/bin/res/drawable-hdpi/grid_pressed.9.png
new file mode 100644
index 0000000..ace72ac
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/grid_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/grid_selected.9.png b/FairphoneHome/bin/res/drawable-hdpi/grid_selected.9.png
new file mode 100644
index 0000000..d5f646c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/grid_selected.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/home_press.9.png b/FairphoneHome/bin/res/drawable-hdpi/home_press.9.png
new file mode 100644
index 0000000..da21336
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/home_press.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/homescreen_blue_normal_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/homescreen_blue_normal_holo.9.png
new file mode 100644
index 0000000..7436f8a
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/homescreen_blue_normal_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/homescreen_blue_strong_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/homescreen_blue_strong_holo.9.png
new file mode 100644
index 0000000..a2ee98b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/homescreen_blue_strong_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/hotseat_scrubber_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/hotseat_scrubber_holo.9.png
new file mode 100644
index 0000000..baf6b6e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/hotseat_scrubber_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/hotseat_track_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/hotseat_track_holo.9.png
new file mode 100644
index 0000000..9922eb8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/hotseat_track_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_allapps.png b/FairphoneHome/bin/res/drawable-hdpi/ic_allapps.png
new file mode 100644
index 0000000..bd7dc09
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_allapps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_allapps_pressed.png b/FairphoneHome/bin/res/drawable-hdpi/ic_allapps_pressed.png
new file mode 100644
index 0000000..c9636b3
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_home_all_apps_holo_dark.png b/FairphoneHome/bin/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
new file mode 100644
index 0000000..e6f0307
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_home_search_normal_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_home_search_normal_holo.png
new file mode 100644
index 0000000..fe7144b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_home_search_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_home_voice_search_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_home_voice_search_holo.png
new file mode 100644
index 0000000..2fb71bf
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_home_voice_search_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_clear_active_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_clear_active_holo.png
new file mode 100644
index 0000000..b525ab0
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_clear_active_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_clear_normal_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_clear_normal_holo.png
new file mode 100644
index 0000000..2998311
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_clear_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_info_active_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_info_active_holo.png
new file mode 100644
index 0000000..194e274
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_info_active_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_info_normal_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_info_normal_holo.png
new file mode 100644
index 0000000..ed65334
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_info_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_market_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_market_holo.png
new file mode 100644
index 0000000..cd8ac0b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_market_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png
new file mode 100644
index 0000000..a280bab
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png
new file mode 100644
index 0000000..06b2aa9
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/icon_edit.png b/FairphoneHome/bin/res/drawable-hdpi/icon_edit.png
new file mode 100644
index 0000000..01b4a0b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/icon_edit.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_app_icon.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_app_icon.png
new file mode 100644
index 0000000..fd580c2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_app_icon.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_app_icon_small.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_app_icon_small.png
new file mode 100644
index 0000000..141d677
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_app_icon_small.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_arrow_big.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_arrow_big.png
new file mode 100644
index 0000000..ba5ecdd
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_arrow_big.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_delete_higlight.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_delete_higlight.png
new file mode 100644
index 0000000..5b40940
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_delete_higlight.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_delete_x.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_delete_x.png
new file mode 100644
index 0000000..f003b07
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_delete_x.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_all_apps.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_all_apps.png
new file mode 100644
index 0000000..d699556
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_all_apps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_drag_intro.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_drag_intro.png
new file mode 100644
index 0000000..0fa8018
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_drag_intro.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_favourite_apps.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_favourite_apps.png
new file mode 100644
index 0000000..f04e325
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_edit_favourite_apps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_fairphone_logo.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_fairphone_logo.png
new file mode 100644
index 0000000..ad81c9d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_fairphone_logo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_hand.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_hand.png
new file mode 100644
index 0000000..094a543
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_hand.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_hand_shadow.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_hand_shadow.png
new file mode 100644
index 0000000..9f8ad29
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_hand_shadow.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_icon_all_apps.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_icon_all_apps.png
new file mode 100644
index 0000000..1c420eb
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_icon_all_apps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_icon_select.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_icon_select.png
new file mode 100644
index 0000000..466962c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_icon_select.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_language_button_press.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_language_button_press.png
new file mode 100644
index 0000000..8c4114f
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_language_button_press.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_language_button_up.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_language_button_up.png
new file mode 100644
index 0000000..7769e2a
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_language_button_up.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_menu.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_menu.png
new file mode 100644
index 0000000..194b94f
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_menu.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_selection_big.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_selection_big.png
new file mode 100644
index 0000000..e4941c5
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_selection_big.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_wifi_button_press.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_wifi_button_press.png
new file mode 100644
index 0000000..9aa8f1e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_wifi_button_press.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/oobe_wifi_button_up.png b/FairphoneHome/bin/res/drawable-hdpi/oobe_wifi_button_up.png
new file mode 100644
index 0000000..3514d13
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/oobe_wifi_button_up.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/overscroll_glow_left.9.png b/FairphoneHome/bin/res/drawable-hdpi/overscroll_glow_left.9.png
new file mode 100644
index 0000000..4a664ae
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/overscroll_glow_left.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/overscroll_glow_right.9.png b/FairphoneHome/bin/res/drawable-hdpi/overscroll_glow_right.9.png
new file mode 100644
index 0000000..66b6167
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/overscroll_glow_right.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/page_hover_left_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/page_hover_left_holo.9.png
new file mode 100644
index 0000000..f1711aa
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/page_hover_left_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/page_hover_right_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/page_hover_right_holo.9.png
new file mode 100644
index 0000000..acc4759
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/page_hover_right_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/paged_view_indicator.9.png b/FairphoneHome/bin/res/drawable-hdpi/paged_view_indicator.9.png
new file mode 100644
index 0000000..c205ec4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/paged_view_indicator.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/portal_container_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/portal_container_holo.9.png
new file mode 100644
index 0000000..7e5e74c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/portal_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/portal_ring_inner_holo.png b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_inner_holo.png
new file mode 100644
index 0000000..32d67ad
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/portal_ring_inner_nolip_holo.png b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_inner_nolip_holo.png
new file mode 100644
index 0000000..98ac813
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_inner_nolip_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/portal_ring_outer_holo.png b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_outer_holo.png
new file mode 100644
index 0000000..54ebe43
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/portal_ring_rest.png b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_rest.png
new file mode 100644
index 0000000..b3718f6
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/portal_ring_rest.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/search_frame.9.png b/FairphoneHome/bin/res/drawable-hdpi/search_frame.9.png
new file mode 100644
index 0000000..394e3d0
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/search_frame.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/swipe_menu_shadow_bottom.png b/FairphoneHome/bin/res/drawable-hdpi/swipe_menu_shadow_bottom.png
new file mode 100644
index 0000000..b4b5606
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/swipe_menu_shadow_bottom.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/swipe_menu_shadow_top.png b/FairphoneHome/bin/res/drawable-hdpi/swipe_menu_shadow_top.png
new file mode 100644
index 0000000..a3f0e50
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/swipe_menu_shadow_top.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_selected_focused_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..1e6ab9a
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_selected_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..4dfaac8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..dbbc315
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..4060199
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..8d03d51
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..c251c6a
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..def9c87
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..86304e5
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_container_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..1f46314
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_preview_tile.png b/FairphoneHome/bin/res/drawable-hdpi/widget_preview_tile.png
new file mode 100644
index 0000000..43cdd6c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_preview_tile.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_resize_frame_holo.9.png b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..c3c303e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_bottom.png b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..6b9bdc2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_left.png b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..1f91d15
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_right.png b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..7c3d0da
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_top.png b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..3866879
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-hdpi/workspace_bg.9.png b/FairphoneHome/bin/res/drawable-hdpi/workspace_bg.9.png
new file mode 100644
index 0000000..c3eaf81
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/app_switcher_icon_sync.png b/FairphoneHome/bin/res/drawable-mdpi/app_switcher_icon_sync.png
new file mode 100644
index 0000000..c993406
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/app_switcher_icon_sync.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/apps_customize_bg.png b/FairphoneHome/bin/res/drawable-mdpi/apps_customize_bg.png
new file mode 100644
index 0000000..775e6e8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/apps_customize_bg.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/bg_appwidget_error.9.png b/FairphoneHome/bin/res/drawable-mdpi/bg_appwidget_error.9.png
new file mode 100644
index 0000000..50d06f1
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/bg_appwidget_error.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/bg_cling1.png b/FairphoneHome/bin/res/drawable-mdpi/bg_cling1.png
new file mode 100644
index 0000000..ac8e421
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/bg_cling1.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/bg_cling2.png b/FairphoneHome/bin/res/drawable-mdpi/bg_cling2.png
new file mode 100644
index 0000000..a6ddf43
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/bg_cling2.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/bg_cling3.png b/FairphoneHome/bin/res/drawable-mdpi/bg_cling3.png
new file mode 100644
index 0000000..767f5a9
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/bg_cling3.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/bg_cling4.png b/FairphoneHome/bin/res/drawable-mdpi/bg_cling4.png
new file mode 100644
index 0000000..7667032
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/bg_cling4.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/bg_cling5.png b/FairphoneHome/bin/res/drawable-mdpi/bg_cling5.png
new file mode 100644
index 0000000..ced1506
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/bg_cling5.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/btn_cling_normal.9.png b/FairphoneHome/bin/res/drawable-mdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..a1ca0d9
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/btn_cling_pressed.9.png b/FairphoneHome/bin/res/drawable-mdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..f75ffe2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/cling.png b/FairphoneHome/bin/res/drawable-mdpi/cling.png
new file mode 100644
index 0000000..2f2abfb
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/cling.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/divider_launcher_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/divider_launcher_holo.9.png
new file mode 100644
index 0000000..2131b61
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/flying_icon_bg_pressed.9.png b/FairphoneHome/bin/res/drawable-mdpi/flying_icon_bg_pressed.9.png
new file mode 100644
index 0000000..43ce30b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/flying_icon_bg_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/focused_bg.9.png b/FairphoneHome/bin/res/drawable-mdpi/focused_bg.9.png
new file mode 100644
index 0000000..a77f98d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/focused_bg.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/fp_wallpaper_default.png b/FairphoneHome/bin/res/drawable-mdpi/fp_wallpaper_default.png
new file mode 100644
index 0000000..8a65f38
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/fp_wallpaper_default.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/grid_focused.9.png b/FairphoneHome/bin/res/drawable-mdpi/grid_focused.9.png
new file mode 100644
index 0000000..bd421fe
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/grid_focused.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/grid_pressed.9.png b/FairphoneHome/bin/res/drawable-mdpi/grid_pressed.9.png
new file mode 100644
index 0000000..268c415
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/grid_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/grid_selected.9.png b/FairphoneHome/bin/res/drawable-mdpi/grid_selected.9.png
new file mode 100644
index 0000000..7763d1e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/grid_selected.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/hand.png b/FairphoneHome/bin/res/drawable-mdpi/hand.png
new file mode 100644
index 0000000..365282e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/hand.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/home_press.9.png b/FairphoneHome/bin/res/drawable-mdpi/home_press.9.png
new file mode 100644
index 0000000..a9d7c9e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/home_press.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/homescreen_blue_normal_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/homescreen_blue_normal_holo.9.png
new file mode 100644
index 0000000..153ed51
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/homescreen_blue_normal_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/homescreen_blue_strong_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/homescreen_blue_strong_holo.9.png
new file mode 100644
index 0000000..29c42c1
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/homescreen_blue_strong_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/hotseat_scrubber_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/hotseat_scrubber_holo.9.png
new file mode 100644
index 0000000..f07690a
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/hotseat_scrubber_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/hotseat_track_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/hotseat_track_holo.9.png
new file mode 100644
index 0000000..2f8bb02
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/hotseat_track_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_allapps.png b/FairphoneHome/bin/res/drawable-mdpi/ic_allapps.png
new file mode 100644
index 0000000..918fb25
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_allapps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_allapps_pressed.png b/FairphoneHome/bin/res/drawable-mdpi/ic_allapps_pressed.png
new file mode 100644
index 0000000..c962410
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_home_all_apps_holo_dark.png b/FairphoneHome/bin/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
new file mode 100644
index 0000000..47e5532
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_home_search_normal_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_home_search_normal_holo.png
new file mode 100644
index 0000000..8676484
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_home_search_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_home_voice_search_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_home_voice_search_holo.png
new file mode 100644
index 0000000..2deac3e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_home_voice_search_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_clear_active_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_clear_active_holo.png
new file mode 100644
index 0000000..30df91b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_clear_active_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_clear_normal_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_clear_normal_holo.png
new file mode 100644
index 0000000..72bfb4d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_clear_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_info_active_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_info_active_holo.png
new file mode 100644
index 0000000..5d3fe4e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_info_active_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_info_normal_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_info_normal_holo.png
new file mode 100644
index 0000000..2c67991
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_info_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_market_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_market_holo.png
new file mode 100644
index 0000000..56e98f8
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_market_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png
new file mode 100644
index 0000000..934014d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png
new file mode 100644
index 0000000..dbb31f7
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/overscroll_glow_left.9.png b/FairphoneHome/bin/res/drawable-mdpi/overscroll_glow_left.9.png
new file mode 100644
index 0000000..8ebce44
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/overscroll_glow_left.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/overscroll_glow_right.9.png b/FairphoneHome/bin/res/drawable-mdpi/overscroll_glow_right.9.png
new file mode 100644
index 0000000..40a2e43
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/overscroll_glow_right.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/page_hover_left_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/page_hover_left_holo.9.png
new file mode 100644
index 0000000..420c275
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/page_hover_left_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/page_hover_right_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/page_hover_right_holo.9.png
new file mode 100644
index 0000000..d0f05b9
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/page_hover_right_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/paged_view_indicator.9.png b/FairphoneHome/bin/res/drawable-mdpi/paged_view_indicator.9.png
new file mode 100644
index 0000000..c0502b4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/paged_view_indicator.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/portal_container_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/portal_container_holo.9.png
new file mode 100644
index 0000000..535da5d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/portal_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/portal_ring_inner_holo.png b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_inner_holo.png
new file mode 100644
index 0000000..e89ff00
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/portal_ring_inner_nolip_holo.png b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_inner_nolip_holo.png
new file mode 100644
index 0000000..6da00b2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_inner_nolip_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/portal_ring_outer_holo.png b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_outer_holo.png
new file mode 100644
index 0000000..e9f96a0
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/portal_ring_rest.png b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_rest.png
new file mode 100644
index 0000000..97166b4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/portal_ring_rest.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/search_frame.9.png b/FairphoneHome/bin/res/drawable-mdpi/search_frame.9.png
new file mode 100644
index 0000000..53a8de5
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/search_frame.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_selected_focused_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..bce0e08
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_selected_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..dd022de
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..b2d5760
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..2852fb5
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..43b91e6
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..c9c32c9
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..635f9f6
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..d2716b3
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_container_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..cbb5149
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_preview_tile.png b/FairphoneHome/bin/res/drawable-mdpi/widget_preview_tile.png
new file mode 100644
index 0000000..89221f2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_preview_tile.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_resize_frame_holo.9.png b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..5fa729b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_bottom.png b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..98afbe0
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_left.png b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..ccaf83f
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_right.png b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..506d131
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_top.png b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..428f77e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-mdpi/workspace_bg.9.png b/FairphoneHome/bin/res/drawable-mdpi/workspace_bg.9.png
new file mode 100644
index 0000000..97709dc
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/background.png b/FairphoneHome/bin/res/drawable-nodpi/background.png
new file mode 100644
index 0000000..8ba56ed
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/background.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/edit_text.png b/FairphoneHome/bin/res/drawable-nodpi/edit_text.png
new file mode 100644
index 0000000..6dbaa54
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/edit_text.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/fp_fav_background.png b/FairphoneHome/bin/res/drawable-nodpi/fp_fav_background.png
new file mode 100644
index 0000000..acfda1d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/fp_fav_background.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/fp_fav_icon_ring.png b/FairphoneHome/bin/res/drawable-nodpi/fp_fav_icon_ring.png
new file mode 100644
index 0000000..2d8c057
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/fp_fav_icon_ring.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/fp_wallpaper_default.png b/FairphoneHome/bin/res/drawable-nodpi/fp_wallpaper_default.png
new file mode 100644
index 0000000..8a65f38
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/fp_wallpaper_default.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/fp_wallpaper_default_small.png b/FairphoneHome/bin/res/drawable-nodpi/fp_wallpaper_default_small.png
new file mode 100644
index 0000000..d30f10d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/fp_wallpaper_default_small.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/icon_all_apps.png b/FairphoneHome/bin/res/drawable-nodpi/icon_all_apps.png
new file mode 100644
index 0000000..426658d
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/icon_all_apps.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-nodpi/icon_clean.png b/FairphoneHome/bin/res/drawable-nodpi/icon_clean.png
new file mode 100644
index 0000000..52e2a62
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-nodpi/icon_clean.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_1.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_1.png
new file mode 100644
index 0000000..8871eeb
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_1.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_10.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_10.png
new file mode 100644
index 0000000..b231db2
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_10.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_11.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_11.png
new file mode 100644
index 0000000..1b7d055
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_11.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_12.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_12.png
new file mode 100644
index 0000000..011acb5
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_12.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_13.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_13.png
new file mode 100644
index 0000000..ac5d0bd
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_13.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_2.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_2.png
new file mode 100644
index 0000000..50b101e
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_2.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_3.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_3.png
new file mode 100644
index 0000000..db6914b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_3.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_4.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_4.png
new file mode 100644
index 0000000..441f91c
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_4.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_5.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_5.png
new file mode 100644
index 0000000..d1228e4
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_5.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_6.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_6.png
new file mode 100644
index 0000000..782e4c7
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_6.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_7.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_7.png
new file mode 100644
index 0000000..b2e1541
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_7.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_8.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_8.png
new file mode 100644
index 0000000..adafc7b
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_8.png
Binary files differ
diff --git a/FairphoneHome/bin/res/drawable-xxhdpi/oobe_9.png b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_9.png
new file mode 100644
index 0000000..3e324f3
--- /dev/null
+++ b/FairphoneHome/bin/res/drawable-xxhdpi/oobe_9.png
Binary files differ
diff --git a/FairphoneHome/bin/res/mipmap-hdpi/ic_launcher_application.png b/FairphoneHome/bin/res/mipmap-hdpi/ic_launcher_application.png
new file mode 100644
index 0000000..2d0ad2a
--- /dev/null
+++ b/FairphoneHome/bin/res/mipmap-hdpi/ic_launcher_application.png
Binary files differ
diff --git a/FairphoneHome/bin/res/mipmap-hdpi/ic_launcher_wallpaper.png b/FairphoneHome/bin/res/mipmap-hdpi/ic_launcher_wallpaper.png
new file mode 100644
index 0000000..85dcabe
--- /dev/null
+++ b/FairphoneHome/bin/res/mipmap-hdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/FairphoneHome/bin/res/mipmap-hdpi/icon_launcher_home.png b/FairphoneHome/bin/res/mipmap-hdpi/icon_launcher_home.png
new file mode 100644
index 0000000..9a0d866
--- /dev/null
+++ b/FairphoneHome/bin/res/mipmap-hdpi/icon_launcher_home.png
Binary files differ
diff --git a/FairphoneHome/bin/resources.ap_ b/FairphoneHome/bin/resources.ap_
new file mode 100644
index 0000000..beab636
--- /dev/null
+++ b/FairphoneHome/bin/resources.ap_
Binary files differ
diff --git a/FairphoneHome/fill_screens.py b/FairphoneHome/fill_screens.py
new file mode 100755
index 0000000..5841b8e
--- /dev/null
+++ b/FairphoneHome/fill_screens.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python2.5
+
+import cgi
+import os
+import shutil
+import sys
+import sqlite3
+
+SCREENS = 5
+COLUMNS = 4
+ROWS = 4
+CELL_SIZE = 110
+
+DIR = "db_files"
+AUTO_FILE = "launcher.db"
+
+APPLICATION_COMPONENTS = [
+  "com.android.calculator2/com.android.calculator2.Calculator",
+  "com.android.providers.downloads.ui/com.android.providers.downloads.ui.DownloadList",
+  "com.android.settings/com.android.settings.Settings",
+  "com.android.mms/com.android.mms.ui.ConversationList",
+  "com.android.contacts/com.android.contacts.activities.PeopleActivity",
+  "com.android.contacts/com.android.contacts.activities.DialtactsActivity"
+]
+
+def usage():
+  print "usage: fill_screens.py -- fills up the launcher db"
+
+
+def make_dir():
+  shutil.rmtree(DIR, True)
+  os.makedirs(DIR)
+
+def pull_file(fn):
+  print "pull_file: " + fn
+  rv = os.system("adb pull"
+    + " /data/data/com.android.launcher/databases/launcher.db"
+    + " " + fn);
+  if rv != 0:
+    print "adb pull failed"
+    sys.exit(1)
+
+def push_file(fn):
+  print "push_file: " + fn
+  rv = os.system("adb push"
+    + " " + fn
+    + " /data/data/com.android.launcher/databases/launcher.db")
+  if rv != 0:
+    print "adb push failed"
+    sys.exit(1)
+
+def process_file(fn):
+  print "process_file: " + fn
+  conn = sqlite3.connect(fn)
+  c = conn.cursor()
+  c.execute("DELETE FROM favorites")
+
+  intentFormat = "#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=%s;end"
+
+  id = 0;
+  for s in range(SCREENS):
+    for x in range(ROWS):
+      for y in range(COLUMNS):
+        id += 1
+        insert = "INSERT into favorites (_id, title, intent, container, screen, cellX, cellY, spanX, spanY, itemType, appWidgetId, iconType) VALUES (%d, '%s', '%s', %d, %d, %d, %d, %d, %d, %d, %d, %d)"
+        insert = insert % (id, "title", "", -100, s, x, y, 1, 1, 2, -1, 0)
+        c.execute(insert)
+        folder_id = id
+
+        for z in range(15):
+          id += 1
+          intent = intentFormat % (APPLICATION_COMPONENTS[id % len(APPLICATION_COMPONENTS)])
+          insert = "INSERT into favorites (_id, title, intent, container, screen, cellX, cellY, spanX, spanY, itemType, appWidgetId, iconType) VALUES (%d, '%s', '%s', %d, %d, %d, %d, %d, %d, %d, %d, %d)"
+          insert = insert % (id, "title", intent, folder_id, 0, 0, 0, 1, 1, 0, -1, 0)
+          c.execute(insert)
+
+  conn.commit()
+  c.close()
+
+def main(argv):
+  if len(argv) == 1:
+    make_dir()
+    pull_file(AUTO_FILE)
+    process_file(AUTO_FILE)
+    push_file(AUTO_FILE)
+  else:
+    usage()
+
+if __name__=="__main__":
+  main(sys.argv)
diff --git a/FairphoneHome/gen/org/fairphone/launcher/BuildConfig.java b/FairphoneHome/gen/org/fairphone/launcher/BuildConfig.java
new file mode 100644
index 0000000..7e10afd
--- /dev/null
+++ b/FairphoneHome/gen/org/fairphone/launcher/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package org.fairphone.launcher;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/FairphoneHome/gen/org/fairphone/launcher/Manifest.java b/FairphoneHome/gen/org/fairphone/launcher/Manifest.java
new file mode 100644
index 0000000..b6d25fe
--- /dev/null
+++ b/FairphoneHome/gen/org/fairphone/launcher/Manifest.java
@@ -0,0 +1,18 @@
+/* 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 org.fairphone.launcher;
+
+public final class Manifest {
+    public static final class permission {
+        public static final String INSTALL_SHORTCUT="com.android.launcher.permission.INSTALL_SHORTCUT";
+        public static final String PRELOAD_WORKSPACE="com.android.launcher.permission.PRELOAD_WORKSPACE";
+        public static final String READ_SETTINGS="com.android.launcher.permission.READ_SETTINGS";
+        public static final String UNINSTALL_SHORTCUT="com.android.launcher.permission.UNINSTALL_SHORTCUT";
+        public static final String WRITE_SETTINGS="com.android.launcher.permission.WRITE_SETTINGS";
+    }
+}
diff --git a/FairphoneHome/gen/org/fairphone/launcher/R.java b/FairphoneHome/gen/org/fairphone/launcher/R.java
new file mode 100644
index 0000000..b296f9e
--- /dev/null
+++ b/FairphoneHome/gen/org/fairphone/launcher/R.java
@@ -0,0 +1,2759 @@
+/* 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 org.fairphone.launcher;
+
+public final class R {
+    public static final class anim {
+        public static final int button_select_animation=0x7f050000;
+        public static final int fade_in_fast=0x7f050001;
+        public static final int fade_in_slow=0x7f050002;
+        public static final int fade_out_fast=0x7f050003;
+        public static final int fade_out_slow=0x7f050004;
+        public static final int menu_activation_zone_appear=0x7f050005;
+        public static final int menu_activation_zone_disappear=0x7f050006;
+        public static final int menu_appear_from_left_animation=0x7f050007;
+        public static final int menu_appear_from_right_animation=0x7f050008;
+        public static final int menu_background_fade_in=0x7f050009;
+        public static final int menu_background_fade_out=0x7f05000a;
+        public static final int menu_disappear_to_left_animation=0x7f05000b;
+        public static final int menu_disappear_to_right_animation=0x7f05000c;
+        public static final int menu_edge_edit_button_fade_in=0x7f05000d;
+        public static final int menu_icon_ring_fade_in=0x7f05000e;
+        public static final int menu_icon_ring_fade_out=0x7f05000f;
+        public static final int tutorial_edge_swipe_arrow_main=0x7f050010;
+        public static final int tutorial_edge_swipe_arrow_main_2=0x7f050011;
+        public static final int tutorial_edge_swipe_arrow_outro=0x7f050012;
+        public static final int tutorial_edge_swipe_hand_main=0x7f050013;
+        public static final int tutorial_edge_swipe_hand_main_2=0x7f050014;
+        public static final int tutorial_edge_swipe_hand_outro=0x7f050015;
+        public static final int tutorial_edge_swipe_touch_main=0x7f050016;
+        public static final int tutorial_edge_swipe_touch_main_2=0x7f050017;
+        public static final int tutorial_edge_swipe_touch_outro=0x7f050018;
+        public static final int tutorial_edit_favs_counter_main=0x7f050019;
+        public static final int tutorial_edit_favs_hand_main=0x7f05001a;
+        public static final int tutorial_edit_favs_hand_outro=0x7f05001b;
+        public static final int tutorial_edit_favs_icon_blue_main=0x7f05001c;
+        public static final int tutorial_edit_favs_icon_holder_main=0x7f05001d;
+        public static final int tutorial_edit_favs_icon_main=0x7f05001e;
+        public static final int tutorial_edit_favs_touch_main=0x7f05001f;
+        public static final int tutorial_intro=0x7f050020;
+        public static final int tutorial_outro=0x7f050021;
+        public static final int tutorial_title_text_intro_bottom=0x7f050022;
+        public static final int tutorial_title_text_intro_top=0x7f050023;
+    }
+    public static final class array {
+        public static final int extra_wallpapers=0x7f080002;
+        public static final int prefMoodChangerType=0x7f080000;
+        public static final int prefMoodChangerTypeValues=0x7f080001;
+        public static final int wallpapers=0x7f080003;
+    }
+    public static final class attr {
+        /**  The number of horizontal cells in the CellLayout 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int cellCountX=0x7f010004;
+        /**  The number of vertical cells in the CellLayout 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int cellCountY=0x7f010005;
+        /**  The height of a single cell 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int cellHeight=0x7f010007;
+        /**  The width of a single cell 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int cellWidth=0x7f010006;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int className=0x7f010020;
+        /**  The x index of the item to be focused in the cling 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int clingFocusedX=0x7f01001e;
+        /**  The y index of the item to be focused in the cling 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int clingFocusedY=0x7f01001f;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int container=0x7f010022;
+        /**  The first screen the workspace should display. 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int defaultScreen=0x7f010003;
+        /**  Orientation of a widget. 
+         <p>Must be one of the following constant values.</p>
+<table>
+<colgroup align="left" />
+<colgroup align="left" />
+<colgroup align="left" />
+<tr><th>Constant</th><th>Value</th><th>Description</th></tr>
+<tr><td><code>vertical</code></td><td>0</td><td> Vertical widget. </td></tr>
+<tr><td><code>horizontal</code></td><td>1</td><td> Horizontal widget. </td></tr>
+</table>
+         */
+        public static final int direction=0x7f010000;
+        /**  Used to identify how to draw the cling bg 
+         <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int drawIdentifier=0x7f010002;
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int heightGap=0x7f010009;
+        /** <p>Must be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+         */
+        public static final int icon=0x7f010028;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int key=0x7f01002b;
+        /**  Max number of cells of applications horizontally 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int maxAppCellCountX=0x7f010018;
+        /**  Max number of cells of applications vertically 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int maxAppCellCountY=0x7f010019;
+        /**  The max gap size for each dimension 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int maxGap=0x7f01000a;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int packageName=0x7f010021;
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageLayoutHeightGap=0x7f010010;
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageLayoutPaddingBottom=0x7f010012;
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageLayoutPaddingLeft=0x7f010013;
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageLayoutPaddingRight=0x7f010014;
+        /**  The padding of the pages that are dynamically created per page 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageLayoutPaddingTop=0x7f010011;
+        /**  A spacing override for the icons within a page 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageLayoutWidthGap=0x7f01000f;
+        /**  The space between adjacent pages of the PagedView. 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int pageSpacing=0x7f010015;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int screen=0x7f010023;
+        /**  The padding for the scroll indicator area 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int scrollIndicatorPaddingLeft=0x7f010016;
+        /** <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int scrollIndicatorPaddingRight=0x7f010017;
+        /**  The source view to generate and apply the drawable states to/from 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int sourceImageViewId=0x7f01000e;
+        /**  The source view to delegate touch presses events to. 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int sourceViewId=0x7f010001;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int spanX=0x7f010026;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int spanY=0x7f010027;
+        /**  The color of the stroke outline 
+         <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int strokeColor=0x7f01000b;
+        /**  The color of the text 
+         <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int strokeTextColor=0x7f01000c;
+        /**  The width of the stroke 
+         <p>Must be a floating point value, such as "<code>1.2</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int strokeWidth=0x7f01000d;
+        /** <p>Must be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+         */
+        public static final int title=0x7f010029;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int uri=0x7f01002a;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int value=0x7f01002c;
+        /**  Vertical spacing between widgets 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int widgetCellHeightGap=0x7f01001b;
+        /**  Horizontal spacing between widgets and wallpapers 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int widgetCellWidthGap=0x7f01001a;
+        /**  Number of widgets horizontally 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int widgetCountX=0x7f01001c;
+        /**  Number of widgets vertically 
+         <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int widgetCountY=0x7f01001d;
+        /**  An override for the width and height gap to allow users to specify
+             a specific size for the page using spacing instead of resolving the
+             spacing from the width of the page 
+         <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int widthGap=0x7f010008;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int x=0x7f010024;
+        /** <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+         */
+        public static final int y=0x7f010025;
+    }
+    public static final class bool {
+        public static final int allow_rotation=0x7f0b0002;
+        public static final int config_largeHeap=0x7f0b0000;
+        /**  Whether or not to use custom clings if a custom workspace layout is passed in 
+         */
+        public static final int config_useCustomClings=0x7f0b0005;
+        /**  Workspace 
+ Whether or not the drop targets drop down as opposed to fade in 
+ Workspace 
+ Whether or not the drop targets drop down as opposed to fade in 
+         */
+        public static final int config_useDropTargetDownTransition=0x7f0b0003;
+        /**  Whether or not to fade the side pages 
+ Whether or not to fade the side pages 
+ Workspace 
+ Whether or not to fade the side pages 
+         */
+        public static final int config_workspaceFadeAdjacentScreens=0x7f0b0004;
+        /**  Hotseat 
+         */
+        public static final int hotseat_transpose_layout_with_orientation=0x7f0b0006;
+        public static final int is_large_screen=0x7f0b0001;
+    }
+    public static final class color {
+        public static final int appwidget_error_color=0x7f0a0003;
+        public static final int bubble_dark_background=0x7f0a0002;
+        public static final int button_app_switcher_reset_text=0x7f0a000d;
+        /** 
+         The color tints to apply to the text and drag view when hovering
+         over the delete target or the info target
+    
+         */
+        public static final int delete_target_hover_tint=0x7f0a0000;
+        public static final int google_blue=0x7f0a000b;
+        public static final int google_progressbar_grey=0x7f0a000c;
+        public static final int info_target_hover_tint=0x7f0a0001;
+        public static final int text_color_white=0x7f0a0007;
+        public static final int text_shadow_color=0x7f0a0008;
+        public static final int transparent=0x7f0a000a;
+        public static final int white=0x7f0a0009;
+        public static final int workspace_all_apps_and_delete_zone_text_color=0x7f0a0004;
+        public static final int workspace_all_apps_and_delete_zone_text_shadow_color=0x7f0a0005;
+        public static final int workspace_icon_text_color=0x7f0a0006;
+    }
+    public static final class dimen {
+        public static final int app_icon_drawable_padding=0x7f0e0019;
+        public static final int app_icon_drawable_padding_land=0x7f0e001a;
+        public static final int app_icon_padding_top=0x7f0e001b;
+        public static final int app_icon_size=0x7f0e0022;
+        public static final int app_widget_preview_label_margin_left=0x7f0e0037;
+        public static final int app_widget_preview_label_margin_right=0x7f0e0038;
+        public static final int app_widget_preview_label_margin_top=0x7f0e0036;
+        /**  Padding applied to AppWidget previews 
+         */
+        public static final int app_widget_preview_padding_left=0x7f0e0033;
+        public static final int app_widget_preview_padding_right=0x7f0e0034;
+        public static final int app_widget_preview_padding_top=0x7f0e0035;
+        /**  The width can be 76dp because we don't have B padding 
+         */
+        public static final int apps_customize_cell_height=0x7f0e0024;
+        /**  The width can be 72dp because we don't have L/R padding 
+ AppsCustomize 
+         */
+        public static final int apps_customize_cell_width=0x7f0e0023;
+        public static final int apps_customize_max_gap=0x7f0e0025;
+        public static final int apps_customize_pageLayoutHeightGap=0x7f0e0068;
+        public static final int apps_customize_pageLayoutPaddingBottom=0x7f0e006a;
+        public static final int apps_customize_pageLayoutPaddingLeft=0x7f0e006b;
+        public static final int apps_customize_pageLayoutPaddingRight=0x7f0e006c;
+        /**  AppsCustomize 
+         */
+        public static final int apps_customize_pageLayoutPaddingTop=0x7f0e0069;
+        /**  AppsCustomize 
+         */
+        public static final int apps_customize_pageLayoutWidthGap=0x7f0e0067;
+        /**  The height of the tab bar - if this changes, we should update the
+         external icon width/height above to compensate 
+         */
+        public static final int apps_customize_tab_bar_height=0x7f0e0020;
+        public static final int apps_customize_tab_bar_margin_top=0x7f0e0021;
+        public static final int apps_customize_widget_cell_height_gap=0x7f0e0027;
+        public static final int apps_customize_widget_cell_width_gap=0x7f0e0026;
+        /**  height of the bottom row of controls 
+ height of the bottom row of controls 
+ height of the bottom row of controls 
+         */
+        public static final int button_bar_height=0x7f0e0028;
+        /**  Because portal animations go beyond the bounds of an icon, we need
+         to make the dock layout slightly larger than the button_bar_height 
+         */
+        public static final int button_bar_height_bottom_padding=0x7f0e002a;
+        public static final int button_bar_height_plus_padding=0x7f0e002d;
+        /**  Because portal animations go beyond the bounds of an icon, we need
+         to make the dock layout slightly larger than the button_bar_height 
+ Because portal animations go beyond the bounds of an icon, we need
+         to make the dock layout slightly larger than the button_bar_height 
+         */
+        public static final int button_bar_height_top_padding=0x7f0e0029;
+        public static final int button_bar_width_left_padding=0x7f0e002b;
+        public static final int button_bar_width_right_padding=0x7f0e002c;
+        public static final int cell_layout_bottom_padding=0x7f0e0062;
+        public static final int cell_layout_bottom_padding_land=0x7f0e0049;
+        public static final int cell_layout_bottom_padding_port=0x7f0e0048;
+        /**  Block spacing on each side of the screen.  And also padding
+         for the portals to look right. 
+ Workspace 
+ Block spacing on each side of the screen.  And also padding
+         for the portals to look right. 
+         */
+        public static final int cell_layout_left_padding=0x7f0e005f;
+        public static final int cell_layout_left_padding_land=0x7f0e0043;
+        /**  CellLayout padding 
+ CellLayout padding land / port
+         */
+        public static final int cell_layout_left_padding_port=0x7f0e0042;
+        public static final int cell_layout_right_padding=0x7f0e0060;
+        public static final int cell_layout_right_padding_land=0x7f0e0045;
+        public static final int cell_layout_right_padding_port=0x7f0e0044;
+        public static final int cell_layout_top_padding=0x7f0e0061;
+        public static final int cell_layout_top_padding_land=0x7f0e0047;
+        public static final int cell_layout_top_padding_port=0x7f0e0046;
+        /**  Cling 
+         */
+        public static final int clingPunchThroughGraphicCenterRadius=0x7f0e0000;
+        /**  The offset for the text in the cling 
+         */
+        public static final int cling_text_block_offset_x=0x7f0e0002;
+        public static final int cling_text_block_offset_y=0x7f0e0003;
+        /**  When dragging items on the workspace, the number of dps by which the position of
+     the drag view should be offset from the position of the original view. 
+         */
+        public static final int dragViewOffsetX=0x7f0e0030;
+        public static final int dragViewOffsetY=0x7f0e0031;
+        /**   When dragging an item, how much bigger (fixed dps) the dragged view
+          should be. If 0, it will not be scaled at all. 
+         */
+        public static final int dragViewScale=0x7f0e0032;
+        /**  Drag padding to add to the bottom of drop targets 
+ Drag padding to add to the bottom of drop targets 
+         */
+        public static final int drop_target_drag_padding=0x7f0e002e;
+        /**  EdgeSwipe deadzones
+         */
+        public static final int edge_swipe_inner_deadzone=0x7f0e005c;
+        /**  	<dimen name="edge_swipe_up_limit">250dp</dimen> 
+ 	<dimen name="edge_swipe_down_limit">210dp</dimen> 
+ Edge swipe Radius Menu 
+         */
+        public static final int edge_swipe_menu_radius=0x7f0e005b;
+        public static final int edge_swipe_outer_deadzone=0x7f0e005d;
+        /**  EdgeSwipe 
+         */
+        public static final int edge_swipe_show_limit=0x7f0e005a;
+        /**  Clings 
+         */
+        public static final int folderClingMarginTop=0x7f0e0001;
+        public static final int folder_cell_height=0x7f0e000c;
+        public static final int folder_cell_width=0x7f0e000b;
+        public static final int folder_height_gap=0x7f0e0040;
+        public static final int folder_icon_padding_top=0x7f0e000d;
+        public static final int folder_name_padding=0x7f0e003e;
+        public static final int folder_padding=0x7f0e0041;
+        /**  The amount that the preview contents are inset from the preview background 
+         */
+        public static final int folder_preview_padding=0x7f0e003d;
+        /**  Folders 
+ The size of the image which sits behind the preview of the folder contents 
+ Folders 
+ The size of the image which sits behind the preview of the folder contents 
+         */
+        public static final int folder_preview_size=0x7f0e003c;
+        public static final int folder_width_gap=0x7f0e003f;
+        public static final int hotseat_cell_height=0x7f0e0013;
+        /**  Workspace 
+         */
+        public static final int hotseat_cell_width=0x7f0e0012;
+        public static final int hotseat_height_gap=0x7f0e0015;
+        /**  Hotseat 
+         */
+        public static final int hotseat_width_gap=0x7f0e0014;
+        public static final int qsb_bar_height=0x7f0e0006;
+        /**  Workspace 
+ qsb_bar_height_inset represents qsb_bar_height minus the padding
+         that we put on each page for allowing folders to draw out of bounds 
+ QSB 
+ qsb_bar_height_inset represents qsb_bar_height minus the padding
+         that we put on each page for allowing folders to draw out of bounds 
+ FPNOTE : This is changed for  
+ Workspace 
+ qsb_bar_height_inset represents qsb_bar_height minus the padding
+         that we put on each page for allowing folders to draw out of bounds 
+         */
+        public static final int qsb_bar_height_inset=0x7f0e0005;
+        public static final int qsb_padding_left=0x7f0e0007;
+        public static final int qsb_padding_right=0x7f0e0008;
+        public static final int reveal_radius=0x7f0e0004;
+        /**  Dragging 
+ the area at the edge of the screen that makes the workspace go left
+         or right while you're dragging. 
+         */
+        public static final int scroll_zone=0x7f0e002f;
+        public static final int search_bar_height=0x7f0e0009;
+        /**  Padding applied to shortcut previews 
+         */
+        public static final int shortcut_preview_padding_left=0x7f0e0039;
+        public static final int shortcut_preview_padding_right=0x7f0e003a;
+        public static final int shortcut_preview_padding_top=0x7f0e003b;
+        public static final int toolbar_button_horizontal_padding=0x7f0e001d;
+        /**  QSB 
+ QSB 
+         */
+        public static final int toolbar_button_vertical_padding=0x7f0e001c;
+        public static final int toolbar_external_icon_height=0x7f0e001f;
+        /**  External toolbar icon size (for bounds) 
+         */
+        public static final int toolbar_external_icon_width=0x7f0e001e;
+        public static final int workspace_bottom_padding=0x7f0e0066;
+        public static final int workspace_bottom_padding_land=0x7f0e0051;
+        public static final int workspace_bottom_padding_port=0x7f0e0050;
+        public static final int workspace_cell_height=0x7f0e006e;
+        public static final int workspace_cell_height_land=0x7f0e0054;
+        public static final int workspace_cell_height_port=0x7f0e0055;
+        /**  Workspace cell size 
+ Workspace cell size 
+         */
+        public static final int workspace_cell_width=0x7f0e006d;
+        /**  Workspace cell size 
+         */
+        public static final int workspace_cell_width_land=0x7f0e0052;
+        public static final int workspace_cell_width_port=0x7f0e0053;
+        public static final int workspace_divider_padding_bottom=0x7f0e0011;
+        /**  Workspace 
+         */
+        public static final int workspace_divider_padding_left=0x7f0e000e;
+        public static final int workspace_divider_padding_right=0x7f0e000f;
+        public static final int workspace_divider_padding_top=0x7f0e0010;
+        public static final int workspace_height_gap=0x7f0e0070;
+        public static final int workspace_height_gap_land=0x7f0e0058;
+        public static final int workspace_height_gap_port=0x7f0e0059;
+        public static final int workspace_icon_text_size=0x7f0e0017;
+        /**  Workspace padding 
+ Workspace padding 
+         */
+        public static final int workspace_left_padding=0x7f0e0063;
+        public static final int workspace_left_padding_land=0x7f0e004b;
+        /**  Workspace padding 
+         */
+        public static final int workspace_left_padding_port=0x7f0e004a;
+        public static final int workspace_max_gap=0x7f0e000a;
+        public static final int workspace_overscroll_drawable_padding=0x7f0e0016;
+        /**  We really want the page spacing to be the max of either the button bar
+     height or the qsb bar height 
+         */
+        public static final int workspace_page_spacing=0x7f0e005e;
+        public static final int workspace_right_padding=0x7f0e0064;
+        public static final int workspace_right_padding_land=0x7f0e004d;
+        public static final int workspace_right_padding_port=0x7f0e004c;
+        public static final int workspace_spring_loaded_page_spacing=0x7f0e0018;
+        public static final int workspace_top_padding=0x7f0e0065;
+        public static final int workspace_top_padding_land=0x7f0e004f;
+        public static final int workspace_top_padding_port=0x7f0e004e;
+        public static final int workspace_width_gap=0x7f0e006f;
+        public static final int workspace_width_gap_land=0x7f0e0056;
+        public static final int workspace_width_gap_port=0x7f0e0057;
+    }
+    public static final class drawable {
+        public static final int all_apps_button_icon=0x7f020000;
+        public static final int app_placeholder_blue_icon=0x7f020001;
+        public static final int app_placeholder_icon=0x7f020002;
+        public static final int app_switcher_background_right=0x7f020003;
+        public static final int app_switcher_background_right_item=0x7f020004;
+        public static final int app_switcher_button_reset_disabled=0x7f020005;
+        public static final int app_switcher_button_reset_press=0x7f020006;
+        public static final int app_switcher_button_reset_up=0x7f020007;
+        public static final int app_switcher_divider=0x7f020008;
+        public static final int app_switcher_icon_all_apps=0x7f020009;
+        public static final int app_switcher_icon_apps=0x7f02000a;
+        public static final int app_switcher_icon_sync=0x7f02000b;
+        public static final int app_switcher_list_background=0x7f02000c;
+        public static final int app_switcher_separator=0x7f02000d;
+        public static final int apps_customize_bg=0x7f02000e;
+        public static final int apps_widgets_bg=0x7f02000f;
+        public static final int appswicther_widget_icon=0x7f020010;
+        public static final int background=0x7f020011;
+        public static final int bg_appwidget_error=0x7f020012;
+        public static final int bg_cling1=0x7f020013;
+        public static final int bg_cling2=0x7f020014;
+        public static final int bg_cling3=0x7f020015;
+        public static final int bg_cling4=0x7f020016;
+        public static final int bg_cling5=0x7f020017;
+        public static final int bg_gradient=0x7f020018;
+        public static final int btn_cling_normal=0x7f020019;
+        public static final int btn_cling_pressed=0x7f02001a;
+        public static final int button_app_switcher_reset=0x7f02001b;
+        public static final int button_last_used_app=0x7f02001c;
+        public static final int cling=0x7f02001d;
+        public static final int cling_button_bg=0x7f02001e;
+        public static final int divider_launcher_holo=0x7f02001f;
+        public static final int edge_swipe_menu_highlight=0x7f020020;
+        public static final int edit_holder=0x7f020021;
+        public static final int edit_menu_all_apps_faded=0x7f020022;
+        public static final int edit_menu_circle=0x7f020023;
+        public static final int edit_menu_circle_faded=0x7f020024;
+        public static final int edit_menu_icon_remove=0x7f020025;
+        public static final int edit_menu_list_background=0x7f020026;
+        public static final int edit_menu_list_separator=0x7f020027;
+        public static final int edit_menu_list_shadow_bottom=0x7f020028;
+        public static final int edit_menu_list_shadow_top=0x7f020029;
+        public static final int edit_menu_separator=0x7f02002a;
+        public static final int edit_text=0x7f02002b;
+        public static final int fairphone_fav_menu_background=0x7f02002c;
+        public static final int flying_icon_bg=0x7f02002d;
+        public static final int flying_icon_bg_pressed=0x7f02002e;
+        public static final int focusable_view_bg=0x7f02002f;
+        public static final int focused_bg=0x7f020030;
+        public static final int fp_edit_favs_remove_red_bg=0x7f020031;
+        public static final int fp_fav_background=0x7f020032;
+        public static final int fp_fav_icon_ring=0x7f020033;
+        public static final int fp_gaaps_alert_button=0x7f020034;
+        public static final int fp_gapps_alert_background=0x7f020035;
+        public static final int fp_gapps_installer_icon=0x7f020036;
+        public static final int fp_gapps_progress=0x7f020037;
+        public static final int fp_gapps_widget_install=0x7f020038;
+        public static final int fp_gapps_widget_uninstall=0x7f020039;
+        public static final int fp_oobe_background=0x7f02003a;
+        public static final int fp_wallpaper_company=0x7f02003b;
+        public static final int fp_wallpaper_company_small=0x7f02003c;
+        public static final int fp_wallpaper_crystal_1=0x7f02003d;
+        public static final int fp_wallpaper_crystal_1_blue=0x7f02003e;
+        public static final int fp_wallpaper_crystal_1_blue_small=0x7f02003f;
+        public static final int fp_wallpaper_crystal_1_pink=0x7f020040;
+        public static final int fp_wallpaper_crystal_1_pink_small=0x7f020041;
+        public static final int fp_wallpaper_crystal_1_small=0x7f020042;
+        public static final int fp_wallpaper_crystal_2=0x7f020043;
+        public static final int fp_wallpaper_crystal_2_small=0x7f020044;
+        public static final int fp_wallpaper_crystal_3=0x7f020045;
+        public static final int fp_wallpaper_crystal_3_small=0x7f020046;
+        public static final int fp_wallpaper_crystal_4=0x7f020047;
+        public static final int fp_wallpaper_crystal_4_blue=0x7f020048;
+        public static final int fp_wallpaper_crystal_4_blue_small=0x7f020049;
+        public static final int fp_wallpaper_crystal_4_pink=0x7f02004a;
+        public static final int fp_wallpaper_crystal_4_pink_small=0x7f02004b;
+        public static final int fp_wallpaper_crystal_4_small=0x7f02004c;
+        public static final int fp_wallpaper_crystal_5=0x7f02004d;
+        public static final int fp_wallpaper_crystal_5_blue=0x7f02004e;
+        public static final int fp_wallpaper_crystal_5_blue_small=0x7f02004f;
+        public static final int fp_wallpaper_crystal_5_pink=0x7f020050;
+        public static final int fp_wallpaper_crystal_5_pink_small=0x7f020051;
+        public static final int fp_wallpaper_crystal_5_small=0x7f020052;
+        public static final int fp_wallpaper_crystal_6=0x7f020053;
+        public static final int fp_wallpaper_crystal_6_small=0x7f020054;
+        public static final int fp_wallpaper_default=0x7f020055;
+        public static final int fp_wallpaper_default_small=0x7f020056;
+        public static final int fp_wallpaper_mine_5_blue=0x7f020057;
+        public static final int fp_wallpaper_mine_5_blue_small=0x7f020058;
+        public static final int fp_wallpaper_sun_1=0x7f020059;
+        public static final int fp_wallpaper_sun_1_pink=0x7f02005a;
+        public static final int fp_wallpaper_sun_1_pink_small=0x7f02005b;
+        public static final int fp_wallpaper_sun_1_small=0x7f02005c;
+        public static final int fp_wallpaper_sun_2=0x7f02005d;
+        public static final int fp_wallpaper_sun_2_small=0x7f02005e;
+        public static final int fp_wallpaper_sun_3=0x7f02005f;
+        public static final int fp_wallpaper_sun_3_small=0x7f020060;
+        public static final int fp_wallpaper_sun_4=0x7f020061;
+        public static final int fp_wallpaper_sun_4_pink=0x7f020062;
+        public static final int fp_wallpaper_sun_4_pink_small=0x7f020063;
+        public static final int fp_wallpaper_sun_4_small=0x7f020064;
+        public static final int fp_wallpaper_sun_5=0x7f020065;
+        public static final int fp_wallpaper_sun_5_small=0x7f020066;
+        public static final int grid_focused=0x7f020067;
+        public static final int grid_pressed=0x7f020068;
+        public static final int grid_selected=0x7f020069;
+        public static final int hand=0x7f02006a;
+        public static final int home_press=0x7f02006b;
+        public static final int homescreen_blue_normal_holo=0x7f02006c;
+        public static final int homescreen_blue_strong_holo=0x7f02006d;
+        public static final int hotseat_scrubber_holo=0x7f02006e;
+        public static final int hotseat_track_holo=0x7f02006f;
+        public static final int ic_allapps=0x7f020070;
+        public static final int ic_allapps_pressed=0x7f020071;
+        public static final int ic_home_all_apps_holo_dark=0x7f020072;
+        public static final int ic_home_search_normal_holo=0x7f020073;
+        public static final int ic_home_voice_search_holo=0x7f020074;
+        public static final int ic_launcher_clear_active_holo=0x7f020075;
+        public static final int ic_launcher_clear_normal_holo=0x7f020076;
+        public static final int ic_launcher_info_active_holo=0x7f020077;
+        public static final int ic_launcher_info_normal_holo=0x7f020078;
+        public static final int ic_launcher_market_holo=0x7f020079;
+        public static final int ic_launcher_trashcan_active_holo=0x7f02007a;
+        public static final int ic_launcher_trashcan_normal_holo=0x7f02007b;
+        public static final int icon_all_apps=0x7f02007c;
+        public static final int icon_clean=0x7f02007d;
+        public static final int icon_edit=0x7f02007e;
+        public static final int info_target_selector=0x7f02007f;
+        public static final int oobe_app_icon=0x7f020080;
+        public static final int oobe_app_icon_small=0x7f020081;
+        public static final int oobe_arrow_big=0x7f020082;
+        public static final int oobe_delete_higlight=0x7f020083;
+        public static final int oobe_delete_x=0x7f020084;
+        public static final int oobe_edit_all_apps=0x7f020085;
+        public static final int oobe_edit_drag_intro=0x7f020086;
+        public static final int oobe_edit_favourite_apps=0x7f020087;
+        public static final int oobe_fairphone_logo=0x7f020088;
+        public static final int oobe_hand=0x7f020089;
+        public static final int oobe_hand_shadow=0x7f02008a;
+        public static final int oobe_icon_all_apps=0x7f02008b;
+        public static final int oobe_icon_select=0x7f02008c;
+        public static final int oobe_language_button=0x7f02008d;
+        public static final int oobe_language_button_press=0x7f02008e;
+        public static final int oobe_language_button_up=0x7f02008f;
+        public static final int oobe_menu=0x7f020090;
+        public static final int oobe_selection_big=0x7f020091;
+        public static final int oobe_wifi_button=0x7f020092;
+        public static final int oobe_wifi_button_press=0x7f020093;
+        public static final int oobe_wifi_button_up=0x7f020094;
+        public static final int overscroll_glow_left=0x7f020095;
+        public static final int overscroll_glow_right=0x7f020096;
+        public static final int page_hover_left_holo=0x7f020097;
+        public static final int page_hover_right_holo=0x7f020098;
+        public static final int paged_view_indicator=0x7f020099;
+        public static final int portal_container_holo=0x7f02009a;
+        public static final int portal_ring_inner_holo=0x7f02009b;
+        public static final int portal_ring_inner_nolip_holo=0x7f02009c;
+        public static final int portal_ring_outer_holo=0x7f02009d;
+        public static final int portal_ring_rest=0x7f02009e;
+        public static final int remove_target_selector=0x7f02009f;
+        public static final int search_frame=0x7f0200a0;
+        public static final int swipe_menu_shadow_bottom=0x7f0200a1;
+        public static final int swipe_menu_shadow_top=0x7f0200a2;
+        public static final int tab_selected_focused_holo=0x7f0200a3;
+        public static final int tab_selected_holo=0x7f0200a4;
+        public static final int tab_selected_pressed_focused_holo=0x7f0200a5;
+        public static final int tab_selected_pressed_holo=0x7f0200a6;
+        public static final int tab_unselected_focused_holo=0x7f0200a7;
+        public static final int tab_unselected_holo=0x7f0200a8;
+        public static final int tab_unselected_pressed_focused_holo=0x7f0200a9;
+        public static final int tab_unselected_pressed_holo=0x7f0200aa;
+        public static final int tab_widget_indicator_selector=0x7f0200ab;
+        public static final int uninstall_target_selector=0x7f0200ac;
+        public static final int wallpaper_gallery_background=0x7f0200ad;
+        public static final int wallpaper_gallery_item=0x7f0200ae;
+        public static final int widget_container_holo=0x7f0200af;
+        public static final int widget_preview_tile=0x7f0200b0;
+        public static final int widget_resize_frame_holo=0x7f0200b1;
+        public static final int widget_resize_handle_bottom=0x7f0200b2;
+        public static final int widget_resize_handle_left=0x7f0200b3;
+        public static final int widget_resize_handle_right=0x7f0200b4;
+        public static final int widget_resize_handle_top=0x7f0200b5;
+        public static final int workspace_bg=0x7f0200b6;
+    }
+    public static final class id {
+        public static final int allAppsGridView=0x7f090027;
+        public static final int allAppsGroup=0x7f090026;
+        public static final int allAppsTextView=0x7f090028;
+        public static final int all_apps_cling=0x7f09000c;
+        public static final int all_apps_cling_add_item=0x7f090003;
+        public static final int all_apps_cling_title=0x7f090002;
+        public static final int animation_buffer=0x7f09000a;
+        public static final int appMenuContainer=0x7f090081;
+        public static final int appPicture=0x7f090044;
+        public static final int appSwitcher=0x7f09001c;
+        public static final int appSwitcherMain=0x7f090017;
+        public static final int appText=0x7f090045;
+        public static final int application_icon=0x7f090005;
+        public static final int apps_customize_content=0x7f090006;
+        public static final int apps_customize_pane=0x7f090080;
+        public static final int apps_customize_pane_content=0x7f090009;
+        public static final int apps_customize_progress_bar=0x7f09000d;
+        public static final int backButton=0x7f090065;
+        public static final int buttonLauncher=0x7f090019;
+        public static final int buttonReset=0x7f09001a;
+        public static final int buttonResetDisabled=0x7f09001b;
+        public static final int cell1=0x7f090078;
+        public static final int cell2=0x7f090079;
+        public static final int cell3=0x7f09007a;
+        public static final int cell4=0x7f09007b;
+        public static final int cell5=0x7f09007c;
+        public static final int cling_dismiss=0x7f090004;
+        public static final int currentVersionTitleSeparator=0x7f090085;
+        public static final int delete_target_text=0x7f090011;
+        public static final int disclaimerCancelButton=0x7f09004b;
+        public static final int disclaimerOkButton=0x7f09004c;
+        public static final int drag_layer=0x7f090076;
+        public static final int drag_target_bar=0x7f090086;
+        public static final int editFavAddAnimationView=0x7f09008e;
+        public static final int editFavMoveAnimationView=0x7f09008f;
+        public static final int editFavRemoveAnimationView=0x7f090090;
+        public static final int editGroup=0x7f09003f;
+        public static final int editMenuMain=0x7f090024;
+        public static final int editRing=0x7f090041;
+        public static final int editText=0x7f090040;
+        public static final int failedDownloadCancelButton=0x7f09004e;
+        public static final int failedDownloadOkButton=0x7f09004f;
+        public static final int favouriteGroup1=0x7f090029;
+        public static final int favouriteGroup2=0x7f09002c;
+        public static final int favouriteGroup3=0x7f09002f;
+        public static final int favouriteGroup4=0x7f090032;
+        public static final int favouriteRing1=0x7f09002a;
+        public static final int favouriteRing2=0x7f09002d;
+        public static final int favouriteRing3=0x7f090030;
+        public static final int favouriteRing4=0x7f090033;
+        public static final int favouriteText1=0x7f09002b;
+        public static final int favouriteText2=0x7f09002e;
+        public static final int favouriteText3=0x7f090031;
+        public static final int favouriteText4=0x7f090034;
+        public static final int folder_cling=0x7f09007f;
+        public static final int folder_cling_create_folder=0x7f090014;
+        public static final int folder_cling_title=0x7f090013;
+        public static final int folder_content=0x7f090092;
+        public static final int folder_icon_name=0x7f090016;
+        public static final int folder_name=0x7f090088;
+        public static final int fp_oobe_video=0x7f090067;
+        public static final int fp_oobe_video_skip_button=0x7f090068;
+        public static final int gallery=0x7f090093;
+        public static final int googleAppsInstaller=0x7f090097;
+        public static final int googleAppsIntallerMain=0x7f090046;
+        public static final int header=0x7f090018;
+        public static final int horizontal=0x7f090001;
+        public static final int icon1=0x7f090038;
+        public static final int icon2=0x7f09003b;
+        public static final int icon3=0x7f09003c;
+        public static final int icon4=0x7f09003d;
+        public static final int icon5=0x7f09003e;
+        public static final int iconPressRing=0x7f09003a;
+        public static final int iconSelectedName=0x7f090039;
+        public static final int info_target_text=0x7f090012;
+        public static final int installButton=0x7f090048;
+        public static final int installGroup=0x7f090047;
+        public static final int installText=0x7f090049;
+        public static final int label=0x7f090087;
+        public static final int lastUsedApps=0x7f09001f;
+        public static final int lastUsedAppsOOBETitle=0x7f09001d;
+        public static final int lastUsedAppsTitle=0x7f09001e;
+        public static final int launcher=0x7f090075;
+        public static final int layout=0x7f090074;
+        public static final int mainTitle=0x7f090025;
+        public static final int market_button=0x7f090008;
+        public static final int menuBackground=0x7f090035;
+        public static final int menuContent=0x7f090037;
+        public static final int menuRoot=0x7f090036;
+        public static final int mostUsedApps=0x7f090023;
+        public static final int mostUsedAppsOOBEDescription=0x7f090021;
+        public static final int mostUsedAppsOOBETitle=0x7f090020;
+        public static final int mostUsedAppsTitle=0x7f090022;
+        public static final int mostUsedButton=0x7f09005f;
+        public static final int mostUsedRow=0x7f09005e;
+        public static final int nextButton=0x7f090064;
+        public static final int oobeTextGroup1=0x7f090069;
+        public static final int oobeTextGroup2=0x7f09006b;
+        public static final int oobeTextGroup3=0x7f09006d;
+        public static final int oobeTextGroup4=0x7f09006e;
+        public static final int oobeTextGroup5=0x7f09006f;
+        public static final int oobeTextGroup6=0x7f090070;
+        public static final int oobeTextGroup7=0x7f090071;
+        public static final int oobeTextGroup8=0x7f090072;
+        public static final int oobeTextGroup9=0x7f090073;
+        public static final int oobeVideoViewGroup=0x7f090066;
+        public static final int oobe_background=0x7f090060;
+        public static final int openAppAnimationView=0x7f090091;
+        public static final int paged_view_indicator=0x7f09000b;
+        public static final int permissionsDialogTitle=0x7f090057;
+        public static final int permissionsOkButton=0x7f090058;
+        public static final int popupDisclaimerGroup=0x7f09004a;
+        public static final int popupFailedDownloadGroup=0x7f09004d;
+        public static final int popupPermissionsGroup=0x7f090056;
+        public static final int popupProgressGroup=0x7f090050;
+        public static final int popupRebootGroup=0x7f090053;
+        public static final int preview_background=0x7f090015;
+        public static final int progressBar=0x7f090052;
+        public static final int progressDialogTitle=0x7f090051;
+        public static final int qsb_bar=0x7f09007d;
+        public static final int rebootDialogTitle=0x7f090054;
+        public static final int rebootOkButton=0x7f090055;
+        public static final int recentButton=0x7f09005d;
+        public static final int search_button=0x7f090089;
+        public static final int search_button_container=0x7f09008a;
+        public static final int selectLanguageButton=0x7f09006a;
+        public static final int set=0x7f090094;
+        public static final int setupWifiButton=0x7f09006c;
+        public static final int skipButton=0x7f090062;
+        public static final int startButton=0x7f090063;
+        public static final int swipeAnimationView=0x7f09008d;
+        public static final int swipeMenuBottomShadow=0x7f090043;
+        public static final int swipeMenuTopShadow=0x7f090042;
+        public static final int systemUpdater=0x7f090082;
+        public static final int systemUpdaterLla=0x7f090083;
+        public static final int tabs_container=0x7f090007;
+        public static final int titleText=0x7f090084;
+        public static final int tutorialAnimationViewContainer=0x7f090061;
+        public static final int uninstallButton=0x7f09005a;
+        public static final int uninstallGroup=0x7f090059;
+        public static final int uninstallText=0x7f09005c;
+        public static final int uninstallTitle=0x7f09005b;
+        public static final int vertical=0x7f090000;
+        public static final int voice_button=0x7f09008c;
+        public static final int voice_button_container=0x7f09008b;
+        public static final int wallpaper_chooser_fragment=0x7f090095;
+        public static final int wallpaper_image=0x7f090096;
+        public static final int widget_dims=0x7f090010;
+        public static final int widget_name=0x7f09000f;
+        public static final int widget_preview=0x7f09000e;
+        public static final int workspace=0x7f090077;
+        public static final int workspace_cling=0x7f09007e;
+    }
+    public static final class integer {
+        public static final int apps_customize_cling_focused_x=0x7f0c0028;
+        public static final int apps_customize_cling_focused_y=0x7f0c0029;
+        /**  AllApps/Customize/AppsCustomize 
+         */
+        public static final int apps_customize_maxCellCountX=0x7f0c0024;
+        public static final int apps_customize_maxCellCountY=0x7f0c0025;
+        public static final int apps_customize_widget_cell_count_x=0x7f0c0026;
+        public static final int apps_customize_widget_cell_count_y=0x7f0c0027;
+        public static final int cell_count_x=0x7f0c001d;
+        public static final int cell_count_y=0x7f0c001e;
+        /**  Batch loading for loading in LauncherModel 
+         */
+        public static final int config_allAppsBatchLoadDelay=0x7f0c000e;
+        public static final int config_allAppsBatchSize=0x7f0c000f;
+        /**  The slope, in percent, of the drag movement needed to drag an item out of
+         AppsCustomize (y / x * 100%)  
+         */
+        public static final int config_appsCustomizeDragSlopeThreshold=0x7f0c000d;
+        public static final int config_appsCustomizeFadeInTime=0x7f0c0007;
+        public static final int config_appsCustomizeFadeOutTime=0x7f0c0008;
+        /**  AllApps/Customize/AppsCustomize 
+ The alpha of the AppsCustomize bg in spring loaded mode 
+         */
+        public static final int config_appsCustomizeSpringLoadedBgAlpha=0x7f0c0001;
+        public static final int config_appsCustomizeWorkspaceAnimationStagger=0x7f0c000a;
+        public static final int config_appsCustomizeWorkspaceShrinkTime=0x7f0c0009;
+        /**  Fade/zoom in/out duration & scale in the AllApps transition.
+         Note: This should be less than the workspaceShrinkTime as they happen together. 
+         */
+        public static final int config_appsCustomizeZoomInTime=0x7f0c0004;
+        public static final int config_appsCustomizeZoomOutTime=0x7f0c0005;
+        public static final int config_appsCustomizeZoomScaleFactor=0x7f0c0006;
+        /**  Camera distance for the overscroll effect 
+         */
+        public static final int config_cameraDistance=0x7f0c0019;
+        /**  Properties controlling the workspace fade-out during dragging 
+         */
+        public static final int config_dragFadeOutAlpha=0x7f0c0017;
+        public static final int config_dragFadeOutDuration=0x7f0c0018;
+        /**  The duration (in ms) of the fade animation on the object outlines, used when
+         we are dragging objects around on the home screen. 
+         */
+        public static final int config_dragOutlineFadeTime=0x7f0c0011;
+        /**  The alpha value at which to show the most recent drop visualization outline. 
+         */
+        public static final int config_dragOutlineMaxAlpha=0x7f0c0012;
+        /**  The distance at which the animation should take the max duration 
+         */
+        public static final int config_dropAnimMaxDist=0x7f0c0016;
+        public static final int config_dropAnimMaxDuration=0x7f0c0014;
+        /**  Parameters controlling the animation for when an item is dropped on the home screen,
+         and it animates from its old position to the new one. 
+         */
+        public static final int config_dropAnimMinDuration=0x7f0c0013;
+        /**  The transition duration for the background of the drop targets 
+         */
+        public static final int config_dropTargetBgTransitionDuration=0x7f0c0010;
+        public static final int config_edgeMenuEditButtonTime=0x7f0c0023;
+        public static final int config_edgeMenuQuickTime=0x7f0c0022;
+        /**  DragController 
+         */
+        public static final int config_flingToDeleteMinVelocity=0x7f0c0000;
+        /**  The duration of the UserFolder opening and closing animation 
+         */
+        public static final int config_folderAnimDuration=0x7f0c0015;
+        /**  Tab transition animation duration 
+         */
+        public static final int config_tabTransitionDuration=0x7f0c000c;
+        public static final int config_workspaceAppsCustomizeAnimationStagger=0x7f0c000b;
+        /**  Out of 100, the percent to shrink the workspace during spring loaded mode. 
+         */
+        public static final int config_workspaceSpringLoadShrinkPercentage=0x7f0c0003;
+        public static final int config_workspaceUnshrinkTime=0x7f0c0002;
+        /**  Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y
+         >= folder_max_num_items. When these are set to -1, they are automatically determined. 
+ Folder max bounds and max number of items.
+         Note: folder_max_count_x * folder_max_count_y >= folder_max_num_items. 
+         */
+        public static final int folder_max_count_x=0x7f0c001a;
+        public static final int folder_max_count_y=0x7f0c001b;
+        public static final int folder_max_num_items=0x7f0c001c;
+        public static final int hotseat_all_apps_index=0x7f0c0020;
+        public static final int hotseat_cell_count=0x7f0c001f;
+        /**  must be between 0 and 100 
+         */
+        public static final int hotseat_item_scale_percentage=0x7f0c0021;
+    }
+    public static final class layout {
+        public static final int add_list_item=0x7f040000;
+        public static final int all_apps_cling=0x7f040001;
+        public static final int application=0x7f040002;
+        public static final int apps_customize_application=0x7f040003;
+        public static final int apps_customize_pane=0x7f040004;
+        public static final int apps_customize_progressbar=0x7f040005;
+        public static final int apps_customize_widget=0x7f040006;
+        public static final int appwidget_error=0x7f040007;
+        public static final int custom_workspace_cling=0x7f040008;
+        public static final int drop_target_bar=0x7f040009;
+        public static final int folder_cling=0x7f04000a;
+        public static final int folder_icon=0x7f04000b;
+        public static final int fp_app_switcher=0x7f04000c;
+        public static final int fp_edit_favorites=0x7f04000d;
+        public static final int fp_fav_apps_layout=0x7f04000e;
+        public static final int fp_favorites_all_apps_list_item=0x7f04000f;
+        public static final int fp_google_apps_installer_widget=0x7f040010;
+        public static final int fp_last_used_item=0x7f040011;
+        public static final int fp_most_used_item=0x7f040012;
+        public static final int fp_oobe_activity=0x7f040013;
+        public static final int fp_oobe_texts=0x7f040014;
+        public static final int hotseat=0x7f040015;
+        public static final int launcher=0x7f040016;
+        public static final int market_button=0x7f040017;
+        public static final int qsb_bar=0x7f040018;
+        public static final int rename_folder=0x7f040019;
+        public static final int scroll_indicator=0x7f04001a;
+        public static final int search_bar=0x7f04001b;
+        public static final int tab_widget_indicator=0x7f04001c;
+        public static final int tutorial_edge_swipe_layout=0x7f04001d;
+        public static final int tutorial_edit_fav_add_layout=0x7f04001e;
+        public static final int tutorial_edit_fav_move_layout=0x7f04001f;
+        public static final int tutorial_edit_fav_remove_layout=0x7f040020;
+        public static final int tutorial_open_app_layout=0x7f040021;
+        public static final int user_folder=0x7f040022;
+        public static final int wallpaper_chooser=0x7f040023;
+        public static final int wallpaper_chooser_base=0x7f040024;
+        public static final int wallpaper_item=0x7f040025;
+        public static final int workspace_cling=0x7f040026;
+        public static final int workspace_divider=0x7f040027;
+        public static final int workspace_screen=0x7f040028;
+    }
+    public static final class mipmap {
+        public static final int ic_launcher_application=0x7f030000;
+        public static final int ic_launcher_wallpaper=0x7f030001;
+        public static final int icon_launcher_home=0x7f030002;
+    }
+    public static final class raw {
+        public static final int fp_buy_a_phone_start_a_movement=0x7f070000;
+        public static final int public_key=0x7f070001;
+    }
+    public static final class string {
+        /**  Accessibility: AllApps button 
+         */
+        public static final int accessibility_all_apps_button=0x7f0d0037;
+        /**  Accessibility: Delete button 
+         */
+        public static final int accessibility_delete_button=0x7f0d0038;
+        /**  Accessibility: Search button 
+         */
+        public static final int accessibility_search_button=0x7f0d0035;
+        /**  Accessibility: Voice Search button 
+         */
+        public static final int accessibility_voice_search_button=0x7f0d0036;
+        /**  Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none] 
+         */
+        public static final int activity_not_found=0x7f0d0010;
+        /**  All applications label 
+         */
+        public static final int all_apps_button_label=0x7f0d002e;
+        /**  The description of how to pick up and add an item to the workspace [CHAR_LIMIT=none] 
+         */
+        public static final int all_apps_cling_add_item=0x7f0d005d;
+        /**  The title text for the All Apps cling [CHAR_LIMIT=none] 
+         */
+        public static final int all_apps_cling_title=0x7f0d005c;
+        /** 
+         Label for button in all applications label to go back home (to the workspace / desktop)
+         for accessibilty (spoken when the button gets focus).
+    
+         */
+        public static final int all_apps_home_button_label=0x7f0d002f;
+        /**  AppSwitcher Widget  name 
+         */
+        public static final int app_switcher_dialog_name=0x7f0d0009;
+        /**  AppSwitcher Widget  name 
+         */
+        public static final int app_switcher_name=0x7f0d0008;
+        public static final int app_switcher_reset_message=0x7f0d0077;
+        /**  Application name 
+         */
+        public static final int application_name=0x7f0d0007;
+        /**  The format string for AppsCustomize Apps page scroll text [CHAR_LIMIT=none] 
+         */
+        public static final int apps_customize_apps_scroll_format=0x7f0d0057;
+        /**  The format string for AppsCustomize Apps page scroll text [CHAR_LIMIT=none] 
+         */
+        public static final int apps_customize_widgets_scroll_format=0x7f0d0058;
+        /**  Appears in the CAB when an app is selected in All Apps or Customize mode. [CHAR_LIMIT=50] 
+         */
+        public static final int cab_app_selection_text=0x7f0d0044;
+        /**  Appears in the CAB when a folder is selected in Customize mode. [CHAR_LIMIT=50] 
+         */
+        public static final int cab_folder_selection_text=0x7f0d0046;
+        /** 
+         Describes the button for getting details/info about currently selected application.
+         Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none]
+    
+         */
+        public static final int cab_menu_app_info=0x7f0d0043;
+        /** 
+         Describes the button for uninstalling the currently selected application.
+         Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none]
+    
+         */
+        public static final int cab_menu_delete_app=0x7f0d0042;
+        /**  Appears in the CAB when a shortcut is selected in Customize mode. [CHAR_LIMIT=50] 
+         */
+        public static final int cab_shortcut_selection_text=0x7f0d0047;
+        /**  Appears in the CAB when a widget is selected in Customize mode. [CHAR_LIMIT=50] 
+         */
+        public static final int cab_widget_selection_text=0x7f0d0045;
+        /**  Buttons in Rename folder dialog box 
+         */
+        public static final int cancel_action=0x7f0d001b;
+        /**  Title of dialog that appears after user selects Wallpaper from menu 
+         */
+        public static final int chooser_wallpaper=0x7f0d000d;
+        /**  The text on the button to dismiss a cling [CHAR_LIMIT=none] 
+         */
+        public static final int cling_dismiss=0x7f0d0061;
+        /**  Error message when user has filled all their home screens 
+         */
+        public static final int completely_out_of_space=0x7f0d0025;
+        /**  Dummy string [CHAR_LIMIT=60] 
+         */
+        public static final int custom_workspace_cling_description_1=0x7f0d006a;
+        /**  Dummy string [CHAR_LIMIT=60] 
+         */
+        public static final int custom_workspace_cling_description_2=0x7f0d006c;
+        /**  Strings used in device overlays 
+ Clings 
+ Dummy string [CHAR_LIMIT=40] 
+         */
+        public static final int custom_workspace_cling_title_1=0x7f0d0069;
+        /**  Dummy string [CHAR_LIMIT=40] 
+         */
+        public static final int custom_workspace_cling_title_2=0x7f0d006b;
+        /**  The format string for default page scroll text [CHAR_LIMIT=none] 
+         */
+        public static final int default_scroll_format=0x7f0d0055;
+        /**  Label for delete drop target. [CHAR_LIMIT=30] 
+         */
+        public static final int delete_target_label=0x7f0d0032;
+        /**  Label for uninstall drop target. [CHAR_LIMIT=30] 
+         */
+        public static final int delete_target_uninstall_label=0x7f0d0033;
+        /** 
+         Label for trash icon in All Apps. The icon/widget will become completely unavailable on the
+         device. [CHAR_LIMIT=30]
+    
+         */
+        public static final int delete_zone_label_all_apps=0x7f0d0031;
+        /** 
+         Label for trash icon in All Apps, when an updated system app is selected. The update will
+         be uninstalled. [CHAR_LIMIT=30]
+    
+         */
+        public static final int delete_zone_label_all_apps_system_app=0x7f0d0039;
+        /** 
+         Label for trash icon on workspace. Meant to communicate the idea of removing the
+         icon/widget from the home screen, but not permanently. [CHAR_LIMIT=30]
+    
+         */
+        public static final int delete_zone_label_workspace=0x7f0d0030;
+        public static final int drag_here_to_add=0x7f0d007b;
+        public static final int drag_here_to_remove=0x7f0d007c;
+        /**  Title of the Android Dreams (screensaver) module 
+         */
+        public static final int dream_name=0x7f0d0052;
+        /**  Error message on dummy custom cling layout [DO NOT TRANSLATE] 
+         */
+        public static final int dummy_custom_cling_error_message=0x7f0d0062;
+        /**  Edge menu 
+         */
+        public static final int edge_swipe_default_apps=0x7f0d0000;
+        public static final int edit=0x7f0d0079;
+        /**  Settings 
+ Settings 
+ Settings 
+ Settings 
+ Settings 
+ Settings 
+         */
+        public static final int energy_mood=0x7f0d007d;
+        public static final int energy_mood_summary=0x7f0d007e;
+        /** 
+         External-drop widget error string.  This is the error that is shown
+         when you drag and item into the homescreen and it is unable to fit,
+         or an error is encountered. [CHAR_LIMIT=50]
+    
+         */
+        public static final int external_drop_widget_error=0x7f0d0016;
+        /**  External-drop widget pick label format string [CHAR_LIMIT=25] 
+         */
+        public static final int external_drop_widget_pick_format=0x7f0d0015;
+        /** 
+         External-drop widget pick title.  This is shown as the title of the
+         dialog which allows you to pick which widgets to handle a particular
+         drop if there are multiple choices. [CHAR_LIMIT=35]
+    
+         */
+        public static final int external_drop_widget_pick_title=0x7f0d0017;
+        public static final int favourite_apps=0x7f0d007a;
+        /**  The description of how to create a folder [CHAR_LIMIT=none] 
+         */
+        public static final int folder_cling_create_folder=0x7f0d0060;
+        /**  The description of how to move an app [CHAR_LIMIT=none] 
+         */
+        public static final int folder_cling_move_item=0x7f0d005f;
+        /**  The title text for the Folder cling [CHAR_LIMIT=none] 
+         */
+        public static final int folder_cling_title=0x7f0d005e;
+        /**  Indication that folder closed 
+         */
+        public static final int folder_closed=0x7f0d0066;
+        /**  Default folder title 
+         */
+        public static final int folder_hint_text=0x7f0d0053;
+        /**  Default folder name 
+         */
+        public static final int folder_name=0x7f0d000c;
+        /**  Folder name format 
+         */
+        public static final int folder_name_format=0x7f0d0068;
+        /**  Folder accessibility 
+ The format string for when a folder is opened, speaks the dimensions 
+         */
+        public static final int folder_opened=0x7f0d0063;
+        /**  Folder renamed format 
+         */
+        public static final int folder_renamed=0x7f0d0067;
+        /**  Instruction that clicking outside will close folder 
+         */
+        public static final int folder_tap_to_close=0x7f0d0064;
+        /**  Instruction that clicking outside will commit folder rename 
+         */
+        public static final int folder_tap_to_rename=0x7f0d0065;
+        /**  Text to show user in place of a gadget when we can't display it properly 
+         */
+        public static final int gadget_error_text=0x7f0d0050;
+        public static final int gapps_installer_cfg=0x7f0d0004;
+        /** <string name="gapps_installer_download_url">http://www.kwamecorp.com/dev/fairphonegapps.zip</string>
+         */
+        public static final int gapps_installer_config_file=0x7f0d0002;
+        /**  Google Apps Instaler 
+         */
+        public static final int gapps_installer_download_url=0x7f0d0001;
+        public static final int gapps_installer_filename=0x7f0d0006;
+        public static final int gapps_installer_sig=0x7f0d0005;
+        public static final int gapps_installer_zip=0x7f0d0003;
+        public static final int google_apps_connection_description=0x7f0d00bc;
+        public static final int google_apps_connection_title=0x7f0d00bb;
+        public static final int google_apps_denied_permissions_description=0x7f0d00ac;
+        public static final int google_apps_denied_permissions_title=0x7f0d00ab;
+        public static final int google_apps_disclaimer_agree=0x7f0d00aa;
+        public static final int google_apps_disclaimer_description=0x7f0d00a9;
+        public static final int google_apps_disclaimer_title=0x7f0d00a8;
+        public static final int google_apps_download_error=0x7f0d00ba;
+        public static final int google_apps_download_title=0x7f0d00af;
+        public static final int google_apps_failed_download_description=0x7f0d00b9;
+        public static final int google_apps_failed_download_title=0x7f0d00b8;
+        public static final int google_apps_initial_title=0x7f0d00a7;
+        public static final int google_apps_install_title=0x7f0d00b1;
+        /**  Google Apps Install Widget 
+ Google Apps Install Widget 
+ Google Apps Install Widget 
+ Google Apps Install Widget 
+ Google Apps Install Widget 
+ Google Apps Install Widget 
+         */
+        public static final int google_apps_installer_name=0x7f0d00a6;
+        public static final int google_apps_permissions_description=0x7f0d00b3;
+        public static final int google_apps_permissions_title=0x7f0d00b4;
+        public static final int google_apps_reboot_description=0x7f0d00b5;
+        public static final int google_apps_reboot_failed_description=0x7f0d00ae;
+        public static final int google_apps_reboot_failed_title=0x7f0d00ad;
+        public static final int google_apps_reboot_title=0x7f0d00b2;
+        public static final int google_apps_uninstall_description=0x7f0d00b7;
+        public static final int google_apps_uninstall_title=0x7f0d00b6;
+        public static final int google_apps_unzip_title=0x7f0d00b0;
+        /**  Options in "Add to Home" dialog box; Title of the group containing the list of all apps 
+         */
+        public static final int group_applications=0x7f0d001d;
+        /** 
+Options in "Add to Home" dialog box; Title of the group containing the list of all shortcut
+s
+    
+         */
+        public static final int group_shortcuts=0x7f0d001e;
+        /**  Options in "Add to Home" dialog box; Title of the group containing the list of apps that can set the wallpaper 
+         */
+        public static final int group_wallpapers=0x7f0d0020;
+        /**  Options in "Add to Home" dialog box; Title of the group containing the list of all widgets/gadgets 
+         */
+        public static final int group_widgets=0x7f0d001f;
+        /**  URL pointing to help text. If empty, no link to help will be created [DO NOT TRANSLATE] 
+         */
+        public static final int help_url=0x7f0d0041;
+        /**  Accessibility-facing application name 
+         */
+        public static final int home=0x7f0d000a;
+        /**  Error message when user has filled the hotseat 
+         */
+        public static final int hotseat_out_of_space=0x7f0d0027;
+        /**  Default image description 
+         */
+        public static final int image_desc=0x7f0d006d;
+        /**  Label for the info icon. [CHAR_LIMIT=30] 
+         */
+        public static final int info_target_label=0x7f0d0034;
+        /**  Error message when user tries to drop an invalid item on the hotseat 
+         */
+        public static final int invalid_hotseat_item=0x7f0d0028;
+        public static final int last_used=0x7f0d0070;
+        public static final int last_used_apps=0x7f0d006f;
+        public static final int last_used_oobe=0x7f0d0074;
+        /**  AppsCustomize pane 
+ Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] 
+         */
+        public static final int long_press_widget_to_add=0x7f0d0012;
+        /** 
+         Market button text.  The market button text is removed in Launcher.java 
+         in the Phone UI. [CHAR LIMIT=32]
+    
+         */
+        public static final int market=0x7f0d0013;
+        /**  Verb, menu item used to add an item on the desktop 
+         */
+        public static final int menu_add=0x7f0d003a;
+        public static final int menu_change_edge_swipe=0x7f0d0023;
+        public static final int menu_change_edge_swipe_alternative=0x7f0d0081;
+        public static final int menu_change_edge_swipe_change_to=0x7f0d007f;
+        public static final int menu_change_edge_swipe_normal=0x7f0d0080;
+        /**  TODO - FP edit favorites 
+         */
+        public static final int menu_edit_favorites=0x7f0d0021;
+        /**  Noun, menu item used to show help. [CHAR_LIMIT=none] 
+         */
+        public static final int menu_help=0x7f0d0040;
+        public static final int menu_home_settings=0x7f0d0024;
+        /**  Title of dialog box 
+         */
+        public static final int menu_item_add_item=0x7f0d001c;
+        /**  Menu item used to manage installed applications 
+         */
+        public static final int menu_manage_apps=0x7f0d003b;
+        /**  Noun, menu item used to bring down the notifications shade 
+         */
+        public static final int menu_notifications=0x7f0d003e;
+        /**  Verb, menu item used to initiate global search 
+         */
+        public static final int menu_search=0x7f0d003d;
+        /**  Noun, menu item used to show the system settings 
+         */
+        public static final int menu_settings=0x7f0d003f;
+        public static final int menu_show_OOBE=0x7f0d0022;
+        /**  Noun, menu item used to set the desktop's wallpaper 
+         */
+        public static final int menu_wallpaper=0x7f0d003c;
+        public static final int most_used=0x7f0d0072;
+        public static final int most_used_apps=0x7f0d0071;
+        public static final int most_used_oobe=0x7f0d0075;
+        public static final int no_apps_have_been_opened_yet=0x7f0d0073;
+        public static final int oobeVideoSkipButtonText=0x7f0d0082;
+        public static final int oobe_back=0x7f0d00a2;
+        public static final int oobe_done=0x7f0d00a5;
+        public static final int oobe_edge_swipe_text=0x7f0d0093;
+        public static final int oobe_edge_swipe_title=0x7f0d0092;
+        public static final int oobe_edit_drag_add_text=0x7f0d0098;
+        public static final int oobe_edit_drag_add_title=0x7f0d0097;
+        public static final int oobe_edit_drag_intro=0x7f0d0096;
+        public static final int oobe_edit_drag_remove_text=0x7f0d009a;
+        public static final int oobe_edit_drag_remove_title=0x7f0d0099;
+        public static final int oobe_edit_drag_trade_text=0x7f0d009c;
+        public static final int oobe_edit_drag_trade_title=0x7f0d009b;
+        public static final int oobe_intro_bottom=0x7f0d0091;
+        public static final int oobe_intro_top=0x7f0d0090;
+        public static final int oobe_next=0x7f0d00a4;
+        public static final int oobe_open_app_text=0x7f0d0095;
+        public static final int oobe_open_app_title=0x7f0d0094;
+        /**  OOBE Texts 
+ OOBE Texts 
+ OOBE Textos 
+ OOBE Texts 
+ OOBE Texts 
+ OOBE Texts 
+         */
+        public static final int oobe_quick_access=0x7f0d008d;
+        public static final int oobe_select_language=0x7f0d008e;
+        public static final int oobe_setup_wifi=0x7f0d008f;
+        public static final int oobe_skip=0x7f0d00a3;
+        public static final int oobe_start=0x7f0d00a1;
+        public static final int oobe_your_apps_intro=0x7f0d009d;
+        public static final int oobe_your_apps_last_ones=0x7f0d009f;
+        public static final int oobe_your_apps_learning=0x7f0d009e;
+        public static final int oobe_your_apps_start_using=0x7f0d00a0;
+        /**  Error message when user has filled a home screen 
+         */
+        public static final int out_of_space=0x7f0d0026;
+        /**  Permission description 
+         */
+        public static final int permdesc_install_shortcut=0x7f0d0049;
+        /**  Permission description 
+         */
+        public static final int permdesc_read_settings=0x7f0d004d;
+        /**  Permission description 
+         */
+        public static final int permdesc_uninstall_shortcut=0x7f0d004b;
+        /**  Permission description 
+         */
+        public static final int permdesc_write_settings=0x7f0d004f;
+        /**  Permission short label 
+         */
+        public static final int permlab_install_shortcut=0x7f0d0048;
+        /**  Permission short label 
+         */
+        public static final int permlab_read_settings=0x7f0d004c;
+        /**  Permission short label 
+         */
+        public static final int permlab_uninstall_shortcut=0x7f0d004a;
+        /**  Permission short label 
+         */
+        public static final int permlab_write_settings=0x7f0d004e;
+        /**  Option in "Select wallpaper from" dialog box 
+         */
+        public static final int pick_wallpaper=0x7f0d000f;
+        public static final int pref_edge_swipe_safe_zone=0x7f0d0085;
+        public static final int pref_edge_swipe_safe_zone_summ=0x7f0d0086;
+        public static final int pref_edge_swipe_title=0x7f0d0084;
+        public static final int pref_is_mood_changer_solid=0x7f0d008c;
+        public static final int pref_is_mood_changer_solid_summary=0x7f0d008b;
+        /**  Preferences 
+         */
+        public static final int pref_mood_changer_title=0x7f0d0083;
+        public static final int pref_show_mood_changer_on_homescreen=0x7f0d008a;
+        public static final int pref_show_mood_changer_on_homescreen_summary=0x7f0d0089;
+        public static final int pref_show_mood_changer_on_lockscreen=0x7f0d0088;
+        public static final int pref_show_mood_changer_on_lockscreen_summary=0x7f0d0087;
+        /**  Quick Access 
+ Quick Access 
+ Quick Access 
+ Quick Access 
+ Quick Access 
+ Quick Access 
+         */
+        public static final int quick_access=0x7f0d0078;
+        /**  Buttons in Rename folder dialog box 
+         */
+        public static final int rename_action=0x7f0d001a;
+        /**  Label of Folder name field in Rename folder dialog box 
+         */
+        public static final int rename_folder_label=0x7f0d0018;
+        /**  Title of dialog box 
+         */
+        public static final int rename_folder_title=0x7f0d0019;
+        public static final int reset=0x7f0d0076;
+        /**  Message displayed when an external application attemps to create a shortcut that already exists 
+         */
+        public static final int shortcut_duplicate=0x7f0d002b;
+        /**  Message displayed when a shortcut is created by an external application 
+         */
+        public static final int shortcut_installed=0x7f0d0029;
+        /**  Message displayed when a shortcut is uninstalled by an external application 
+         */
+        public static final int shortcut_uninstalled=0x7f0d002a;
+        /**  Title of dialog when user is selecting an application to add to homescreen 
+         */
+        public static final int title_select_application=0x7f0d002d;
+        /**  Title of dialog when user is selecting shortcut to add to homescreen 
+         */
+        public static final int title_select_shortcut=0x7f0d002c;
+        /**  Name for all applications running as this uid. 
+         */
+        public static final int uid_name=0x7f0d000b;
+        /**  Text to inform the user that they can't uninstall a system application 
+         */
+        public static final int uninstall_system_app_text=0x7f0d0051;
+        public static final int updatingSystem=0x7f0d00bd;
+        /**  Button label on Wallpaper Gallery screen; user selects this button to set a specific wallpaper 
+         */
+        public static final int wallpaper_instructions=0x7f0d000e;
+        /**  The format string for the dimensions of a widget in the drawer 
+         */
+        public static final int widget_dims_format=0x7f0d0014;
+        /**  Labels for the tabs in the customize drawer 
+         */
+        public static final int widgets_tab_label=0x7f0d0011;
+        /**  The description of how to use the workspace [CHAR_LIMIT=none] 
+         */
+        public static final int workspace_cling_move_item=0x7f0d005a;
+        /**  The description of how to open all apps from the workspace [CHAR_LIMIT=none] 
+         */
+        public static final int workspace_cling_open_all_apps=0x7f0d005b;
+        /**  Clings 
+ The title text for the workspace cling [CHAR_LIMIT=none] 
+         */
+        public static final int workspace_cling_title=0x7f0d0059;
+        /**  The format string for Workspace descriptions [CHAR_LIMIT=none] 
+         */
+        public static final int workspace_description_format=0x7f0d0054;
+        /**  The format string for Workspace page scroll text [CHAR_LIMIT=none] 
+         */
+        public static final int workspace_scroll_format=0x7f0d0056;
+        /**  Fairphone 
+ Your Apps 
+ Fairphone 
+ Your Apps 
+ Fairphone 
+ Your Apps 
+ Fairphone 
+ Your Apps 
+ Fairphone 
+ Your Apps 
+ Fairphone 
+ Your Apps 
+ Fairphone 
+ Your Apps 
+         */
+        public static final int your_apps=0x7f0d006e;
+    }
+    public static final class style {
+        /**  Button styles 
+         */
+        public static final int AppSwitcherButtonReset=0x7f0f0016;
+        public static final int AppSwitcherOOBEDescriptionText=0x7f0f0020;
+        public static final int AppSwitcherOOBEText=0x7f0f001f;
+        public static final int BigIconText=0x7f0f001d;
+        public static final int ClingButton=0x7f0f0002;
+        public static final int ClingText=0x7f0f0004;
+        public static final int ClingTitleText=0x7f0f0003;
+        public static final int CustomClingText=0x7f0f0015;
+        /**  Overridden in device overlays 
+         */
+        public static final int CustomClingTitleText=0x7f0f0014;
+        public static final int DropTargetButton=0x7f0f0010;
+        public static final int DropTargetButtonContainer=0x7f0f000f;
+        public static final int IconText=0x7f0f001c;
+        public static final int MainText=0x7f0f001b;
+        /**  Text styles 
+         */
+        public static final int MainTitle=0x7f0f0018;
+        public static final int MarketButton=0x7f0f0013;
+        public static final int OOBEButton=0x7f0f0017;
+        public static final int OOBEText=0x7f0f0023;
+        public static final int OOBETheme=0x7f0f0021;
+        public static final int OOBETitle=0x7f0f0022;
+        public static final int OOBETitleBig=0x7f0f0024;
+        /**  Search Bar 
+         */
+        public static final int QSBBar=0x7f0f000c;
+        /**  Workspace 
+         */
+        public static final int SearchButton=0x7f0f000e;
+        public static final int SearchDropTargetBar=0x7f0f000d;
+        public static final int SecondaryMainTitle=0x7f0f0019;
+        public static final int SubTitle=0x7f0f001a;
+        public static final int SwipeMenuEditText=0x7f0f001e;
+        public static final int TabIndicator=0x7f0f0011;
+        /**  Overridden in values-land 
+ AppsCustomize 
+ AppsCustomize 
+ AppsCustomize 
+         */
+        public static final int TabIndicator_AppsCustomize=0x7f0f0012;
+        public static final int Theme=0x7f0f0001;
+        public static final int Theme_WallpaperPicker=0x7f0f0000;
+        public static final int WorkspaceIcon=0x7f0f0005;
+        public static final int WorkspaceIcon_Landscape=0x7f0f0007;
+        public static final int WorkspaceIcon_Landscape_AppsCustomize=0x7f0f000b;
+        public static final int WorkspaceIcon_Landscape_Folder=0x7f0f0009;
+        public static final int WorkspaceIcon_Portrait=0x7f0f0006;
+        public static final int WorkspaceIcon_Portrait_AppsCustomize=0x7f0f000a;
+        public static final int WorkspaceIcon_Portrait_Folder=0x7f0f0008;
+    }
+    public static final class xml {
+        public static final int default_workspace=0x7f060000;
+        public static final int google_apps_widget=0x7f060001;
+        public static final int launcher_settings=0x7f060002;
+        public static final int update_workspace=0x7f060003;
+        public static final int wallpaper_picker_preview=0x7f060004;
+        public static final int widget_provider=0x7f060005;
+    }
+    public static final class styleable {
+        /**  AppsCustomizePagedView specific attributes.  These attributes are used to
+         customize an AppsCustomizePagedView in xml files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_clingFocusedX org.fairphone.launcher:clingFocusedX}</code></td><td> The x index of the item to be focused in the cling </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_clingFocusedY org.fairphone.launcher:clingFocusedY}</code></td><td> The y index of the item to be focused in the cling </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_maxAppCellCountX org.fairphone.launcher:maxAppCellCountX}</code></td><td> Max number of cells of applications horizontally </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_maxAppCellCountY org.fairphone.launcher:maxAppCellCountY}</code></td><td> Max number of cells of applications vertically </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_widgetCellHeightGap org.fairphone.launcher:widgetCellHeightGap}</code></td><td> Vertical spacing between widgets </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_widgetCellWidthGap org.fairphone.launcher:widgetCellWidthGap}</code></td><td> Horizontal spacing between widgets and wallpapers </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_widgetCountX org.fairphone.launcher:widgetCountX}</code></td><td> Number of widgets horizontally </td></tr>
+           <tr><td><code>{@link #AppsCustomizePagedView_widgetCountY org.fairphone.launcher:widgetCountY}</code></td><td> Number of widgets vertically </td></tr>
+           </table>
+           @see #AppsCustomizePagedView_clingFocusedX
+           @see #AppsCustomizePagedView_clingFocusedY
+           @see #AppsCustomizePagedView_maxAppCellCountX
+           @see #AppsCustomizePagedView_maxAppCellCountY
+           @see #AppsCustomizePagedView_widgetCellHeightGap
+           @see #AppsCustomizePagedView_widgetCellWidthGap
+           @see #AppsCustomizePagedView_widgetCountX
+           @see #AppsCustomizePagedView_widgetCountY
+         */
+        public static final int[] AppsCustomizePagedView = {
+            0x7f010018, 0x7f010019, 0x7f01001a, 0x7f01001b,
+            0x7f01001c, 0x7f01001d, 0x7f01001e, 0x7f01001f
+        };
+        /**
+          <p>
+          @attr description
+           The x index of the item to be focused in the cling 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:clingFocusedX
+        */
+        public static final int AppsCustomizePagedView_clingFocusedX = 6;
+        /**
+          <p>
+          @attr description
+           The y index of the item to be focused in the cling 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:clingFocusedY
+        */
+        public static final int AppsCustomizePagedView_clingFocusedY = 7;
+        /**
+          <p>
+          @attr description
+           Max number of cells of applications horizontally 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:maxAppCellCountX
+        */
+        public static final int AppsCustomizePagedView_maxAppCellCountX = 0;
+        /**
+          <p>
+          @attr description
+           Max number of cells of applications vertically 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:maxAppCellCountY
+        */
+        public static final int AppsCustomizePagedView_maxAppCellCountY = 1;
+        /**
+          <p>
+          @attr description
+           Vertical spacing between widgets 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:widgetCellHeightGap
+        */
+        public static final int AppsCustomizePagedView_widgetCellHeightGap = 3;
+        /**
+          <p>
+          @attr description
+           Horizontal spacing between widgets and wallpapers 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:widgetCellWidthGap
+        */
+        public static final int AppsCustomizePagedView_widgetCellWidthGap = 2;
+        /**
+          <p>
+          @attr description
+           Number of widgets horizontally 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:widgetCountX
+        */
+        public static final int AppsCustomizePagedView_widgetCountX = 4;
+        /**
+          <p>
+          @attr description
+           Number of widgets vertically 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:widgetCountY
+        */
+        public static final int AppsCustomizePagedView_widgetCountY = 5;
+        /**  CellLayout specific attributes. These attributes are used to customize
+         a CellLayout view in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #CellLayout_cellHeight org.fairphone.launcher:cellHeight}</code></td><td> The height of a single cell </td></tr>
+           <tr><td><code>{@link #CellLayout_cellWidth org.fairphone.launcher:cellWidth}</code></td><td> The width of a single cell </td></tr>
+           <tr><td><code>{@link #CellLayout_heightGap org.fairphone.launcher:heightGap}</code></td><td></td></tr>
+           <tr><td><code>{@link #CellLayout_maxGap org.fairphone.launcher:maxGap}</code></td><td> The max gap size for each dimension </td></tr>
+           <tr><td><code>{@link #CellLayout_widthGap org.fairphone.launcher:widthGap}</code></td><td> An override for the width and height gap to allow users to specify
+             a specific size for the page using spacing instead of resolving the
+             spacing from the width of the page </td></tr>
+           </table>
+           @see #CellLayout_cellHeight
+           @see #CellLayout_cellWidth
+           @see #CellLayout_heightGap
+           @see #CellLayout_maxGap
+           @see #CellLayout_widthGap
+         */
+        public static final int[] CellLayout = {
+            0x7f010006, 0x7f010007, 0x7f010008, 0x7f010009,
+            0x7f01000a
+        };
+        /**
+          <p>
+          @attr description
+           The height of a single cell 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:cellHeight
+        */
+        public static final int CellLayout_cellHeight = 1;
+        /**
+          <p>
+          @attr description
+           The width of a single cell 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:cellWidth
+        */
+        public static final int CellLayout_cellWidth = 0;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#heightGap}
+          attribute's value can be found in the {@link #CellLayout} array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:heightGap
+        */
+        public static final int CellLayout_heightGap = 3;
+        /**
+          <p>
+          @attr description
+           The max gap size for each dimension 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:maxGap
+        */
+        public static final int CellLayout_maxGap = 4;
+        /**
+          <p>
+          @attr description
+           An override for the width and height gap to allow users to specify
+             a specific size for the page using spacing instead of resolving the
+             spacing from the width of the page 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:widthGap
+        */
+        public static final int CellLayout_widthGap = 2;
+        /**  Cling specific attributes. These attributes are used to customize
+         the cling in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #Cling_drawIdentifier org.fairphone.launcher:drawIdentifier}</code></td><td> Used to identify how to draw the cling bg </td></tr>
+           </table>
+           @see #Cling_drawIdentifier
+         */
+        public static final int[] Cling = {
+            0x7f010002
+        };
+        /**
+          <p>
+          @attr description
+           Used to identify how to draw the cling bg 
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:drawIdentifier
+        */
+        public static final int Cling_drawIdentifier = 0;
+        /** Attributes that can be used with a CustomClingText.
+         */
+        public static final int[] CustomClingText = {
+            
+        };
+        /**  Only used in the device overlays 
+         */
+        public static final int[] CustomClingTitleText = {
+            
+        };
+        /**  DrawableStateProxyView specific attributes. These attributes are used to customize
+         a DrawableStateProxyView view in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #DrawableStateProxyView_sourceViewId org.fairphone.launcher:sourceViewId}</code></td><td> The source view to delegate touch presses events to.</td></tr>
+           </table>
+           @see #DrawableStateProxyView_sourceViewId
+         */
+        public static final int[] DrawableStateProxyView = {
+            0x7f010001
+        };
+        /**
+          <p>
+          @attr description
+           The source view to delegate touch presses events to. 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:sourceViewId
+        */
+        public static final int DrawableStateProxyView_sourceViewId = 0;
+        /** Attributes that can be used with a Extra.
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #Extra_key org.fairphone.launcher:key}</code></td><td></td></tr>
+           <tr><td><code>{@link #Extra_value org.fairphone.launcher:value}</code></td><td></td></tr>
+           </table>
+           @see #Extra_key
+           @see #Extra_value
+         */
+        public static final int[] Extra = {
+            0x7f01002b, 0x7f01002c
+        };
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#key}
+          attribute's value can be found in the {@link #Extra} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:key
+        */
+        public static final int Extra_key = 0;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#value}
+          attribute's value can be found in the {@link #Extra} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:value
+        */
+        public static final int Extra_value = 1;
+        /**  XML attributes used by default_workspace.xml 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #Favorite_className org.fairphone.launcher:className}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_container org.fairphone.launcher:container}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_icon org.fairphone.launcher:icon}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_packageName org.fairphone.launcher:packageName}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_screen org.fairphone.launcher:screen}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_spanX org.fairphone.launcher:spanX}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_spanY org.fairphone.launcher:spanY}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_title org.fairphone.launcher:title}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_uri org.fairphone.launcher:uri}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_x org.fairphone.launcher:x}</code></td><td></td></tr>
+           <tr><td><code>{@link #Favorite_y org.fairphone.launcher:y}</code></td><td></td></tr>
+           </table>
+           @see #Favorite_className
+           @see #Favorite_container
+           @see #Favorite_icon
+           @see #Favorite_packageName
+           @see #Favorite_screen
+           @see #Favorite_spanX
+           @see #Favorite_spanY
+           @see #Favorite_title
+           @see #Favorite_uri
+           @see #Favorite_x
+           @see #Favorite_y
+         */
+        public static final int[] Favorite = {
+            0x7f010020, 0x7f010021, 0x7f010022, 0x7f010023,
+            0x7f010024, 0x7f010025, 0x7f010026, 0x7f010027,
+            0x7f010028, 0x7f010029, 0x7f01002a
+        };
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#className}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:className
+        */
+        public static final int Favorite_className = 0;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#container}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:container
+        */
+        public static final int Favorite_container = 2;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#icon}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+          @attr name org.fairphone.launcher:icon
+        */
+        public static final int Favorite_icon = 8;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#packageName}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:packageName
+        */
+        public static final int Favorite_packageName = 1;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#screen}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:screen
+        */
+        public static final int Favorite_screen = 3;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#spanX}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:spanX
+        */
+        public static final int Favorite_spanX = 6;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#spanY}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:spanY
+        */
+        public static final int Favorite_spanY = 7;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#title}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a reference to another resource, in the form "<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>"
+or to a theme attribute in the form "<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>".
+          @attr name org.fairphone.launcher:title
+        */
+        public static final int Favorite_title = 9;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#uri}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:uri
+        */
+        public static final int Favorite_uri = 10;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#x}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:x
+        */
+        public static final int Favorite_x = 4;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#y}
+          attribute's value can be found in the {@link #Favorite} array.
+
+
+          <p>Must be a string value, using '\\;' to escape characters such as '\\n' or '\\uxxxx' for a unicode character.
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:y
+        */
+        public static final int Favorite_y = 5;
+        /**  HandleView specific attributes. These attributes are used to customize
+         a HandleView view in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #HandleView_direction org.fairphone.launcher:direction}</code></td><td> Orientation of the handle.</td></tr>
+           </table>
+           @see #HandleView_direction
+         */
+        public static final int[] HandleView = {
+            0x7f010000
+        };
+        /**
+          <p>
+          @attr description
+           Orientation of the handle. 
+
+
+          <p>Must be one of the following constant values.</p>
+<table>
+<colgroup align="left" />
+<colgroup align="left" />
+<colgroup align="left" />
+<tr><th>Constant</th><th>Value</th><th>Description</th></tr>
+<tr><td><code>vertical</code></td><td>0</td><td> Vertical widget. </td></tr>
+<tr><td><code>horizontal</code></td><td>1</td><td> Horizontal widget. </td></tr>
+</table>
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:direction
+        */
+        public static final int HandleView_direction = 0;
+        /**  HolographicLinearLayout specific attributes. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #HolographicLinearLayout_sourceImageViewId org.fairphone.launcher:sourceImageViewId}</code></td><td> The source view to generate and apply the drawable states to/from </td></tr>
+           </table>
+           @see #HolographicLinearLayout_sourceImageViewId
+         */
+        public static final int[] HolographicLinearLayout = {
+            0x7f01000e
+        };
+        /**
+          <p>
+          @attr description
+           The source view to generate and apply the drawable states to/from 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:sourceImageViewId
+        */
+        public static final int HolographicLinearLayout_sourceImageViewId = 0;
+        /**  Hotseat specific attributes. These attributes are used to customize
+         the hotseat in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #Hotseat_cellCountX org.fairphone.launcher:cellCountX}</code></td><td> The number of horizontal cells in the CellLayout </td></tr>
+           <tr><td><code>{@link #Hotseat_cellCountY org.fairphone.launcher:cellCountY}</code></td><td> The number of vertical cells in the CellLayout </td></tr>
+           </table>
+           @see #Hotseat_cellCountX
+           @see #Hotseat_cellCountY
+         */
+        public static final int[] Hotseat = {
+            0x7f010004, 0x7f010005
+        };
+        /**
+          <p>
+          @attr description
+           The number of horizontal cells in the CellLayout 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:cellCountX
+        */
+        public static final int Hotseat_cellCountX = 0;
+        /**
+          <p>
+          @attr description
+           The number of vertical cells in the CellLayout 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:cellCountY
+        */
+        public static final int Hotseat_cellCountY = 1;
+        /**  PagedView specific attributes. These attributes are used to customize
+         a PagedView view in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #PagedView_pageLayoutHeightGap org.fairphone.launcher:pageLayoutHeightGap}</code></td><td></td></tr>
+           <tr><td><code>{@link #PagedView_pageLayoutPaddingBottom org.fairphone.launcher:pageLayoutPaddingBottom}</code></td><td></td></tr>
+           <tr><td><code>{@link #PagedView_pageLayoutPaddingLeft org.fairphone.launcher:pageLayoutPaddingLeft}</code></td><td></td></tr>
+           <tr><td><code>{@link #PagedView_pageLayoutPaddingRight org.fairphone.launcher:pageLayoutPaddingRight}</code></td><td></td></tr>
+           <tr><td><code>{@link #PagedView_pageLayoutPaddingTop org.fairphone.launcher:pageLayoutPaddingTop}</code></td><td> The padding of the pages that are dynamically created per page </td></tr>
+           <tr><td><code>{@link #PagedView_pageLayoutWidthGap org.fairphone.launcher:pageLayoutWidthGap}</code></td><td> A spacing override for the icons within a page </td></tr>
+           <tr><td><code>{@link #PagedView_pageSpacing org.fairphone.launcher:pageSpacing}</code></td><td> The space between adjacent pages of the PagedView.</td></tr>
+           <tr><td><code>{@link #PagedView_scrollIndicatorPaddingLeft org.fairphone.launcher:scrollIndicatorPaddingLeft}</code></td><td> The padding for the scroll indicator area </td></tr>
+           <tr><td><code>{@link #PagedView_scrollIndicatorPaddingRight org.fairphone.launcher:scrollIndicatorPaddingRight}</code></td><td></td></tr>
+           </table>
+           @see #PagedView_pageLayoutHeightGap
+           @see #PagedView_pageLayoutPaddingBottom
+           @see #PagedView_pageLayoutPaddingLeft
+           @see #PagedView_pageLayoutPaddingRight
+           @see #PagedView_pageLayoutPaddingTop
+           @see #PagedView_pageLayoutWidthGap
+           @see #PagedView_pageSpacing
+           @see #PagedView_scrollIndicatorPaddingLeft
+           @see #PagedView_scrollIndicatorPaddingRight
+         */
+        public static final int[] PagedView = {
+            0x7f01000f, 0x7f010010, 0x7f010011, 0x7f010012,
+            0x7f010013, 0x7f010014, 0x7f010015, 0x7f010016,
+            0x7f010017
+        };
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#pageLayoutHeightGap}
+          attribute's value can be found in the {@link #PagedView} array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:pageLayoutHeightGap
+        */
+        public static final int PagedView_pageLayoutHeightGap = 1;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#pageLayoutPaddingBottom}
+          attribute's value can be found in the {@link #PagedView} array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:pageLayoutPaddingBottom
+        */
+        public static final int PagedView_pageLayoutPaddingBottom = 3;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#pageLayoutPaddingLeft}
+          attribute's value can be found in the {@link #PagedView} array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:pageLayoutPaddingLeft
+        */
+        public static final int PagedView_pageLayoutPaddingLeft = 4;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#pageLayoutPaddingRight}
+          attribute's value can be found in the {@link #PagedView} array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:pageLayoutPaddingRight
+        */
+        public static final int PagedView_pageLayoutPaddingRight = 5;
+        /**
+          <p>
+          @attr description
+           The padding of the pages that are dynamically created per page 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:pageLayoutPaddingTop
+        */
+        public static final int PagedView_pageLayoutPaddingTop = 2;
+        /**
+          <p>
+          @attr description
+           A spacing override for the icons within a page 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:pageLayoutWidthGap
+        */
+        public static final int PagedView_pageLayoutWidthGap = 0;
+        /**
+          <p>
+          @attr description
+           The space between adjacent pages of the PagedView. 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:pageSpacing
+        */
+        public static final int PagedView_pageSpacing = 6;
+        /**
+          <p>
+          @attr description
+           The padding for the scroll indicator area 
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:scrollIndicatorPaddingLeft
+        */
+        public static final int PagedView_scrollIndicatorPaddingLeft = 7;
+        /**
+          <p>This symbol is the offset where the {@link org.fairphone.launcher.R.attr#scrollIndicatorPaddingRight}
+          attribute's value can be found in the {@link #PagedView} array.
+
+
+          <p>Must be a dimension value, which is a floating point number appended with a unit such as "<code>14.5sp</code>".
+Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),
+in (inches), mm (millimeters).
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          @attr name org.fairphone.launcher:scrollIndicatorPaddingRight
+        */
+        public static final int PagedView_scrollIndicatorPaddingRight = 8;
+        /**  StrokedTextView specific attributes. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #StrokedTextView_strokeColor org.fairphone.launcher:strokeColor}</code></td><td> The color of the stroke outline </td></tr>
+           <tr><td><code>{@link #StrokedTextView_strokeTextColor org.fairphone.launcher:strokeTextColor}</code></td><td> The color of the text </td></tr>
+           <tr><td><code>{@link #StrokedTextView_strokeWidth org.fairphone.launcher:strokeWidth}</code></td><td> The width of the stroke </td></tr>
+           </table>
+           @see #StrokedTextView_strokeColor
+           @see #StrokedTextView_strokeTextColor
+           @see #StrokedTextView_strokeWidth
+         */
+        public static final int[] StrokedTextView = {
+            0x7f01000b, 0x7f01000c, 0x7f01000d
+        };
+        /**
+          <p>
+          @attr description
+           The color of the stroke outline 
+
+
+          <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:strokeColor
+        */
+        public static final int StrokedTextView_strokeColor = 0;
+        /**
+          <p>
+          @attr description
+           The color of the text 
+
+
+          <p>Must be a color value, in the form of "<code>#<i>rgb</i></code>", "<code>#<i>argb</i></code>",
+"<code>#<i>rrggbb</i></code>", or "<code>#<i>aarrggbb</i></code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:strokeTextColor
+        */
+        public static final int StrokedTextView_strokeTextColor = 1;
+        /**
+          <p>
+          @attr description
+           The width of the stroke 
+
+
+          <p>Must be a floating point value, such as "<code>1.2</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:strokeWidth
+        */
+        public static final int StrokedTextView_strokeWidth = 2;
+        /**  Workspace specific attributes. These attributes are used to customize
+         the workspace in XML files. 
+           <p>Includes the following attributes:</p>
+           <table>
+           <colgroup align="left" />
+           <colgroup align="left" />
+           <tr><th>Attribute</th><th>Description</th></tr>
+           <tr><td><code>{@link #Workspace_cellCountX org.fairphone.launcher:cellCountX}</code></td><td> The number of horizontal cells in the CellLayout </td></tr>
+           <tr><td><code>{@link #Workspace_cellCountY org.fairphone.launcher:cellCountY}</code></td><td> The number of vertical cells in the CellLayout </td></tr>
+           <tr><td><code>{@link #Workspace_defaultScreen org.fairphone.launcher:defaultScreen}</code></td><td> The first screen the workspace should display.</td></tr>
+           </table>
+           @see #Workspace_cellCountX
+           @see #Workspace_cellCountY
+           @see #Workspace_defaultScreen
+         */
+        public static final int[] Workspace = {
+            0x7f010003, 0x7f010004, 0x7f010005
+        };
+        /**
+          <p>
+          @attr description
+           The number of horizontal cells in the CellLayout 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:cellCountX
+        */
+        public static final int Workspace_cellCountX = 1;
+        /**
+          <p>
+          @attr description
+           The number of vertical cells in the CellLayout 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:cellCountY
+        */
+        public static final int Workspace_cellCountY = 2;
+        /**
+          <p>
+          @attr description
+           The first screen the workspace should display. 
+
+
+          <p>Must be an integer value, such as "<code>100</code>".
+<p>This may also be a reference to a resource (in the form
+"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>") or
+theme attribute (in the form
+"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>")
+containing a value of this type.
+          <p>This is a private symbol.
+          @attr name org.fairphone.launcher:defaultScreen
+        */
+        public static final int Workspace_defaultScreen = 0;
+    };
+}
diff --git a/FairphoneHome/libs/RootTools-3.3.jar b/FairphoneHome/libs/RootTools-3.3.jar
new file mode 100644
index 0000000..fc9419c
--- /dev/null
+++ b/FairphoneHome/libs/RootTools-3.3.jar
Binary files differ
diff --git a/FairphoneHome/libs/acra-4.4.0.jar b/FairphoneHome/libs/acra-4.4.0.jar
new file mode 100644
index 0000000..27fdae4
--- /dev/null
+++ b/FairphoneHome/libs/acra-4.4.0.jar
Binary files differ
diff --git a/FairphoneHome/libs/android-support-v4.jar b/FairphoneHome/libs/android-support-v4.jar
new file mode 100644
index 0000000..af90a7f
--- /dev/null
+++ b/FairphoneHome/libs/android-support-v4.jar
Binary files differ
diff --git a/FairphoneHome/print_db.py b/FairphoneHome/print_db.py
new file mode 100755
index 0000000..4f90f94
--- /dev/null
+++ b/FairphoneHome/print_db.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python2.5
+
+import cgi
+import os
+import shutil
+import sys
+import sqlite3
+
+SCREENS = 5
+COLUMNS = 4
+ROWS = 4
+HOTSEAT_SIZE = 5
+CELL_SIZE = 110
+
+DIR = "db_files"
+AUTO_FILE = DIR + "/launcher.db"
+INDEX_FILE = DIR + "/index.html"
+
+def usage():
+  print "usage: print_db.py launcher.db -- prints a launcher.db"
+  print "usage: print_db.py -- adb pulls a launcher.db from a device"
+  print "       and prints it"
+  print
+  print "The dump will be created in a directory called db_files in cwd."
+  print "This script will delete any db_files directory you have now"
+
+
+def make_dir():
+  shutil.rmtree(DIR, True)
+  os.makedirs(DIR)
+
+def pull_file(fn):
+  print "pull_file: " + fn
+  rv = os.system("adb pull"
+    + " /data/data/com.android.launcher/databases/launcher.db"
+    + " " + fn);
+  if rv != 0:
+    print "adb pull failed"
+    sys.exit(1)
+
+def get_favorites(conn):
+  c = conn.cursor()
+  c.execute("SELECT * FROM favorites")
+  columns = [d[0] for d in c.description]
+  rows = []
+  for row in c:
+    rows.append(row)
+  return columns,rows
+
+def print_intent(out, id, i, cell):
+  if cell:
+    out.write("""<span class="intent" title="%s">shortcut</span>""" % (
+        cgi.escape(cell, True)
+      ))
+
+
+def print_icon(out, id, i, cell):
+  if cell:
+    icon_fn = "icon_%d.png" % id
+    out.write("""<img src="%s">""" % ( icon_fn ))
+    f = file(DIR + "/" + icon_fn, "w")
+    f.write(cell)
+    f.close()
+
+def print_cell(out, id, i, cell):
+  if not cell is None:
+    out.write(cgi.escape(str(cell)))
+
+FUNCTIONS = {
+  "intent": print_intent,
+  "icon": print_icon
+}
+
+def render_cell_info(out, cell, occupied):
+  if cell is None:
+    out.write("    <td width=%d height=%d></td>\n" %
+        (CELL_SIZE, CELL_SIZE))
+  elif cell == occupied:
+    pass
+  else:
+    cellX = cell["cellX"]
+    cellY = cell["cellY"]
+    spanX = cell["spanX"]
+    spanY = cell["spanY"]
+    intent = cell["intent"]
+    if intent:
+      title = "title=\"%s\"" % cgi.escape(cell["intent"], True)
+    else:
+      title = ""
+    out.write(("    <td colspan=%d rowspan=%d width=%d height=%d"
+        + " bgcolor=#dddddd align=center valign=middle %s>") % (
+          spanX, spanY,
+          (CELL_SIZE*spanX), (CELL_SIZE*spanY),
+          title))
+    itemType = cell["itemType"]
+    if itemType == 0:
+      out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] ))
+      out.write("<br/>\n")
+      out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>")
+    elif itemType == 1:
+      out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] ))
+      out.write("<br/>\n")
+      out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>")
+    elif itemType == 2:
+      out.write("""<i>folder</i>""")
+    elif itemType == 3:
+      out.write("""<i>live folder</i>""")
+    elif itemType == 4:
+      out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"])
+    elif itemType == 1000:
+      out.write("""<i>clock</i>""")
+    elif itemType == 1001:
+      out.write("""<i>search</i>""")
+    elif itemType == 1002:
+      out.write("""<i>photo frame</i>""")
+    else:
+      out.write("<b>unknown type: %d</b>" % itemType)
+    out.write("</td>\n")
+
+def process_file(fn):
+  print "process_file: " + fn
+  conn = sqlite3.connect(fn)
+  columns,rows = get_favorites(conn)
+  data = [dict(zip(columns,row)) for row in rows]
+
+  out = file(INDEX_FILE, "w")
+  out.write("""<html>
+<head>
+<style type="text/css">
+.intent {
+  font-style: italic;
+}
+</style>
+</head>
+<body>
+""")
+
+  # Data table
+  out.write("<b>Favorites table</b><br/>\n")
+  out.write("""<html>
+<table border=1 cellspacing=0 cellpadding=4>
+<tr>
+""")
+  print_functions = []
+  for col in columns:
+    print_functions.append(FUNCTIONS.get(col, print_cell))
+  for i in range(0,len(columns)):
+    col = columns[i]
+    out.write("""  <th>%s</th>
+""" % ( col ))
+  out.write("""
+</tr>
+""")
+  for row in rows:
+    out.write("""<tr>
+""")
+    for i in range(0,len(row)):
+      cell = row[i]
+      # row[0] is always _id
+      out.write("""  <td>""")
+      print_functions[i](out, row[0], row, cell)
+      out.write("""</td>
+""")
+    out.write("""</tr>
+""")
+  out.write("""</table>
+""")
+
+  # Hotseat
+  hotseat = []
+  for i in range(0, HOTSEAT_SIZE):
+    hotseat.append(None)
+  for row in data:
+    if row["container"] != -101:
+      continue
+    screen = row["screen"]
+    hotseat[screen] = row
+  out.write("<br/><b>Hotseat</b><br/>\n")
+  out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
+  for cell in hotseat:
+    render_cell_info(out, cell, None)
+  out.write("</table>\n")
+
+  # Pages
+  screens = []
+  for i in range(0,SCREENS):
+    screen = []
+    for j in range(0,ROWS):
+      m = []
+      for k in range(0,COLUMNS):
+        m.append(None)
+      screen.append(m)
+    screens.append(screen)
+  occupied = "occupied"
+  for row in data:
+    screen = screens[row["screen"]]
+    # desktop
+    if row["container"] != -100:
+      continue
+    cellX = row["cellX"]
+    cellY = row["cellY"]
+    spanX = row["spanX"]
+    spanY = row["spanY"]
+    for j in range(cellY, cellY+spanY):
+      for k in range(cellX, cellX+spanX):
+        screen[j][k] = occupied
+    screen[cellY][cellX] = row
+  i=0
+  for screen in screens:
+    out.write("<br/><b>Screen %d</b><br/>\n" % i)
+    out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
+    for m in screen:
+      out.write("  <tr>\n")
+      for cell in m:
+        render_cell_info(out, cell, occupied)
+      out.write("</tr>\n")
+    out.write("</table>\n")
+    i=i+1
+
+  out.write("""
+</body>
+</html>
+""")
+
+  out.close()
+
+def main(argv):
+  if len(argv) == 1:
+    make_dir()
+    pull_file(AUTO_FILE)
+    process_file(AUTO_FILE)
+  elif len(argv) == 2:
+    make_dir()
+    process_file(argv[1])
+  else:
+    usage()
+
+if __name__=="__main__":
+  main(sys.argv)
diff --git a/FairphoneHome/proguard-project.txt b/FairphoneHome/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/FairphoneHome/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/FairphoneHome/proguard.flags b/FairphoneHome/proguard.flags
new file mode 100644
index 0000000..0cde28e
--- /dev/null
+++ b/FairphoneHome/proguard.flags
@@ -0,0 +1,64 @@
+-keep class com.android.launcher2.Launcher {
+  public void previousScreen(android.view.View);
+  public void nextScreen(android.view.View);
+  public void launchHotSeat(android.view.View);
+  public void onClickSearchButton(android.view.View);
+  public void onClickVoiceButton(android.view.View);
+  public void onClickConfigureButton(android.view.View);
+  public void onClickAllAppsButton(android.view.View);
+  public void onClickAppMarketButton(android.view.View);
+  public void dismissWorkspaceCling(android.view.View);
+  public void dismissAllAppsCling(android.view.View);
+}
+
+-keep class com.android.launcher2.CellLayout {
+  public float getBackgroundAlpha();
+  public void setBackgroundAlpha(float);
+  public float getDimmableProgress();
+  public void setDimmableProgress(float);
+  public float getHoverScale();
+  public void setHoverScale(float);
+  public float getHoverAlpha();
+  public void setHoverAlpha(float);
+}
+
+-keep class com.android.launcher2.DragLayer$LayoutParams {
+  public void setWidth(int);
+  public int getWidth();
+  public void setHeight(int);
+  public int getHeight();
+  public void setX(int);
+  public int getX();
+  public void setY(int);
+  public int getY();
+}
+
+-keep class com.android.launcher2.CellLayout$LayoutParams {
+  public void setWidth(int);
+  public int getWidth();
+  public void setHeight(int);
+  public int getHeight();
+  public void setX(int);
+  public int getX();
+  public void setY(int);
+  public int getY();
+}
+
+-keep class com.android.launcher2.Workspace {
+  public float getBackgroundAlpha();
+  public void setBackgroundAlpha(float);
+  public float getChildrenOutlineAlpha();
+  public void setChildrenOutlineAlpha(float);
+  public void setVerticalWallpaperOffset(float);
+  public float getVerticalWallpaperOffset();
+  public void setHorizontalWallpaperOffset(float);
+  public float getHorizontalWallpaperOffset();
+}
+
+-keep class com.android.launcher2.AllApps3D$Defines {
+  *;
+}
+
+-keep class com.android.launcher2.ClippedImageView {
+  *;
+}
diff --git a/FairphoneHome/project.properties b/FairphoneHome/project.properties
new file mode 100644
index 0000000..0c9830a
--- /dev/null
+++ b/FairphoneHome/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=Google Inc.:Google APIs:17
diff --git a/FairphoneHome/res/anim/button_select_animation.xml b/FairphoneHome/res/anim/button_select_animation.xml
new file mode 100644
index 0000000..589ff1a
--- /dev/null
+++ b/FairphoneHome/res/anim/button_select_animation.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+<!-- 

+    <alpha

+        android:duration="100"

+        android:fromAlpha="1.0"

+        android:toAlpha="0.2" />

+  -->

+    <scale

+        android:duration="200"

+        android:fromXScale="1.3"

+        android:fromYScale="1.3"

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:pivotX="50%"

+        android:pivotY="50%"

+        android:toXScale="1.0"

+        android:toYScale="1.0" />

+ <!--

+        <alpha

+        android:duration="100"

+        android:fromAlpha="0.2"

+        android:toAlpha="1.0"

+        android:startOffset="100" />

+-->

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/fade_in_fast.xml b/FairphoneHome/res/anim/fade_in_fast.xml
new file mode 100644
index 0000000..4fa9847
--- /dev/null
+++ b/FairphoneHome/res/anim/fade_in_fast.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="@android:integer/config_mediumAnimTime" />
diff --git a/FairphoneHome/res/anim/fade_in_slow.xml b/FairphoneHome/res/anim/fade_in_slow.xml
new file mode 100644
index 0000000..4d28444
--- /dev/null
+++ b/FairphoneHome/res/anim/fade_in_slow.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="600" />
diff --git a/FairphoneHome/res/anim/fade_out_fast.xml b/FairphoneHome/res/anim/fade_out_fast.xml
new file mode 100644
index 0000000..a061a6c
--- /dev/null
+++ b/FairphoneHome/res/anim/fade_out_fast.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+
+    android:duration="@android:integer/config_mediumAnimTime" />
diff --git a/FairphoneHome/res/anim/fade_out_slow.xml b/FairphoneHome/res/anim/fade_out_slow.xml
new file mode 100644
index 0000000..0052546
--- /dev/null
+++ b/FairphoneHome/res/anim/fade_out_slow.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/decelerate_interpolator"
+
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+
+    android:duration="600" />
diff --git a/FairphoneHome/res/anim/menu_activation_zone_appear.xml b/FairphoneHome/res/anim/menu_activation_zone_appear.xml
new file mode 100644
index 0000000..729a39c
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_activation_zone_appear.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+

+    <alpha

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromAlpha="0.0"

+        android:toAlpha="1.0" />

+</set>

diff --git a/FairphoneHome/res/anim/menu_activation_zone_disappear.xml b/FairphoneHome/res/anim/menu_activation_zone_disappear.xml
new file mode 100644
index 0000000..3877da6
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_activation_zone_disappear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+

+    <alpha

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromAlpha="1.0"

+        android:toAlpha="0.0" />

+

+</set>

diff --git a/FairphoneHome/res/anim/menu_appear_from_left_animation.xml b/FairphoneHome/res/anim/menu_appear_from_left_animation.xml
new file mode 100644
index 0000000..06c7265
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_appear_from_left_animation.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+

+    <scale

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromXScale="0.1"

+        android:fromYScale="0.1"

+        android:toXScale="1.0"

+        android:toYScale="1.0"

+        android:pivotX="50%"

+        android:pivotY="50%"/>

+

+    <alpha

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromAlpha="0.0"

+        android:toAlpha="1.0" />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/menu_appear_from_right_animation.xml b/FairphoneHome/res/anim/menu_appear_from_right_animation.xml
new file mode 100644
index 0000000..06c7265
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_appear_from_right_animation.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+

+    <scale

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromXScale="0.1"

+        android:fromYScale="0.1"

+        android:toXScale="1.0"

+        android:toYScale="1.0"

+        android:pivotX="50%"

+        android:pivotY="50%"/>

+

+    <alpha

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromAlpha="0.0"

+        android:toAlpha="1.0" />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/menu_background_fade_in.xml b/FairphoneHome/res/anim/menu_background_fade_in.xml
new file mode 100644
index 0000000..edb8814
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_background_fade_in.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="@integer/config_edgeMenuQuickTime" />
diff --git a/FairphoneHome/res/anim/menu_background_fade_out.xml b/FairphoneHome/res/anim/menu_background_fade_out.xml
new file mode 100644
index 0000000..82f93d1
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_background_fade_out.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+
+    android:duration="@integer/config_edgeMenuQuickTime" />
diff --git a/FairphoneHome/res/anim/menu_disappear_to_left_animation.xml b/FairphoneHome/res/anim/menu_disappear_to_left_animation.xml
new file mode 100644
index 0000000..e72a88c
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_disappear_to_left_animation.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android">

+    

+	

+     <scale

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromXScale="1.0"

+        android:fromYScale="1.0"

+        android:toXScale="0.1"

+        android:toYScale="0.1"

+        android:pivotX="50%"

+        android:pivotY="50%"/>

+

+    <alpha

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromAlpha="1.0"

+        android:toAlpha="0.0" />

+    

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/menu_disappear_to_right_animation.xml b/FairphoneHome/res/anim/menu_disappear_to_right_animation.xml
new file mode 100644
index 0000000..e72a88c
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_disappear_to_right_animation.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android">

+    

+	

+     <scale

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromXScale="1.0"

+        android:fromYScale="1.0"

+        android:toXScale="0.1"

+        android:toYScale="0.1"

+        android:pivotX="50%"

+        android:pivotY="50%"/>

+

+    <alpha

+        android:duration="@integer/config_edgeMenuQuickTime"

+        android:fromAlpha="1.0"

+        android:toAlpha="0.0" />

+    

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/menu_edge_edit_button_fade_in.xml b/FairphoneHome/res/anim/menu_edge_edit_button_fade_in.xml
new file mode 100644
index 0000000..edb8814
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_edge_edit_button_fade_in.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="@integer/config_edgeMenuQuickTime" />
diff --git a/FairphoneHome/res/anim/menu_icon_ring_fade_in.xml b/FairphoneHome/res/anim/menu_icon_ring_fade_in.xml
new file mode 100644
index 0000000..dc0533f
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_icon_ring_fade_in.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="100" />
diff --git a/FairphoneHome/res/anim/menu_icon_ring_fade_out.xml b/FairphoneHome/res/anim/menu_icon_ring_fade_out.xml
new file mode 100644
index 0000000..886899a
--- /dev/null
+++ b/FairphoneHome/res/anim/menu_icon_ring_fade_out.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+
+    android:duration="100" />
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_main.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_main.xml
new file mode 100644
index 0000000..776f495
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_main.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">

+

+	    <translate

+	        android:fromXDelta="120%p"

+	        android:toXDelta="0%"

+	        android:startOffset="550"

+	        android:duration="300"

+	        android:interpolator="@android:anim/decelerate_interpolator"/>

+	    

+	    <alpha

+        android:duration="400"

+        android:fromAlpha="1.0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="2000"

+        android:toAlpha="0.0" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_main_2.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_main_2.xml
new file mode 100644
index 0000000..cfa08ff
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_main_2.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">

+

+	    <translate

+	        android:fromXDelta="120%p"

+	        android:toXDelta="0%"

+	        android:startOffset="550"

+	        android:duration="300"

+	        android:interpolator="@android:anim/decelerate_interpolator"/>

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_outro.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_outro.xml
new file mode 100644
index 0000000..776f495
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_arrow_outro.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">

+

+	    <translate

+	        android:fromXDelta="120%p"

+	        android:toXDelta="0%"

+	        android:startOffset="550"

+	        android:duration="300"

+	        android:interpolator="@android:anim/decelerate_interpolator"/>

+	    

+	    <alpha

+        android:duration="400"

+        android:fromAlpha="1.0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="2000"

+        android:toAlpha="0.0" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_hand_main.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_hand_main.xml
new file mode 100644
index 0000000..fcdfcbc
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_hand_main.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:shareInterpolator="false" >

+

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="120%p"

+        android:toXDelta="20"

+        android:duration="700"

+        android:interpolator="@android:anim/accelerate_interpolator"/>

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="20"

+        android:toXDelta="-20"

+        android:duration="1400"

+        android:interpolator="@android:anim/decelerate_interpolator"/>

+    

+    <alpha

+        android:duration="400"

+        android:fromAlpha="1.0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="2000"

+        android:toAlpha="0.0" />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_hand_main_2.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_hand_main_2.xml
new file mode 100644
index 0000000..625258c
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_hand_main_2.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:shareInterpolator="false" >

+

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="120%p"

+        android:toXDelta="20"

+        android:duration="700"

+        android:interpolator="@android:anim/accelerate_interpolator"/>

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="20"

+        android:toXDelta="-20"

+        android:duration="1400"

+        android:interpolator="@android:anim/decelerate_interpolator"/>

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_hand_outro.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_hand_outro.xml
new file mode 100644
index 0000000..204a311
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_hand_outro.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:shareInterpolator="false" >

+

+    <translate

+        android:duration="700"

+        android:fromXDelta="0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="100"

+        android:toXDelta="-50%p" />

+

+    <alpha

+        android:duration="650"

+        android:fromAlpha="1.0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="100"

+        android:toAlpha="0.0" />

+

+    <scale

+        android:fromXScale="1.0"

+        android:fromYScale="1.0"

+        android:toXScale="8.0"

+        android:toYScale="8.0"

+        android:duration="750"

+        android:startOffset="50"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_touch_main.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_touch_main.xml
new file mode 100644
index 0000000..37ab258
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_touch_main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:fillAfter="true">

+

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="120%p"

+        android:toXDelta="20"

+        android:duration="700"

+        android:interpolator="@android:anim/accelerate_interpolator"/>

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="20"

+        android:toXDelta="-20"

+        android:duration="1400"

+        android:interpolator="@android:anim/decelerate_interpolator"/>

+    

+    <alpha

+        android:duration="400"

+        android:fromAlpha="1.0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="2000"

+        android:toAlpha="0.0" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_touch_main_2.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_touch_main_2.xml
new file mode 100644
index 0000000..79b6104
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_touch_main_2.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:fillAfter="true">

+

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="120%p"

+        android:toXDelta="20"

+        android:duration="700"

+        android:interpolator="@android:anim/accelerate_interpolator"/>

+    <translate

+        android:startOffset="600"

+        android:fromXDelta="20"

+        android:toXDelta="-20"

+        android:duration="1400"

+        android:interpolator="@android:anim/decelerate_interpolator"/>

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edge_swipe_touch_outro.xml b/FairphoneHome/res/anim/tutorial_edge_swipe_touch_outro.xml
new file mode 100644
index 0000000..d794da0
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edge_swipe_touch_outro.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:fillAfter="true">

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_counter_main.xml b/FairphoneHome/res/anim/tutorial_edit_favs_counter_main.xml
new file mode 100644
index 0000000..cc72fc8
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_counter_main.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:fillAfter="true"

+    android:shareInterpolator="false" >

+

+    <alpha

+        android:duration="100"

+        android:fillBefore="true"

+        android:fillEnabled="true"

+        android:fromAlpha="0.0"

+        android:startOffset="1700"

+        android:toAlpha="1.0" />

+

+    <scale

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:duration="350"

+        android:fromXScale="0.7"

+        android:fromYScale="0.7"

+        android:pivotX="50%"

+        android:pivotY="50%"

+        android:startOffset="1700"

+        android:toXScale="1.0"

+        android:toYScale="1.0" />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_hand_main.xml b/FairphoneHome/res/anim/tutorial_edit_favs_hand_main.xml
new file mode 100644
index 0000000..384b23c
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_hand_main.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:fillAfter="true"

+    android:shareInterpolator="false" >

+

+    <translate

+        android:duration="500"

+        android:fromXDelta="50%p"

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:startOffset="300"

+        android:toXDelta="0" />

+    <translate

+        android:duration="300"

+        android:fromXDelta="0"

+        android:fromYDelta="0"

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:startOffset="1200"

+        android:toXDelta="-55"

+        android:toYDelta="-135" />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_hand_outro.xml b/FairphoneHome/res/anim/tutorial_edit_favs_hand_outro.xml
new file mode 100644
index 0000000..cf4ef4a
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_hand_outro.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:shareInterpolator="false" >

+

+    <translate

+        android:duration="700"

+        android:fromXDelta="-55"

+        android:fromYDelta="-135"

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:startOffset="100"

+        android:toXDelta="-50%p"

+        android:toYDelta="-135" />

+    

+    <alpha

+        android:duration="650"

+        android:fromAlpha="1.0"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        android:startOffset="100"

+        android:toAlpha="0.0" />

+

+    <scale

+        android:fromXScale="1.0"

+        android:fromYScale="1.0"

+        android:toXScale="8.0"

+        android:toYScale="8.0"

+        android:duration="750"

+        android:startOffset="50"

+        android:interpolator="@android:anim/accelerate_interpolator"

+        />

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_icon_blue_main.xml b/FairphoneHome/res/anim/tutorial_edit_favs_icon_blue_main.xml
new file mode 100644
index 0000000..672afc9
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_icon_blue_main.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:fillAfter="true"

+    android:shareInterpolator="false" >

+

+    <alpha

+        android:duration="100"

+        android:fromAlpha="0.0"

+        android:startOffset="1600"

+        android:toAlpha="1.0" />

+

+    <scale

+        android:duration="150"

+        android:pivotX="50%"

+        android:pivotY="50%"

+        android:fromXScale="0.6"

+        android:fromYScale="0.6"

+        android:startOffset="1600"

+        android:toXScale="1.0"

+        android:toYScale="1.0" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_icon_holder_main.xml b/FairphoneHome/res/anim/tutorial_edit_favs_icon_holder_main.xml
new file mode 100644
index 0000000..980f261
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_icon_holder_main.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:fillAfter="true"

+    android:shareInterpolator="false" >

+

+    <scale

+        android:startOffset="610"

+        android:duration="500"

+        android:fromXScale="0.7"

+        android:fromYScale="0.7"

+        android:interpolator="@android:anim/decelerate_interpolator"

+        android:pivotX="100%"

+        android:pivotY="50%"

+        android:toXScale="1.0"

+        android:toYScale="1.0" />

+

+    <alpha

+        android:startOffset="610"

+        android:duration="400"

+        android:fromAlpha="0.0"

+        android:toAlpha="1.0" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_icon_main.xml b/FairphoneHome/res/anim/tutorial_edit_favs_icon_main.xml
new file mode 100644
index 0000000..22a9b67
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_icon_main.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:fillAfter="true"

+    android:shareInterpolator="false" >

+

+    <scale

+        android:duration="150"

+        android:pivotX="50%"

+        android:pivotY="50%"

+        android:fromXScale="1.0"

+        android:fromYScale="1.0"

+        android:startOffset="1600"

+        android:toXScale="0.0"

+        android:toYScale="0.0" />

+

+    <alpha

+        android:duration="100"

+        android:fromAlpha="1.0"

+        android:startOffset="1600"

+        android:toAlpha="0.0" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_edit_favs_touch_main.xml b/FairphoneHome/res/anim/tutorial_edit_favs_touch_main.xml
new file mode 100644
index 0000000..aae8f09
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_edit_favs_touch_main.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android"

+    android:fillAfter="true"

+    android:shareInterpolator="false" >

+

+    <translate

+        android:duration="500"

+        android:fromXDelta="50%p"

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:startOffset="300"

+        android:toXDelta="0" />

+    <translate

+        android:duration="300"

+        android:fromXDelta="0"

+        android:fromYDelta="0"

+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"

+        android:startOffset="1200"

+        android:toXDelta="-55"

+        android:toYDelta="-135" />

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_intro.xml b/FairphoneHome/res/anim/tutorial_intro.xml
new file mode 100644
index 0000000..872ab7c
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_intro.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>

+<alpha xmlns:android="http://schemas.android.com/apk/res/android"

+    android:duration="300"

+    android:fromAlpha="0.0"

+    android:toAlpha="1.0" >

+

+</alpha>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_outro.xml b/FairphoneHome/res/anim/tutorial_outro.xml
new file mode 100644
index 0000000..914f353
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_outro.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>

+<alpha xmlns:android="http://schemas.android.com/apk/res/android"

+    android:duration="600"

+    android:fromAlpha="1.0"

+    android:toAlpha="0.0" >

+

+</alpha>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_title_text_intro_bottom.xml b/FairphoneHome/res/anim/tutorial_title_text_intro_bottom.xml
new file mode 100644
index 0000000..50337b4
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_title_text_intro_bottom.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+

+    <alpha

+        android:duration="500"

+        android:fromAlpha="0.0"

+        android:toAlpha="1.0" />

+

+    <translate

+        android:fromYDelta="100%"

+        android:toYDelta="0%"

+        android:duration="500"

+        android:interpolator="@android:anim/decelerate_interpolator"/>

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/anim/tutorial_title_text_intro_top.xml b/FairphoneHome/res/anim/tutorial_title_text_intro_top.xml
new file mode 100644
index 0000000..fe32b0b
--- /dev/null
+++ b/FairphoneHome/res/anim/tutorial_title_text_intro_top.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>

+<set xmlns:android="http://schemas.android.com/apk/res/android" >

+

+    <alpha

+        android:duration="500"

+        android:fromAlpha="0.0"

+        android:toAlpha="1.0" />

+

+    <translate

+        android:fromYDelta="-100%"

+        android:toYDelta="0%"

+        android:duration="500"

+        android:interpolator="@android:anim/decelerate_interpolator"/>

+

+</set>
\ No newline at end of file
diff --git a/FairphoneHome/res/color/button_app_switcher_reset_text.xml b/FairphoneHome/res/color/button_app_switcher_reset_text.xml
new file mode 100644
index 0000000..bcefd25
--- /dev/null
+++ b/FairphoneHome/res/color/button_app_switcher_reset_text.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_enabled="false" android:color="#88FFFFFF"/>
+    <item android:state_pressed="true" android:color="#FFFFFF"/>
+    <item android:color="#FFFFFF"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_background_right.png b/FairphoneHome/res/drawable-hdpi/app_switcher_background_right.png
new file mode 100644
index 0000000..5a6b26d
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_background_right.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_background_right_item.png b/FairphoneHome/res/drawable-hdpi/app_switcher_background_right_item.png
new file mode 100644
index 0000000..ee9dfe2
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_background_right_item.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_disabled.png b/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_disabled.png
new file mode 100644
index 0000000..7e98634
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_disabled.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_press.png b/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_press.png
new file mode 100644
index 0000000..b42f448
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_press.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_up.png b/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_up.png
new file mode 100644
index 0000000..a7db725
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_button_reset_up.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_divider.9.png b/FairphoneHome/res/drawable-hdpi/app_switcher_divider.9.png
new file mode 100644
index 0000000..1f305f6
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_divider.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_icon_all_apps.png b/FairphoneHome/res/drawable-hdpi/app_switcher_icon_all_apps.png
new file mode 100644
index 0000000..d765990
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_icon_all_apps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_icon_apps.png b/FairphoneHome/res/drawable-hdpi/app_switcher_icon_apps.png
new file mode 100644
index 0000000..5ef771e
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_icon_apps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_list_background.png b/FairphoneHome/res/drawable-hdpi/app_switcher_list_background.png
new file mode 100644
index 0000000..93ac865
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_list_background.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/app_switcher_separator.9.png b/FairphoneHome/res/drawable-hdpi/app_switcher_separator.9.png
new file mode 100644
index 0000000..0e9afe9
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/app_switcher_separator.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/apps_customize_bg.png b/FairphoneHome/res/drawable-hdpi/apps_customize_bg.png
new file mode 100644
index 0000000..2847467
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/apps_customize_bg.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/apps_widgets_bg.png b/FairphoneHome/res/drawable-hdpi/apps_widgets_bg.png
new file mode 100644
index 0000000..61e213d
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/apps_widgets_bg.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/appswicther_widget_icon.png b/FairphoneHome/res/drawable-hdpi/appswicther_widget_icon.png
new file mode 100644
index 0000000..1bd4df7
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/appswicther_widget_icon.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/bg_appwidget_error.9.png b/FairphoneHome/res/drawable-hdpi/bg_appwidget_error.9.png
new file mode 100644
index 0000000..4da3195
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/bg_appwidget_error.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/bg_cling1.png b/FairphoneHome/res/drawable-hdpi/bg_cling1.png
new file mode 100644
index 0000000..0e15532
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/bg_cling1.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/bg_cling2.png b/FairphoneHome/res/drawable-hdpi/bg_cling2.png
new file mode 100644
index 0000000..e65d9a2
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/bg_cling2.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/bg_cling3.png b/FairphoneHome/res/drawable-hdpi/bg_cling3.png
new file mode 100644
index 0000000..ea71fbd
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/bg_cling3.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/bg_cling4.png b/FairphoneHome/res/drawable-hdpi/bg_cling4.png
new file mode 100644
index 0000000..9403667
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/bg_cling4.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/bg_gradient.png b/FairphoneHome/res/drawable-hdpi/bg_gradient.png
new file mode 100644
index 0000000..26dcba9
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/bg_gradient.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/btn_cling_normal.9.png b/FairphoneHome/res/drawable-hdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..aea8beb
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/btn_cling_pressed.9.png b/FairphoneHome/res/drawable-hdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..ebefd20
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/cling.png b/FairphoneHome/res/drawable-hdpi/cling.png
new file mode 100644
index 0000000..d605799
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/cling.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/divider_launcher_holo.9.png b/FairphoneHome/res/drawable-hdpi/divider_launcher_holo.9.png
new file mode 100644
index 0000000..3b7f000
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edge_swipe_menu_highlight.png b/FairphoneHome/res/drawable-hdpi/edge_swipe_menu_highlight.png
new file mode 100644
index 0000000..09c5afb
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edge_swipe_menu_highlight.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_holder.png b/FairphoneHome/res/drawable-hdpi/edit_holder.png
new file mode 100644
index 0000000..01aeb64
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_holder.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_all_apps_faded.png b/FairphoneHome/res/drawable-hdpi/edit_menu_all_apps_faded.png
new file mode 100644
index 0000000..79f9193
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_all_apps_faded.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_circle.png b/FairphoneHome/res/drawable-hdpi/edit_menu_circle.png
new file mode 100644
index 0000000..eadd623
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_circle.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_circle_faded.png b/FairphoneHome/res/drawable-hdpi/edit_menu_circle_faded.png
new file mode 100644
index 0000000..d4f4e7b
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_circle_faded.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_icon_remove.png b/FairphoneHome/res/drawable-hdpi/edit_menu_icon_remove.png
new file mode 100644
index 0000000..af774c2
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_icon_remove.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_list_background.png b/FairphoneHome/res/drawable-hdpi/edit_menu_list_background.png
new file mode 100644
index 0000000..f129555
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_list_background.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_list_separator.9.png b/FairphoneHome/res/drawable-hdpi/edit_menu_list_separator.9.png
new file mode 100644
index 0000000..180ff56
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_list_separator.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_list_shadow_bottom.png b/FairphoneHome/res/drawable-hdpi/edit_menu_list_shadow_bottom.png
new file mode 100644
index 0000000..cdae1ee
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_list_shadow_bottom.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_list_shadow_top.png b/FairphoneHome/res/drawable-hdpi/edit_menu_list_shadow_top.png
new file mode 100644
index 0000000..ada0b85
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_list_shadow_top.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/edit_menu_separator.9.png b/FairphoneHome/res/drawable-hdpi/edit_menu_separator.9.png
new file mode 100644
index 0000000..d99778b
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/edit_menu_separator.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/flying_icon_bg_pressed.9.png b/FairphoneHome/res/drawable-hdpi/flying_icon_bg_pressed.9.png
new file mode 100644
index 0000000..700fadc
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/flying_icon_bg_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/focused_bg.9.png b/FairphoneHome/res/drawable-hdpi/focused_bg.9.png
new file mode 100644
index 0000000..5552708
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/focused_bg.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_edit_favs_remove_red_bg.png b/FairphoneHome/res/drawable-hdpi/fp_edit_favs_remove_red_bg.png
new file mode 100644
index 0000000..85e5b76
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_edit_favs_remove_red_bg.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_fav_icon_ring.png b/FairphoneHome/res/drawable-hdpi/fp_fav_icon_ring.png
new file mode 100644
index 0000000..f0c5ce2
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_fav_icon_ring.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_gapps_alert_background.9.png b/FairphoneHome/res/drawable-hdpi/fp_gapps_alert_background.9.png
new file mode 100644
index 0000000..6980fef
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_gapps_alert_background.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_gapps_installer_icon.png b/FairphoneHome/res/drawable-hdpi/fp_gapps_installer_icon.png
new file mode 100644
index 0000000..b20d51e
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_gapps_installer_icon.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_gapps_widget_install.png b/FairphoneHome/res/drawable-hdpi/fp_gapps_widget_install.png
new file mode 100644
index 0000000..ad0943b
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_gapps_widget_install.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_gapps_widget_uninstall.png b/FairphoneHome/res/drawable-hdpi/fp_gapps_widget_uninstall.png
new file mode 100644
index 0000000..39d11d9
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_gapps_widget_uninstall.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/fp_oobe_background.png b/FairphoneHome/res/drawable-hdpi/fp_oobe_background.png
new file mode 100644
index 0000000..d69e291
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/fp_oobe_background.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/grid_focused.9.png b/FairphoneHome/res/drawable-hdpi/grid_focused.9.png
new file mode 100644
index 0000000..f6ae267
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/grid_focused.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/grid_pressed.9.png b/FairphoneHome/res/drawable-hdpi/grid_pressed.9.png
new file mode 100644
index 0000000..cb5aea8
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/grid_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/grid_selected.9.png b/FairphoneHome/res/drawable-hdpi/grid_selected.9.png
new file mode 100644
index 0000000..add46a7
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/grid_selected.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/home_press.9.png b/FairphoneHome/res/drawable-hdpi/home_press.9.png
new file mode 100644
index 0000000..ef07011
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/home_press.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/homescreen_blue_normal_holo.9.png b/FairphoneHome/res/drawable-hdpi/homescreen_blue_normal_holo.9.png
new file mode 100644
index 0000000..2710696
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/homescreen_blue_normal_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/homescreen_blue_strong_holo.9.png b/FairphoneHome/res/drawable-hdpi/homescreen_blue_strong_holo.9.png
new file mode 100644
index 0000000..c88ef14
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/homescreen_blue_strong_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/hotseat_scrubber_holo.9.png b/FairphoneHome/res/drawable-hdpi/hotseat_scrubber_holo.9.png
new file mode 100644
index 0000000..00645c4
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/hotseat_scrubber_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/hotseat_track_holo.9.png b/FairphoneHome/res/drawable-hdpi/hotseat_track_holo.9.png
new file mode 100644
index 0000000..255add0
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/hotseat_track_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_allapps.png b/FairphoneHome/res/drawable-hdpi/ic_allapps.png
new file mode 100644
index 0000000..40d5827
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_allapps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_allapps_pressed.png b/FairphoneHome/res/drawable-hdpi/ic_allapps_pressed.png
new file mode 100644
index 0000000..6d87bbb
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_home_all_apps_holo_dark.png b/FairphoneHome/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
new file mode 100644
index 0000000..1dc02d5
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_home_search_normal_holo.png b/FairphoneHome/res/drawable-hdpi/ic_home_search_normal_holo.png
new file mode 100644
index 0000000..3f64d68
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_home_search_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_home_voice_search_holo.png b/FairphoneHome/res/drawable-hdpi/ic_home_voice_search_holo.png
new file mode 100644
index 0000000..dae5446
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_home_voice_search_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_clear_active_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_clear_active_holo.png
new file mode 100644
index 0000000..cdd0052
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_clear_active_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_clear_normal_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_clear_normal_holo.png
new file mode 100644
index 0000000..84549ff
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_clear_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_info_active_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_info_active_holo.png
new file mode 100644
index 0000000..c534e56
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_info_active_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_info_normal_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_info_normal_holo.png
new file mode 100644
index 0000000..c9bcd7f
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_info_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_market_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_market_holo.png
new file mode 100644
index 0000000..dc78251
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_market_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png
new file mode 100644
index 0000000..82b1b59
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_trashcan_active_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png b/FairphoneHome/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png
new file mode 100644
index 0000000..3fc2e83
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/ic_launcher_trashcan_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/icon_edit.png b/FairphoneHome/res/drawable-hdpi/icon_edit.png
new file mode 100644
index 0000000..13dbbe1
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/icon_edit.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_app_icon.png b/FairphoneHome/res/drawable-hdpi/oobe_app_icon.png
new file mode 100644
index 0000000..4c81e26
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_app_icon.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_app_icon_small.png b/FairphoneHome/res/drawable-hdpi/oobe_app_icon_small.png
new file mode 100644
index 0000000..a1ebcf8
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_app_icon_small.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_arrow_big.png b/FairphoneHome/res/drawable-hdpi/oobe_arrow_big.png
new file mode 100644
index 0000000..fa9e2c5
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_arrow_big.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_delete_higlight.png b/FairphoneHome/res/drawable-hdpi/oobe_delete_higlight.png
new file mode 100644
index 0000000..185d6dd
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_delete_higlight.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_delete_x.png b/FairphoneHome/res/drawable-hdpi/oobe_delete_x.png
new file mode 100644
index 0000000..27ab169
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_delete_x.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_edit_all_apps.png b/FairphoneHome/res/drawable-hdpi/oobe_edit_all_apps.png
new file mode 100644
index 0000000..b8958f7
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_edit_all_apps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_edit_drag_intro.png b/FairphoneHome/res/drawable-hdpi/oobe_edit_drag_intro.png
new file mode 100644
index 0000000..051caf6
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_edit_drag_intro.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_edit_favourite_apps.png b/FairphoneHome/res/drawable-hdpi/oobe_edit_favourite_apps.png
new file mode 100644
index 0000000..23b6cf7
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_edit_favourite_apps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_fairphone_logo.png b/FairphoneHome/res/drawable-hdpi/oobe_fairphone_logo.png
new file mode 100644
index 0000000..65a0fab
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_fairphone_logo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_hand.png b/FairphoneHome/res/drawable-hdpi/oobe_hand.png
new file mode 100644
index 0000000..6d0b3d7
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_hand.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_hand_shadow.png b/FairphoneHome/res/drawable-hdpi/oobe_hand_shadow.png
new file mode 100644
index 0000000..6b692a6
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_hand_shadow.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_icon_all_apps.png b/FairphoneHome/res/drawable-hdpi/oobe_icon_all_apps.png
new file mode 100644
index 0000000..8f84996
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_icon_all_apps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_icon_select.png b/FairphoneHome/res/drawable-hdpi/oobe_icon_select.png
new file mode 100644
index 0000000..1c4c592
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_icon_select.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_language_button_press.png b/FairphoneHome/res/drawable-hdpi/oobe_language_button_press.png
new file mode 100644
index 0000000..02b8b52
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_language_button_press.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_language_button_up.png b/FairphoneHome/res/drawable-hdpi/oobe_language_button_up.png
new file mode 100644
index 0000000..5f06269
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_language_button_up.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_menu.png b/FairphoneHome/res/drawable-hdpi/oobe_menu.png
new file mode 100644
index 0000000..f51d096
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_menu.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_selection_big.png b/FairphoneHome/res/drawable-hdpi/oobe_selection_big.png
new file mode 100644
index 0000000..2a11984
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_selection_big.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_wifi_button_press.png b/FairphoneHome/res/drawable-hdpi/oobe_wifi_button_press.png
new file mode 100644
index 0000000..511aa1f
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_wifi_button_press.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/oobe_wifi_button_up.png b/FairphoneHome/res/drawable-hdpi/oobe_wifi_button_up.png
new file mode 100644
index 0000000..02aa5ef
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/oobe_wifi_button_up.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/overscroll_glow_left.9.png b/FairphoneHome/res/drawable-hdpi/overscroll_glow_left.9.png
new file mode 100644
index 0000000..a37592d
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/overscroll_glow_left.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/overscroll_glow_right.9.png b/FairphoneHome/res/drawable-hdpi/overscroll_glow_right.9.png
new file mode 100644
index 0000000..f0f7084
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/overscroll_glow_right.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/page_hover_left_holo.9.png b/FairphoneHome/res/drawable-hdpi/page_hover_left_holo.9.png
new file mode 100644
index 0000000..2ac2c39
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/page_hover_left_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/page_hover_right_holo.9.png b/FairphoneHome/res/drawable-hdpi/page_hover_right_holo.9.png
new file mode 100644
index 0000000..4c0b1ea
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/page_hover_right_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/paged_view_indicator.9.png b/FairphoneHome/res/drawable-hdpi/paged_view_indicator.9.png
new file mode 100644
index 0000000..5b47f44
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/paged_view_indicator.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/portal_container_holo.9.png b/FairphoneHome/res/drawable-hdpi/portal_container_holo.9.png
new file mode 100644
index 0000000..557ee5a
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/portal_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/portal_ring_inner_holo.png b/FairphoneHome/res/drawable-hdpi/portal_ring_inner_holo.png
new file mode 100644
index 0000000..e953221
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/portal_ring_inner_nolip_holo.png b/FairphoneHome/res/drawable-hdpi/portal_ring_inner_nolip_holo.png
new file mode 100644
index 0000000..257fc69
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/portal_ring_inner_nolip_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/portal_ring_outer_holo.png b/FairphoneHome/res/drawable-hdpi/portal_ring_outer_holo.png
new file mode 100644
index 0000000..2bf0c0d
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/portal_ring_rest.png b/FairphoneHome/res/drawable-hdpi/portal_ring_rest.png
new file mode 100644
index 0000000..93e3f6b
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/portal_ring_rest.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/search_frame.9.png b/FairphoneHome/res/drawable-hdpi/search_frame.9.png
new file mode 100644
index 0000000..15ca1f4
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/search_frame.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/swipe_menu_shadow_bottom.png b/FairphoneHome/res/drawable-hdpi/swipe_menu_shadow_bottom.png
new file mode 100644
index 0000000..05095d7
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/swipe_menu_shadow_bottom.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/swipe_menu_shadow_top.png b/FairphoneHome/res/drawable-hdpi/swipe_menu_shadow_top.png
new file mode 100644
index 0000000..8a6acd5
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/swipe_menu_shadow_top.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_selected_focused_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..673e3bf
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_selected_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..d57df98
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..4b312d9
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..6278eef
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..294991d
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_unselected_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..19532ab
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..5140b35
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/FairphoneHome/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..aadc6f8
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_container_holo.9.png b/FairphoneHome/res/drawable-hdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..8c15a7c
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_preview_tile.png b/FairphoneHome/res/drawable-hdpi/widget_preview_tile.png
new file mode 100644
index 0000000..caeddd1
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_preview_tile.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_resize_frame_holo.9.png b/FairphoneHome/res/drawable-hdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..059a9d6
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_resize_handle_bottom.png b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..bc4418f
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_resize_handle_left.png b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..b808170
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_resize_handle_right.png b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..bcb8104
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/widget_resize_handle_top.png b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..3ec18de
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-hdpi/workspace_bg.9.png b/FairphoneHome/res/drawable-hdpi/workspace_bg.9.png
new file mode 100644
index 0000000..5bbfa4f
--- /dev/null
+++ b/FairphoneHome/res/drawable-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/app_switcher_icon_sync.png b/FairphoneHome/res/drawable-mdpi/app_switcher_icon_sync.png
new file mode 100644
index 0000000..605768a
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/app_switcher_icon_sync.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/apps_customize_bg.png b/FairphoneHome/res/drawable-mdpi/apps_customize_bg.png
new file mode 100644
index 0000000..2847467
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/apps_customize_bg.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/bg_appwidget_error.9.png b/FairphoneHome/res/drawable-mdpi/bg_appwidget_error.9.png
new file mode 100644
index 0000000..493c0d4
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/bg_appwidget_error.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/bg_cling1.png b/FairphoneHome/res/drawable-mdpi/bg_cling1.png
new file mode 100644
index 0000000..f284412
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/bg_cling1.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/bg_cling2.png b/FairphoneHome/res/drawable-mdpi/bg_cling2.png
new file mode 100644
index 0000000..0052dc2
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/bg_cling2.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/bg_cling3.png b/FairphoneHome/res/drawable-mdpi/bg_cling3.png
new file mode 100644
index 0000000..fabdf7a
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/bg_cling3.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/bg_cling4.png b/FairphoneHome/res/drawable-mdpi/bg_cling4.png
new file mode 100644
index 0000000..2f152f4
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/bg_cling4.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/bg_cling5.png b/FairphoneHome/res/drawable-mdpi/bg_cling5.png
new file mode 100644
index 0000000..e094809
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/bg_cling5.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/btn_cling_normal.9.png b/FairphoneHome/res/drawable-mdpi/btn_cling_normal.9.png
new file mode 100644
index 0000000..43a407e
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/btn_cling_normal.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/btn_cling_pressed.9.png b/FairphoneHome/res/drawable-mdpi/btn_cling_pressed.9.png
new file mode 100644
index 0000000..bf0c8cb
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/btn_cling_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/cling.png b/FairphoneHome/res/drawable-mdpi/cling.png
new file mode 100644
index 0000000..fba3a07
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/cling.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/divider_launcher_holo.9.png b/FairphoneHome/res/drawable-mdpi/divider_launcher_holo.9.png
new file mode 100644
index 0000000..7bdf323
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/flying_icon_bg_pressed.9.png b/FairphoneHome/res/drawable-mdpi/flying_icon_bg_pressed.9.png
new file mode 100644
index 0000000..fb74449
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/flying_icon_bg_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/focused_bg.9.png b/FairphoneHome/res/drawable-mdpi/focused_bg.9.png
new file mode 100644
index 0000000..00f05d8
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/focused_bg.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/fp_wallpaper_default.png b/FairphoneHome/res/drawable-mdpi/fp_wallpaper_default.png
new file mode 100644
index 0000000..c51af2d
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/fp_wallpaper_default.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/grid_focused.9.png b/FairphoneHome/res/drawable-mdpi/grid_focused.9.png
new file mode 100644
index 0000000..6660a8c
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/grid_focused.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/grid_pressed.9.png b/FairphoneHome/res/drawable-mdpi/grid_pressed.9.png
new file mode 100644
index 0000000..c7e6b06
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/grid_pressed.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/grid_selected.9.png b/FairphoneHome/res/drawable-mdpi/grid_selected.9.png
new file mode 100644
index 0000000..e2732b7
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/grid_selected.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/hand.png b/FairphoneHome/res/drawable-mdpi/hand.png
new file mode 100644
index 0000000..fe5a035
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/hand.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/home_press.9.png b/FairphoneHome/res/drawable-mdpi/home_press.9.png
new file mode 100644
index 0000000..679a1f6
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/home_press.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/homescreen_blue_normal_holo.9.png b/FairphoneHome/res/drawable-mdpi/homescreen_blue_normal_holo.9.png
new file mode 100644
index 0000000..efdc861
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/homescreen_blue_normal_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/homescreen_blue_strong_holo.9.png b/FairphoneHome/res/drawable-mdpi/homescreen_blue_strong_holo.9.png
new file mode 100644
index 0000000..e3edb64
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/homescreen_blue_strong_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/hotseat_scrubber_holo.9.png b/FairphoneHome/res/drawable-mdpi/hotseat_scrubber_holo.9.png
new file mode 100644
index 0000000..1b335d8
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/hotseat_scrubber_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/hotseat_track_holo.9.png b/FairphoneHome/res/drawable-mdpi/hotseat_track_holo.9.png
new file mode 100644
index 0000000..168f092
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/hotseat_track_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_allapps.png b/FairphoneHome/res/drawable-mdpi/ic_allapps.png
new file mode 100644
index 0000000..a3cce14
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_allapps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_allapps_pressed.png b/FairphoneHome/res/drawable-mdpi/ic_allapps_pressed.png
new file mode 100644
index 0000000..5c2076f
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_home_all_apps_holo_dark.png b/FairphoneHome/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
new file mode 100644
index 0000000..84fa594
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_home_search_normal_holo.png b/FairphoneHome/res/drawable-mdpi/ic_home_search_normal_holo.png
new file mode 100644
index 0000000..7367c38
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_home_search_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_home_voice_search_holo.png b/FairphoneHome/res/drawable-mdpi/ic_home_voice_search_holo.png
new file mode 100644
index 0000000..f211a7b
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_home_voice_search_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_clear_active_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_clear_active_holo.png
new file mode 100644
index 0000000..2683bea
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_clear_active_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_clear_normal_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_clear_normal_holo.png
new file mode 100644
index 0000000..219f3e5
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_clear_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_info_active_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_info_active_holo.png
new file mode 100644
index 0000000..f84b4a6
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_info_active_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_info_normal_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_info_normal_holo.png
new file mode 100644
index 0000000..eac578f
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_info_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_market_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_market_holo.png
new file mode 100644
index 0000000..cacb374
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_market_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png
new file mode 100644
index 0000000..0350e55
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_trashcan_active_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png b/FairphoneHome/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png
new file mode 100644
index 0000000..799b62f
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/ic_launcher_trashcan_normal_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/overscroll_glow_left.9.png b/FairphoneHome/res/drawable-mdpi/overscroll_glow_left.9.png
new file mode 100644
index 0000000..897e63d
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/overscroll_glow_left.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/overscroll_glow_right.9.png b/FairphoneHome/res/drawable-mdpi/overscroll_glow_right.9.png
new file mode 100644
index 0000000..dc6ecac
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/overscroll_glow_right.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/page_hover_left_holo.9.png b/FairphoneHome/res/drawable-mdpi/page_hover_left_holo.9.png
new file mode 100644
index 0000000..e1e84c9
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/page_hover_left_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/page_hover_right_holo.9.png b/FairphoneHome/res/drawable-mdpi/page_hover_right_holo.9.png
new file mode 100644
index 0000000..894c263
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/page_hover_right_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/paged_view_indicator.9.png b/FairphoneHome/res/drawable-mdpi/paged_view_indicator.9.png
new file mode 100644
index 0000000..647b60f
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/paged_view_indicator.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/portal_container_holo.9.png b/FairphoneHome/res/drawable-mdpi/portal_container_holo.9.png
new file mode 100644
index 0000000..9a47517
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/portal_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/portal_ring_inner_holo.png b/FairphoneHome/res/drawable-mdpi/portal_ring_inner_holo.png
new file mode 100644
index 0000000..3d704af
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/portal_ring_inner_nolip_holo.png b/FairphoneHome/res/drawable-mdpi/portal_ring_inner_nolip_holo.png
new file mode 100644
index 0000000..1dbdbe8
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/portal_ring_inner_nolip_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/portal_ring_outer_holo.png b/FairphoneHome/res/drawable-mdpi/portal_ring_outer_holo.png
new file mode 100644
index 0000000..3a7303e
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/portal_ring_rest.png b/FairphoneHome/res/drawable-mdpi/portal_ring_rest.png
new file mode 100644
index 0000000..259e48c
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/portal_ring_rest.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/search_frame.9.png b/FairphoneHome/res/drawable-mdpi/search_frame.9.png
new file mode 100644
index 0000000..058905b
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/search_frame.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_selected_focused_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..c9972e7
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_selected_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..587337c
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..284f534
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..155c4fc
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..f0cecd1
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_unselected_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..a2dbf42
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
new file mode 100644
index 0000000..f1a2819
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/FairphoneHome/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..b1223fe
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_container_holo.9.png b/FairphoneHome/res/drawable-mdpi/widget_container_holo.9.png
new file mode 100644
index 0000000..db24457
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_container_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_preview_tile.png b/FairphoneHome/res/drawable-mdpi/widget_preview_tile.png
new file mode 100644
index 0000000..9c7c4f7
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_preview_tile.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_resize_frame_holo.9.png b/FairphoneHome/res/drawable-mdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..435f3aa
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_resize_handle_bottom.png b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..848af0a
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_resize_handle_left.png b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..0e62c9c
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_resize_handle_right.png b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..5c8d477
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/widget_resize_handle_top.png b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..609e06b
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-mdpi/workspace_bg.9.png b/FairphoneHome/res/drawable-mdpi/workspace_bg.9.png
new file mode 100644
index 0000000..2856e09
--- /dev/null
+++ b/FairphoneHome/res/drawable-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/background.png b/FairphoneHome/res/drawable-nodpi/background.png
new file mode 100644
index 0000000..ff634a4
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/background.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/edit_text.png b/FairphoneHome/res/drawable-nodpi/edit_text.png
new file mode 100644
index 0000000..ff9b883
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/edit_text.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_fav_background.png b/FairphoneHome/res/drawable-nodpi/fp_fav_background.png
new file mode 100644
index 0000000..f1290f2
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_fav_background.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_fav_icon_ring.png b/FairphoneHome/res/drawable-nodpi/fp_fav_icon_ring.png
new file mode 100644
index 0000000..fb69432
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_fav_icon_ring.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_company.png b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_company.png
new file mode 100644
index 0000000..355a549
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_company.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_company_small.png b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_company_small.png
new file mode 100644
index 0000000..0e6ea33
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_company_small.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1.jpg
new file mode 100644
index 0000000..3ceaa4f
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_blue.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_blue.jpg
new file mode 100644
index 0000000..87bc756
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_blue.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_blue_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_blue_small.jpg
new file mode 100644
index 0000000..7d4f79c
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_blue_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_pink.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_pink.jpg
new file mode 100644
index 0000000..6240d8f
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_pink.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_pink_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_pink_small.jpg
new file mode 100644
index 0000000..6e87381
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_pink_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_small.jpg
new file mode 100644
index 0000000..c3dc669
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_1_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_2.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_2.jpg
new file mode 100644
index 0000000..27bd8ec
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_2.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_2_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_2_small.jpg
new file mode 100644
index 0000000..3f3a272
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_2_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_3.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_3.jpg
new file mode 100644
index 0000000..ad448d4
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_3.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_3_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_3_small.jpg
new file mode 100644
index 0000000..68c1b55
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_3_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4.jpg
new file mode 100644
index 0000000..bf99b10
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_blue.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_blue.jpg
new file mode 100644
index 0000000..9deeeee
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_blue.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_blue_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_blue_small.jpg
new file mode 100644
index 0000000..6c83dc4
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_blue_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_pink.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_pink.jpg
new file mode 100644
index 0000000..8fdcd35
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_pink.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_pink_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_pink_small.jpg
new file mode 100644
index 0000000..2f9c649
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_pink_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_small.jpg
new file mode 100644
index 0000000..d3b8b2d
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_4_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5.jpg
new file mode 100644
index 0000000..3d9a5da
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_blue.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_blue.jpg
new file mode 100644
index 0000000..5c7be43
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_blue.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_blue_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_blue_small.jpg
new file mode 100644
index 0000000..8b8c4e2
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_blue_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_pink.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_pink.jpg
new file mode 100644
index 0000000..416bfad
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_pink.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_pink_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_pink_small.jpg
new file mode 100644
index 0000000..78bb43f
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_pink_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_small.jpg
new file mode 100644
index 0000000..f9fe3fe
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_5_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_6.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_6.jpg
new file mode 100644
index 0000000..7d9b9c2
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_6.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_6_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_6_small.jpg
new file mode 100644
index 0000000..a50e77f
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_crystal_6_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_default.png b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_default.png
new file mode 100644
index 0000000..c51af2d
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_default.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_default_small.png b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_default_small.png
new file mode 100644
index 0000000..f635848
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_default_small.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_mine_5_blue.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_mine_5_blue.jpg
new file mode 100644
index 0000000..6d10337
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_mine_5_blue.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_mine_5_blue_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_mine_5_blue_small.jpg
new file mode 100644
index 0000000..f30e1c8
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_mine_5_blue_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1.jpg
new file mode 100644
index 0000000..b31a05f
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_pink.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_pink.jpg
new file mode 100644
index 0000000..bbf54b5
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_pink.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_pink_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_pink_small.jpg
new file mode 100644
index 0000000..f68d650
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_pink_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_small.jpg
new file mode 100644
index 0000000..17d2cf3
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_1_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_2.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_2.jpg
new file mode 100644
index 0000000..5371786
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_2.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_2_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_2_small.jpg
new file mode 100644
index 0000000..58b6159
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_2_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_3.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_3.jpg
new file mode 100644
index 0000000..a2c187b
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_3.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_3_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_3_small.jpg
new file mode 100644
index 0000000..79832b6
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_3_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4.jpg
new file mode 100644
index 0000000..bb9e24b
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_pink.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_pink.jpg
new file mode 100644
index 0000000..affccd9
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_pink.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_pink_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_pink_small.jpg
new file mode 100644
index 0000000..2eabc1b
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_pink_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_small.jpg
new file mode 100644
index 0000000..b40e847
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_4_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_5.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_5.jpg
new file mode 100644
index 0000000..23b86d4
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_5.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_5_small.jpg b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_5_small.jpg
new file mode 100644
index 0000000..9e28b95
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/fp_wallpaper_sun_5_small.jpg
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/icon_all_apps.png b/FairphoneHome/res/drawable-nodpi/icon_all_apps.png
new file mode 100644
index 0000000..c0298cb
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/icon_all_apps.png
Binary files differ
diff --git a/FairphoneHome/res/drawable-nodpi/icon_clean.png b/FairphoneHome/res/drawable-nodpi/icon_clean.png
new file mode 100644
index 0000000..ff91225
--- /dev/null
+++ b/FairphoneHome/res/drawable-nodpi/icon_clean.png
Binary files differ
diff --git a/FairphoneHome/res/drawable/all_apps_button_icon.xml b/FairphoneHome/res/drawable/all_apps_button_icon.xml
new file mode 100644
index 0000000..7c69cad
--- /dev/null
+++ b/FairphoneHome/res/drawable/all_apps_button_icon.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:drawable="@drawable/ic_allapps_pressed" />
+    <item android:state_pressed="true" android:drawable="@drawable/ic_allapps_pressed" />
+    <item android:drawable="@drawable/ic_allapps" />
+</selector>
diff --git a/FairphoneHome/res/drawable/app_placeholder_blue_icon.xml b/FairphoneHome/res/drawable/app_placeholder_blue_icon.xml
new file mode 100644
index 0000000..31f37c1
--- /dev/null
+++ b/FairphoneHome/res/drawable/app_placeholder_blue_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>

+<shape xmlns:android="http://schemas.android.com/apk/res/android"

+    android:shape="oval" >

+

+    <solid android:color="#7F11a5e2" />

+

+</shape>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/app_placeholder_icon.xml b/FairphoneHome/res/drawable/app_placeholder_icon.xml
new file mode 100644
index 0000000..920bbd0
--- /dev/null
+++ b/FairphoneHome/res/drawable/app_placeholder_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>

+<shape xmlns:android="http://schemas.android.com/apk/res/android"

+    android:shape="oval" >

+

+    <solid android:color="#33ffffff" />

+

+</shape>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/button_app_switcher_reset.xml b/FairphoneHome/res/drawable/button_app_switcher_reset.xml
new file mode 100644
index 0000000..d532696
--- /dev/null
+++ b/FairphoneHome/res/drawable/button_app_switcher_reset.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/app_switcher_button_reset_disabled" android:state_enabled="false"/>
+    <item android:drawable="@drawable/app_switcher_button_reset_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/app_switcher_button_reset_up"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/button_last_used_app.xml b/FairphoneHome/res/drawable/button_last_used_app.xml
new file mode 100644
index 0000000..1322d1e
--- /dev/null
+++ b/FairphoneHome/res/drawable/button_last_used_app.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/app_switcher_button_reset_press" android:state_pressed="true"/>
+    <item android:drawable="@color/transparent"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/cling_button_bg.xml b/FairphoneHome/res/drawable/cling_button_bg.xml
new file mode 100644
index 0000000..3809cde
--- /dev/null
+++ b/FairphoneHome/res/drawable/cling_button_bg.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@drawable/btn_cling_pressed" />
+    <item android:drawable="@drawable/btn_cling_normal" />
+</selector>
diff --git a/FairphoneHome/res/drawable/fairphone_fav_menu_background.xml b/FairphoneHome/res/drawable/fairphone_fav_menu_background.xml
new file mode 100644
index 0000000..70fa20b
--- /dev/null
+++ b/FairphoneHome/res/drawable/fairphone_fav_menu_background.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>

+<shape xmlns:android="http://schemas.android.com/apk/res/android"

+    android:innerRadius="100dp"

+    android:shape="ring"

+    android:thickness="100dp"

+    android:useLevel="false" >

+

+    <solid android:color="#80000000" />

+

+    <padding

+        android:left="20px"

+        android:top="20px"

+        android:right="20px"

+        android:bottom="20px"/>

+

+</shape>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/flying_icon_bg.xml b/FairphoneHome/res/drawable/flying_icon_bg.xml
new file mode 100644
index 0000000..167c3ba
--- /dev/null
+++ b/FairphoneHome/res/drawable/flying_icon_bg.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@drawable/flying_icon_bg_pressed" />
+    <item android:drawable="@android:color/transparent" />
+</selector>
diff --git a/FairphoneHome/res/drawable/focusable_view_bg.xml b/FairphoneHome/res/drawable/focusable_view_bg.xml
new file mode 100644
index 0000000..66661e2
--- /dev/null
+++ b/FairphoneHome/res/drawable/focusable_view_bg.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
+</selector>
diff --git a/FairphoneHome/res/drawable/fp_gaaps_alert_button.xml b/FairphoneHome/res/drawable/fp_gaaps_alert_button.xml
new file mode 100644
index 0000000..03208b7
--- /dev/null
+++ b/FairphoneHome/res/drawable/fp_gaaps_alert_button.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@color/google_blue" android:state_pressed="true"/>
+    <item android:drawable="@color/transparent"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/fp_gapps_progress.xml b/FairphoneHome/res/drawable/fp_gapps_progress.xml
new file mode 100644
index 0000000..a1d5afe
--- /dev/null
+++ b/FairphoneHome/res/drawable/fp_gapps_progress.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="@color/google_progressbar_grey" />
+        </shape>
+    </item>
+    <item android:id="@android:id/secondaryProgress">
+        <clip android:drawable="@color/google_blue" />
+    </item>
+    <item android:id="@android:id/progress">
+        <clip android:drawable="@color/google_blue" />
+    </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/info_target_selector.xml b/FairphoneHome/res/drawable/info_target_selector.xml
new file mode 100644
index 0000000..f3a7016
--- /dev/null
+++ b/FairphoneHome/res/drawable/info_target_selector.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, 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.
+*/
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_launcher_info_normal_holo"  />
+    <item android:drawable="@drawable/ic_launcher_info_active_holo"  />
+</transition>
diff --git a/FairphoneHome/res/drawable/oobe_language_button.xml b/FairphoneHome/res/drawable/oobe_language_button.xml
new file mode 100644
index 0000000..4825df9
--- /dev/null
+++ b/FairphoneHome/res/drawable/oobe_language_button.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/oobe_language_button_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/oobe_language_button_up"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/oobe_wifi_button.xml b/FairphoneHome/res/drawable/oobe_wifi_button.xml
new file mode 100644
index 0000000..e25e59e
--- /dev/null
+++ b/FairphoneHome/res/drawable/oobe_wifi_button.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/oobe_wifi_button_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/oobe_wifi_button_up"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/remove_target_selector.xml b/FairphoneHome/res/drawable/remove_target_selector.xml
new file mode 100644
index 0000000..5e071fb
--- /dev/null
+++ b/FairphoneHome/res/drawable/remove_target_selector.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_launcher_clear_normal_holo"  />
+    <item android:drawable="@drawable/ic_launcher_clear_active_holo"  />
+</transition>
diff --git a/FairphoneHome/res/drawable/tab_widget_indicator_selector.xml b/FairphoneHome/res/drawable/tab_widget_indicator_selector.xml
new file mode 100644
index 0000000..d06f757
--- /dev/null
+++ b/FairphoneHome/res/drawable/tab_widget_indicator_selector.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Non focused states -->
+    <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_holo" />
+
+    <!-- Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused_holo" />
+    <item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_holo" />
+
+    <!-- Pressed -->
+    <!--    Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_holo" />
+    <item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_holo" />
+
+    <!--    Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_focused_holo" />
+    <item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_focused_holo" />
+</selector>
diff --git a/FairphoneHome/res/drawable/uninstall_target_selector.xml b/FairphoneHome/res/drawable/uninstall_target_selector.xml
new file mode 100644
index 0000000..229942e
--- /dev/null
+++ b/FairphoneHome/res/drawable/uninstall_target_selector.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_launcher_trashcan_normal_holo"  />
+    <item android:drawable="@drawable/ic_launcher_trashcan_active_holo"  />
+</transition>
diff --git a/FairphoneHome/res/drawable/wallpaper_gallery_background.xml b/FairphoneHome/res/drawable/wallpaper_gallery_background.xml
new file mode 100644
index 0000000..271c1df
--- /dev/null
+++ b/FairphoneHome/res/drawable/wallpaper_gallery_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient android:startColor="#0000" android:endColor="#D0000000"
+            android:angle="270"/>
+</shape>
\ No newline at end of file
diff --git a/FairphoneHome/res/drawable/wallpaper_gallery_item.xml b/FairphoneHome/res/drawable/wallpaper_gallery_item.xml
new file mode 100644
index 0000000..b7052bd
--- /dev/null
+++ b/FairphoneHome/res/drawable/wallpaper_gallery_item.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:drawable="@drawable/grid_focused" />
+    <item android:state_pressed="true" android:drawable="@drawable/grid_pressed" />
+    <item android:state_selected="true" android:drawable="@drawable/grid_selected" />
+    <item android:drawable="@android:color/transparent" />
+</selector>
diff --git a/FairphoneHome/res/layout-de/fp_google_apps_installer_widget.xml b/FairphoneHome/res/layout-de/fp_google_apps_installer_widget.xml
new file mode 100644
index 0000000..e5cc8bb
--- /dev/null
+++ b/FairphoneHome/res/layout-de/fp_google_apps_installer_widget.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

+    android:id="@+id/googleAppsIntallerMain"

+    android:layout_width="wrap_content"

+    android:layout_height="wrap_content" >

+

+    <FrameLayout

+        android:id="@+id/installGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/installButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_install" />

+

+        <TextView

+            android:id="@+id/installText"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:text="@string/google_apps_initial_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18sp" />

+    </FrameLayout>

+

+    <LinearLayout

+        android:id="@+id/popupDisclaimerGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_title"

+            android:textColor="@color/google_blue"

+            android:ellipsize="marquee"

+            android:marqueeRepeatLimit="marquee_forever"

+            android:scrollHorizontally="true" 

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/disclaimerCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/disclaimerOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupFailedDownloadGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/failedDownloadCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/failedDownloadOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupProgressGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/progressDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:gravity="center_vertical" 

+            android:maxLines="2" 

+            android:ellipsize="end"

+            android:paddingLeft="10dp"

+            android:paddingTop="5dp"

+            android:paddingBottom="5dp"

+            android:textColor="@color/google_blue"

+            android:textSize="16sp" />

+

+        <ProgressBar

+            android:id="@+id/progressBar"

+            android:layout_width="match_parent"

+            android:layout_height="2dp"

+            android:layout_marginBottom="35dp"

+            android:layout_marginLeft="15dp"

+            android:layout_marginRight="15dp"

+            android:layout_marginTop="35dp"

+            android:indeterminate="false"

+            android:indeterminateOnly="false"

+            android:max="100"

+            android:padding="0dp"

+            android:progressDrawable="@drawable/fp_gapps_progress" />

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupRebootGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/rebootDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+            

+            <Button

+                android:id="@+id/rebootOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupPermissionsGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/permissionsDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_title"

+            android:textColor="@color/google_blue"

+            android:textSize="15sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+

+            <Button

+                android:id="@+id/permissionsOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <FrameLayout

+        android:id="@+id/uninstallGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/uninstallButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_uninstall" />

+

+        <LinearLayout

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:orientation="vertical" >

+

+            <TextView

+                android:id="@+id/uninstallTitle"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:text="@string/google_apps_uninstall_title"

+                android:textColor="#c8c8c8"

+                android:textSize="13.3dp" />

+

+            <TextView

+                android:id="@+id/uninstallText"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:layout_gravity="center_vertical"

+                android:text="@string/google_apps_uninstall_description"

+                android:textColor="#c8c8c8"

+                android:textSize="18.5sp" />

+        </LinearLayout>

+    </FrameLayout>

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout-fr/fp_google_apps_installer_widget.xml b/FairphoneHome/res/layout-fr/fp_google_apps_installer_widget.xml
new file mode 100644
index 0000000..c85d68f
--- /dev/null
+++ b/FairphoneHome/res/layout-fr/fp_google_apps_installer_widget.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

+    android:id="@+id/googleAppsIntallerMain"

+    android:layout_width="wrap_content"

+    android:layout_height="wrap_content" >

+

+    <FrameLayout

+        android:id="@+id/installGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/installButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_install" />

+

+        <TextView

+            android:id="@+id/installText"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:text="@string/google_apps_initial_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18sp" />

+    </FrameLayout>

+

+    <LinearLayout

+        android:id="@+id/popupDisclaimerGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_title"

+            android:textColor="@color/google_blue"

+            android:ellipsize="marquee"

+            android:marqueeRepeatLimit="marquee_forever"

+            android:scrollHorizontally="true" 

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/disclaimerCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/disclaimerOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupFailedDownloadGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/failedDownloadCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/failedDownloadOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupProgressGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/progressDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:gravity="center_vertical"

+            android:maxLines="2" 

+            android:ellipsize="end"

+            android:paddingLeft="10dp"

+            android:paddingTop="5dp"

+            android:paddingBottom="5dp"

+            android:textColor="@color/google_blue"

+            android:textSize="16sp" />

+

+        <ProgressBar

+            android:id="@+id/progressBar"

+            android:layout_width="match_parent"

+            android:layout_height="2dp"

+            android:layout_marginBottom="35dp"

+            android:layout_marginLeft="15dp"

+            android:layout_marginRight="15dp"

+            android:layout_marginTop="35dp"

+            android:indeterminate="false"

+            android:indeterminateOnly="false"

+            android:max="100"

+            android:padding="0dp"

+            android:progressDrawable="@drawable/fp_gapps_progress" />

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupRebootGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/rebootDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+            

+            <Button

+                android:id="@+id/rebootOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupPermissionsGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/permissionsDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+

+            <Button

+                android:id="@+id/permissionsOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <FrameLayout

+        android:id="@+id/uninstallGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/uninstallButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_uninstall" />

+

+        <LinearLayout

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:orientation="vertical" >

+

+            <TextView

+                android:id="@+id/uninstallTitle"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:text="@string/google_apps_uninstall_title"

+                android:textColor="#c8c8c8"

+                android:textSize="13.3dp" />

+

+            <TextView

+                android:id="@+id/uninstallText"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:layout_gravity="center_vertical"

+                android:text="@string/google_apps_uninstall_description"

+                android:textColor="#c8c8c8"

+                android:textSize="17.5sp" />

+        </LinearLayout>

+    </FrameLayout>

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout-nl/fp_google_apps_installer_widget.xml b/FairphoneHome/res/layout-nl/fp_google_apps_installer_widget.xml
new file mode 100644
index 0000000..d242f48
--- /dev/null
+++ b/FairphoneHome/res/layout-nl/fp_google_apps_installer_widget.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

+    android:id="@+id/googleAppsIntallerMain"

+    android:layout_width="wrap_content"

+    android:layout_height="wrap_content" >

+

+    <FrameLayout

+        android:id="@+id/installGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/installButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_install" />

+

+        <TextView

+            android:id="@+id/installText"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:text="@string/google_apps_initial_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18sp" />

+    </FrameLayout>

+

+    <LinearLayout

+        android:id="@+id/popupDisclaimerGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_title"

+            android:textColor="@color/google_blue"

+            android:ellipsize="marquee"

+            android:marqueeRepeatLimit="marquee_forever"

+            android:scrollHorizontally="true" 

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/disclaimerCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/disclaimerOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupFailedDownloadGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/failedDownloadCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/failedDownloadOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupProgressGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/progressDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:gravity="center_vertical"

+            android:maxLines="2" 

+            android:ellipsize="end"

+            android:paddingLeft="10dp"

+            android:paddingTop="5dp"

+            android:paddingBottom="5dp"

+            android:textColor="@color/google_blue"

+            android:textSize="16sp" />

+

+        <ProgressBar

+            android:id="@+id/progressBar"

+            android:layout_width="match_parent"

+            android:layout_height="2dp"

+            android:layout_marginBottom="35dp"

+            android:layout_marginLeft="15dp"

+            android:layout_marginRight="15dp"

+            android:layout_marginTop="35dp"

+            android:indeterminate="false"

+            android:indeterminateOnly="false"

+            android:max="100"

+            android:padding="0dp"

+            android:progressDrawable="@drawable/fp_gapps_progress" />

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupRebootGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/rebootDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_title"

+            android:textColor="@color/google_blue"

+            android:textSize="17sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+            

+            <Button

+                android:id="@+id/rebootOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupPermissionsGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/permissionsDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_title"

+            android:textColor="@color/google_blue"

+            android:textSize="15sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+

+            <Button

+                android:id="@+id/permissionsOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <FrameLayout

+        android:id="@+id/uninstallGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/uninstallButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_uninstall" />

+

+        <LinearLayout

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:orientation="vertical" >

+

+            <TextView

+                android:id="@+id/uninstallTitle"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:text="@string/google_apps_uninstall_title"

+                android:textColor="#c8c8c8"

+                android:textSize="13.3dp" />

+

+            <TextView

+                android:id="@+id/uninstallText"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:layout_gravity="center_vertical"

+                android:text="@string/google_apps_uninstall_description"

+                android:textColor="#c8c8c8"

+                android:textSize="18.5sp" />

+        </LinearLayout>

+    </FrameLayout>

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/add_list_item.xml b/FairphoneHome/res/layout/add_list_item.xml
new file mode 100644
index 0000000..e937d7b
--- /dev/null
+++ b/FairphoneHome/res/layout/add_list_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:textAppearance="?android:attr/textAppearanceLarge"
+    android:gravity="center_vertical"
+    android:drawablePadding="14dip"
+    android:paddingLeft="15dip"
+    android:paddingRight="15dip" />
diff --git a/FairphoneHome/res/layout/all_apps_cling.xml b/FairphoneHome/res/layout/all_apps_cling.xml
new file mode 100644
index 0000000..de725f9
--- /dev/null
+++ b/FairphoneHome/res/layout/all_apps_cling.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<org.fairphone.launcher.Cling
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    launcher:drawIdentifier="all_apps_portrait">
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="20dp"
+        android:layout_marginTop="20dp">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <TextView
+                style="@style/ClingTitleText"
+                android:id="@+id/all_apps_cling_title"
+                android:text="@string/all_apps_cling_title" />
+            <TextView
+                style="@style/ClingText"
+                android:id="@+id/all_apps_cling_add_item"
+                android:layout_width="285dp"
+                android:layout_height="wrap_content"
+                android:text="@string/all_apps_cling_add_item" />
+        </LinearLayout>
+    </FrameLayout>
+    <Button
+        style="@style/ClingButton"
+        android:id="@+id/cling_dismiss"
+        android:layout_marginBottom="15dp"
+        android:layout_marginRight="10dp"
+        android:layout_gravity="bottom|right"
+        android:onClick="dismissAllAppsCling" />
+</org.fairphone.launcher.Cling>
diff --git a/FairphoneHome/res/layout/application.xml b/FairphoneHome/res/layout/application.xml
new file mode 100644
index 0000000..64b8388
--- /dev/null
+++ b/FairphoneHome/res/layout/application.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<org.fairphone.launcher.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
+   style="@style/WorkspaceIcon.Portrait"
+   android:focusable="true"
+   android:background="@drawable/focusable_view_bg" />
diff --git a/FairphoneHome/res/layout/apps_customize_application.xml b/FairphoneHome/res/layout/apps_customize_application.xml
new file mode 100644
index 0000000..2e49960
--- /dev/null
+++ b/FairphoneHome/res/layout/apps_customize_application.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<org.fairphone.launcher.PagedViewIcon
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+
+    style="@style/WorkspaceIcon.Portrait.AppsCustomize"
+
+    android:id="@+id/application_icon"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal"
+
+    android:focusable="true"
+    android:background="@drawable/focusable_view_bg" />
diff --git a/FairphoneHome/res/layout/apps_customize_pane.xml b/FairphoneHome/res/layout/apps_customize_pane.xml
new file mode 100644
index 0000000..c24a935
--- /dev/null
+++ b/FairphoneHome/res/layout/apps_customize_pane.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+     
+     android:background="#FF000000"
+-->
+<org.fairphone.launcher.AppsCustomizeTabHost
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    android:background="@drawable/apps_widgets_bg"
+    >
+    <LinearLayout
+        android:id="@+id/apps_customize_content"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        android:layoutDirection="ltr">
+        <!-- The layout_width of the tab bar gets overriden to align the content
+             with the text in the tabs in AppsCustomizeTabHost. -->
+        <FrameLayout
+            android:id="@+id/tabs_container"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/apps_customize_tab_bar_height"
+            android:layout_marginTop="@dimen/apps_customize_tab_bar_margin_top"
+            android:layout_gravity="center_horizontal">
+            <org.fairphone.launcher.FocusOnlyTabWidget
+                android:id="@android:id/tabs"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="left"
+                android:background="@drawable/tab_unselected_holo"
+                android:tabStripEnabled="false"
+                android:divider="@null" />
+            <include
+                android:id="@+id/market_button"
+                layout="@layout/market_button"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="right" />
+        </FrameLayout>
+        <FrameLayout
+            android:id="@android:id/tabcontent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <org.fairphone.launcher.AppsCustomizePagedView
+                android:id="@+id/apps_customize_pane_content"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                launcher:maxAppCellCountX="@integer/apps_customize_maxCellCountX"
+                launcher:maxAppCellCountY="@integer/apps_customize_maxCellCountY"
+                launcher:pageLayoutWidthGap="@dimen/apps_customize_pageLayoutWidthGap"
+                launcher:pageLayoutHeightGap="@dimen/apps_customize_pageLayoutHeightGap"
+                launcher:pageLayoutPaddingTop="@dimen/apps_customize_pageLayoutPaddingTop"
+                launcher:pageLayoutPaddingBottom="@dimen/apps_customize_pageLayoutPaddingBottom"
+                launcher:pageLayoutPaddingLeft="@dimen/apps_customize_pageLayoutPaddingLeft"
+                launcher:pageLayoutPaddingRight="@dimen/apps_customize_pageLayoutPaddingRight"
+                launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap"
+                launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
+                launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
+                launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
+                launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
+                launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
+                launcher:maxGap="@dimen/workspace_max_gap" />
+            <FrameLayout
+                android:id="@+id/animation_buffer"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="#FF000000"
+                android:visibility="gone" />
+
+            <include
+                android:id="@+id/paged_view_indicator"
+                layout="@layout/scroll_indicator"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="bottom" />
+        </FrameLayout>
+    </LinearLayout>
+
+    <include layout="@layout/all_apps_cling"
+        android:id="@+id/all_apps_cling"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone" />
+</org.fairphone.launcher.AppsCustomizeTabHost>
diff --git a/FairphoneHome/res/layout/apps_customize_progressbar.xml b/FairphoneHome/res/layout/apps_customize_progressbar.xml
new file mode 100644
index 0000000..6aa9099
--- /dev/null
+++ b/FairphoneHome/res/layout/apps_customize_progressbar.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<ProgressBar
+   xmlns:android="http://schemas.android.com/apk/res/android"
+   style="?android:attr/progressBarStyleLarge"
+   android:id="@+id/apps_customize_progress_bar"
+   android:layout_width="wrap_content"
+   android:layout_height="wrap_content"
+   android:layout_gravity="center" />
diff --git a/FairphoneHome/res/layout/apps_customize_widget.xml b/FairphoneHome/res/layout/apps_customize_widget.xml
new file mode 100644
index 0000000..e697ddc
--- /dev/null
+++ b/FairphoneHome/res/layout/apps_customize_widget.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<org.fairphone.launcher.PagedViewWidget
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1"
+    android:orientation="vertical"
+
+    android:background="@drawable/focusable_view_bg"
+    android:focusable="true">
+
+    <!-- The preview of the widget or shortcut. -->
+    <org.fairphone.launcher.PagedViewWidgetImageView
+        android:id="@+id/widget_preview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="@dimen/app_widget_preview_padding_top"
+        android:paddingLeft="@dimen/app_widget_preview_padding_left"
+        android:paddingRight="@dimen/app_widget_preview_padding_right"
+        android:scaleType="matrix"
+        android:background="@drawable/widget_container_holo" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/app_widget_preview_label_margin_top"
+        android:layout_marginLeft="@dimen/app_widget_preview_label_margin_left"
+        android:layout_marginRight="@dimen/app_widget_preview_label_margin_right"
+        android:orientation="horizontal">
+        <!-- The name of the widget. -->
+        <!-- old ns xmlns:android="http://schemas.android.com/apk/res/android" -->
+        <TextView 
+            android:id="@+id/widget_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="left"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal"
+
+            android:textColor="#FFFFFFFF"
+            android:textSize="13sp" />
+
+        <!-- The original dimensions of the widget (can't be the same text as above due to different
+             style. -->
+             <!-- xmlns:android="http://schemas.android.com/apk/res/android" -->
+        <TextView 
+            android:id="@+id/widget_dims"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_marginLeft="5dp"
+            android:layout_weight="0"
+            android:gravity="left"
+
+            android:textColor="#FF555555"
+            android:textSize="12sp" />
+    </LinearLayout>
+
+
+</org.fairphone.launcher.PagedViewWidget>
diff --git a/FairphoneHome/res/layout/appwidget_error.xml b/FairphoneHome/res/layout/appwidget_error.xml
new file mode 100644
index 0000000..03d4ae4
--- /dev/null
+++ b/FairphoneHome/res/layout/appwidget_error.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:paddingTop="10dip"
+    android:paddingBottom="10dip"
+    android:paddingLeft="20dip"
+    android:paddingRight="20dip"
+    android:gravity="center"
+    android:background="@drawable/bg_appwidget_error"
+    android:textAppearance="?android:attr/textAppearanceMediumInverse"
+    android:textColor="@color/appwidget_error_color"
+    android:text="@string/gadget_error_text"
+    />
diff --git a/FairphoneHome/res/layout/custom_workspace_cling.xml b/FairphoneHome/res/layout/custom_workspace_cling.xml
new file mode 100644
index 0000000..a721f32
--- /dev/null
+++ b/FairphoneHome/res/layout/custom_workspace_cling.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<!-- dummy layout, to be replaced in overlays -->
+<org.fairphone.launcher.Cling
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    launcher:drawIdentifier="workspace_custom">
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="20dp"
+        android:textColor="@android:color/holo_blue_light"
+        android:text="@string/dummy_custom_cling_error_message"
+        android:gravity="left"
+        android:layout_gravity="bottom|left"
+    />
+</org.fairphone.launcher.Cling>
diff --git a/FairphoneHome/res/layout/drop_target_bar.xml b/FairphoneHome/res/layout/drop_target_bar.xml
new file mode 100644
index 0000000..ab6e9a9
--- /dev/null
+++ b/FairphoneHome/res/layout/drop_target_bar.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        style="@style/DropTargetButtonContainer"
+        android:layout_weight="1">
+        <!-- Delete target -->
+        <org.fairphone.launcher.DeleteDropTarget
+            style="@style/DropTargetButton"
+            android:id="@+id/delete_target_text"
+            android:text="@string/delete_zone_label_workspace"
+            android:drawableLeft="@drawable/remove_target_selector" />
+    </FrameLayout>
+    <FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        style="@style/DropTargetButtonContainer"
+        android:layout_weight="1">
+        <!-- Info target -->
+        <org.fairphone.launcher.InfoDropTarget
+            style="@style/DropTargetButton"
+            android:id="@+id/info_target_text"
+            android:text="@string/info_target_label"
+            android:drawableLeft="@drawable/info_target_selector" />
+    </FrameLayout>
+</merge>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/folder_cling.xml b/FairphoneHome/res/layout/folder_cling.xml
new file mode 100644
index 0000000..f01cf6a
--- /dev/null
+++ b/FairphoneHome/res/layout/folder_cling.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<org.fairphone.launcher.Cling
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    launcher:drawIdentifier="folder_portrait">
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="@dimen/folderClingMarginTop">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <TextView
+                style="@style/ClingTitleText"
+                android:id="@+id/folder_cling_title"
+                android:text="@string/folder_cling_title" />
+            <TextView
+                style="@style/ClingText"
+                android:id="@+id/folder_cling_create_folder"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/folder_cling_create_folder" />
+        </LinearLayout>
+    </FrameLayout>
+    <Button
+        style="@style/ClingButton"
+        android:id="@+id/cling_dismiss"
+        android:layout_marginBottom="15dp"
+        android:layout_marginRight="10dp"
+        android:layout_gravity="bottom|right"
+        android:onClick="dismissFolderCling" />
+</org.fairphone.launcher.Cling>
diff --git a/FairphoneHome/res/layout/folder_icon.xml b/FairphoneHome/res/layout/folder_icon.xml
new file mode 100644
index 0000000..dd5eb88
--- /dev/null
+++ b/FairphoneHome/res/layout/folder_icon.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<org.fairphone.launcher.FolderIcon
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:focusable="true"
+    android:background="@drawable/focusable_view_bg">
+    <ImageView
+        android:id="@+id/preview_background"
+        android:layout_gravity="center_horizontal"
+        android:layout_width="@dimen/folder_preview_size"
+        android:layout_height="@dimen/folder_preview_size"
+        android:src="@drawable/portal_ring_inner_holo"/>
+    <org.fairphone.launcher.BubbleTextView
+        android:id="@+id/folder_icon_name"
+        style="@style/WorkspaceIcon.Portrait.Folder"/>
+</org.fairphone.launcher.FolderIcon>
diff --git a/FairphoneHome/res/layout/fp_app_switcher.xml b/FairphoneHome/res/layout/fp_app_switcher.xml
new file mode 100755
index 0000000..b63d6d7
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_app_switcher.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/appSwitcherMain"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <RelativeLayout
+        android:id="@+id/header"
+        android:layout_width="match_parent"
+        android:layout_height="62dp" >
+
+        <ImageButton
+            android:id="@+id/buttonLauncher"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:background="#00ffffff"
+            android:src="@drawable/app_switcher_icon_all_apps" />
+
+        <Button
+            android:id="@+id/buttonReset"
+            style="@style/AppSwitcherButtonReset"
+            android:layout_width="wrap_content"
+            android:layout_height="36dp"
+            android:layout_alignParentRight="true"
+            android:layout_marginRight="6.6dp"
+            android:layout_marginTop="13.5dp"
+            android:text="@string/reset"
+            android:visibility="gone" />
+
+        <Button
+            android:id="@+id/buttonResetDisabled"
+            style="@style/AppSwitcherButtonReset"
+            android:layout_width="wrap_content"
+            android:layout_height="36dp"
+            android:layout_alignParentRight="true"
+            android:layout_marginRight="6.6dp"
+            android:layout_marginTop="13.5dp"
+            android:enabled="false"
+            android:text="@string/reset"
+            android:visibility="gone" />
+    </RelativeLayout>
+	
+    <LinearLayout
+        android:id="@+id/appSwitcher"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="horizontal" >
+
+        <LinearLayout
+            android:layout_width="130dp"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="6.6dp"
+            android:layout_marginTop="6.6dp"
+            android:orientation="vertical" >
+
+            <TextView
+                android:id="@+id/lastUsedAppsOOBETitle"
+                style="@style/AppSwitcherOOBEText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="6dp"
+                android:layout_marginLeft="10dp"
+                android:layout_marginTop="6dp"
+                android:text="@string/last_used_apps"
+                android:visibility="gone" />
+
+            <TextView
+                android:id="@+id/lastUsedAppsTitle"
+                style="@style/SubTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="6dp"
+                android:layout_marginTop="13dp"
+                android:gravity="center_horizontal"
+                android:text="@string/last_used" />
+
+            <LinearLayout
+                android:id="@+id/lastUsedApps"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:gravity="center_horizontal"
+                android:orientation="vertical" />
+        </LinearLayout>
+
+        <ImageView
+            android:layout_width="6.6dp"
+            android:layout_height="match_parent"
+            android:background="@drawable/app_switcher_divider" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="6.6dp"
+            android:layout_marginRight="6.6dp"
+            android:layout_marginTop="6.6dp"
+            android:background="@drawable/app_switcher_list_background"
+            android:orientation="vertical" >
+
+            <TextView
+                android:id="@+id/mostUsedAppsOOBETitle"
+                style="@style/AppSwitcherOOBEText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_marginTop="6dp"
+                android:text="@string/most_used_apps"
+                android:visibility="gone" />
+
+            <TextView
+                android:id="@+id/mostUsedAppsOOBEDescription"
+                style="@style/AppSwitcherOOBEDescriptionText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="5dp"
+                android:layout_marginTop="60dp"
+                android:text="@string/no_apps_have_been_opened_yet"
+                android:visibility="gone" />
+
+            <TextView
+                android:id="@+id/mostUsedAppsTitle"
+                style="@style/SubTitle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_marginTop="13dp"
+                android:text="@string/most_used" />
+
+            <LinearLayout
+                android:id="@+id/mostUsedApps"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:orientation="vertical" />
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_edit_favorites.xml b/FairphoneHome/res/layout/fp_edit_favorites.xml
new file mode 100644
index 0000000..11e183f
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_edit_favorites.xml
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="utf-8"?>

+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent"

+        >

+

+    <LinearLayout

+        android:id="@+id/editMenuMain"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent"

+        android:orientation="vertical" >

+

+        <!-- android:background="#CC000000" -->

+

+        <RelativeLayout

+            android:layout_width="match_parent"

+            android:layout_height="62dp"

+            android:paddingLeft="33dp" >

+

+            <TextView

+                android:id="@+id/mainTitle"

+                style="@style/SecondaryMainTitle"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:layout_marginTop="20dp"

+                android:text="@string/edit" />

+

+            <TextView

+                style="@style/IconText"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:layout_below="@+id/mainTitle"

+                android:layout_marginLeft="1dp"

+                android:text="@string/favourite_apps"

+                android:textAllCaps="true" />

+        </RelativeLayout>

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="match_parent"

+            android:orientation="horizontal" >

+

+            <RelativeLayout

+                android:id="@+id/allAppsGroup"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_marginTop="6.6dp"

+                android:layout_weight="1"

+                android:background="@drawable/edit_menu_list_background"

+                android:orientation="vertical" >

+

+                <org.fairphone.launcher.edgeswipe.ui.EditFavoritesGridView

+                    android:id="@+id/allAppsGridView"

+                    android:layout_width="match_parent"

+                    android:layout_height="match_parent"

+                    android:layout_marginLeft="13dp"

+                    android:layout_marginRight="13dp"

+                    android:clipToPadding="false"

+                    android:horizontalSpacing="13dp"

+                    android:listSelector="@color/transparent"

+                    android:numColumns="2"

+                    android:overScrollMode="never"

+                    android:paddingTop="20dp"

+                    android:scrollbars="none"

+                    android:verticalSpacing="15dp" />

+

+                <!--

+                 <GridView

+                android:id="@+id/allAppsGridView"

+                android:layout_width="match_parent"

+                android:layout_height="match_parent"

+                android:layout_marginLeft="13dp"

+                android:layout_marginRight="13dp"

+                android:clipToPadding="false"

+                android:horizontalSpacing="13dp"

+                android:listSelector="@color/transparent"

+                android:numColumns="2"

+                android:overScrollMode="never"

+                android:paddingTop="20dp"

+                android:scrollbars="none"

+                android:verticalSpacing="15dp" />

+                -->

+

+                <TextView

+                    android:id="@+id/allAppsTextView"

+                    style="@style/IconText"

+                    android:layout_width="wrap_content"

+                    android:layout_height="wrap_content"

+                    android:layout_centerInParent="true"

+                    android:drawablePadding="6dp"

+                    android:drawableTop="@drawable/edit_menu_icon_remove"

+                    android:lines="3"

+                    android:text="@string/drag_here_to_remove"

+                    android:textAllCaps="true"

+                    android:visibility="gone" />

+

+                <View

+                    android:layout_width="match_parent"

+                    android:layout_height="15dp"

+                    android:background="@drawable/edit_menu_list_shadow_top" />

+

+                <View

+                    android:layout_width="match_parent"

+                    android:layout_height="15dp"

+                    android:layout_alignParentBottom="true"

+                    android:background="@drawable/edit_menu_list_shadow_bottom" />

+            </RelativeLayout>

+

+            <View

+                android:layout_width="7.3dp"

+                android:layout_height="match_parent"

+                android:background="@drawable/edit_menu_list_separator" />

+

+            <LinearLayout

+                android:layout_width="113dp"

+                android:layout_height="match_parent"

+                android:layout_marginTop="6.6dp"

+                android:gravity="center_horizontal"

+                android:orientation="vertical" >

+

+                <RelativeLayout

+                    android:id="@+id/favouriteGroup1"

+                    android:layout_width="103dp"

+                    android:layout_height="103dp"

+                    android:layout_marginLeft="3dp"

+                    android:background="@drawable/edit_menu_circle_faded" >

+

+                    <TextView

+                        android:id="@+id/favouriteRing1"

+                        style="@style/MainText"

+                        android:layout_width="103dp"

+                        android:layout_height="103dp"

+                        android:background="@drawable/edit_menu_circle"

+                        android:fontFamily="sans-serif"

+                        android:gravity="center"

+                        android:text="@string/drag_here_to_add"

+                        android:textAllCaps="true"

+                        android:visibility="invisible" />

+

+                    <TextView

+                        android:id="@+id/favouriteText1"

+                        style="@style/IconText"

+                        android:layout_width="95dp"

+                        android:layout_height="wrap_content"

+                        android:layout_centerHorizontal="true"

+                        android:layout_marginTop="15dp"

+                        android:drawablePadding="5dp" />

+                </RelativeLayout>

+

+                <RelativeLayout

+                    android:id="@+id/favouriteGroup2"

+                    android:layout_width="103dp"

+                    android:layout_height="103dp"

+                    android:layout_marginLeft="3dp"

+                    android:layout_marginTop="9dp"

+                    android:background="@drawable/edit_menu_circle_faded" >

+

+                    <TextView

+                        android:id="@+id/favouriteRing2"

+                        style="@style/MainText"

+                        android:layout_width="103dp"

+                        android:layout_height="103dp"

+                        android:background="@drawable/edit_menu_circle"

+                        android:fontFamily="sans-serif"

+                        android:gravity="center"

+                        android:text="@string/drag_here_to_add"

+                        android:textAllCaps="true"

+                        android:visibility="invisible" />

+

+                    <TextView

+                        android:id="@+id/favouriteText2"

+                        style="@style/IconText"

+                        android:layout_width="95dp"

+                        android:layout_height="wrap_content"

+                        android:layout_centerHorizontal="true"

+                        android:layout_marginTop="15dp"

+                        android:drawablePadding="5dp" />

+                </RelativeLayout>

+

+                <!-- ALL APPS BUTTONS -->

+

+                <ImageView

+                    android:layout_width="wrap_content"

+                    android:layout_height="wrap_content"

+                    android:paddingBottom="30dp"

+                    android:paddingTop="30dp"

+                    android:src="@drawable/edit_menu_all_apps_faded" />

+

+                <RelativeLayout

+                    android:id="@+id/favouriteGroup3"

+                    android:layout_width="103dp"

+                    android:layout_height="103dp"

+                    android:layout_marginLeft="3dp"

+                    android:background="@drawable/edit_menu_circle_faded" >

+

+                    <TextView

+                        android:id="@+id/favouriteRing3"

+                        style="@style/MainText"

+                        android:layout_width="103dp"

+                        android:layout_height="103dp"

+                        android:background="@drawable/edit_menu_circle"

+                        android:fontFamily="sans-serif"

+                        android:gravity="center"

+                        android:text="@string/drag_here_to_add"

+                        android:textAllCaps="true"

+                        android:visibility="invisible" />

+

+                    <TextView

+                        android:id="@+id/favouriteText3"

+                        style="@style/IconText"

+                        android:layout_width="95dp"

+                        android:layout_height="wrap_content"

+                        android:layout_centerHorizontal="true"

+                        android:layout_marginTop="15dp"

+                        android:drawablePadding="5dp" />

+                </RelativeLayout>

+

+                <RelativeLayout

+                    android:id="@+id/favouriteGroup4"

+                    android:layout_width="103dp"

+                    android:layout_height="103dp"

+                    android:layout_marginLeft="3dp"

+                    android:layout_marginTop="9dp"

+                    android:background="@drawable/edit_menu_circle_faded" >

+

+                    <TextView

+                        android:id="@+id/favouriteRing4"

+                        style="@style/MainText"

+                        android:layout_width="103dp"

+                        android:layout_height="103dp"

+                        android:background="@drawable/edit_menu_circle"

+                        android:fontFamily="sans-serif"

+                        android:gravity="center"

+                        android:text="@string/drag_here_to_add"

+                        android:textAllCaps="true"

+                        android:visibility="invisible" />

+

+                    <TextView

+                        android:id="@+id/favouriteText4"

+                        style="@style/IconText"

+                        android:layout_width="95dp"

+                        android:layout_height="wrap_content"

+                        android:layout_centerHorizontal="true"

+                        android:layout_marginTop="15dp"

+                        android:drawablePadding="5dp" />

+                </RelativeLayout>

+            </LinearLayout>

+        </LinearLayout>

+    </LinearLayout>

+

+</RelativeLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_fav_apps_layout.xml b/FairphoneHome/res/layout/fp_fav_apps_layout.xml
new file mode 100644
index 0000000..255b853
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_fav_apps_layout.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

+    android:layout_width="match_parent"

+    android:layout_height="match_parent" >

+

+    <View

+        android:id="@+id/menuBackground"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent"

+        android:alpha="0.80"

+        android:background="#000000" />

+

+    <FrameLayout

+        android:id="@+id/menuRoot"

+        android:layout_width="500dp"

+        android:layout_height="500dp" >

+

+        <FrameLayout

+            android:id="@+id/menuContent"

+            android:layout_width="500dp"

+            android:layout_height="500dp" >

+

+            <RelativeLayout

+                android:id="@+id/icon1"

+                android:layout_width="103dp"

+                android:layout_height="103dp" >

+

+                <TextView

+                    android:id="@+id/iconSelectedName"

+                    style="@style/IconText"

+                    android:layout_width="95dp"

+                    android:layout_height="wrap_content"

+                    android:layout_centerInParent="true"

+                    android:drawablePadding="4dp"

+                    android:paddingTop="15dp" />

+

+                <View

+                    android:id="@+id/iconPressRing"

+                    android:layout_width="match_parent"

+                    android:layout_height="match_parent"

+                    android:background="@drawable/edit_menu_circle"

+                    android:visibility="gone" />

+            </RelativeLayout>

+

+            <RelativeLayout

+                android:id="@+id/icon2"

+                android:layout_width="103dp"

+                android:layout_height="103dp" >

+

+                <TextView

+                    android:id="@+id/iconSelectedName"

+                    style="@style/IconText"

+                    android:layout_width="95dp"

+                    android:layout_height="wrap_content"

+                    android:layout_centerInParent="true"

+                    android:drawablePadding="4dp"

+                    android:paddingTop="15dp" />

+

+                <View

+                    android:id="@+id/iconPressRing"

+                    android:layout_width="match_parent"

+                    android:layout_height="match_parent"

+                    android:background="@drawable/edit_menu_circle"

+                    android:visibility="gone" />

+            </RelativeLayout>

+

+            <RelativeLayout

+                android:id="@+id/icon3"

+                android:layout_width="103dp"

+                android:layout_height="103dp" >

+

+                <TextView

+                    android:id="@+id/iconSelectedName"

+                    style="@style/IconText"

+                    android:layout_width="95dp"

+                    android:layout_height="wrap_content"

+                    android:layout_centerInParent="true"

+                    android:drawablePadding="4dp"

+                    android:paddingTop="28dp" />

+

+                <View

+                    android:id="@+id/iconPressRing"

+                    android:layout_width="match_parent"

+                    android:layout_height="match_parent"

+                    android:background="@drawable/edit_menu_circle"

+                    android:visibility="gone" />

+            </RelativeLayout>

+

+            <RelativeLayout

+                android:id="@+id/icon4"

+                android:layout_width="103dp"

+                android:layout_height="103dp" >

+

+                <TextView

+                    android:id="@+id/iconSelectedName"

+                    style="@style/IconText"

+                    android:layout_width="95dp"

+                    android:layout_height="wrap_content"

+                    android:layout_centerInParent="true"

+                    android:drawablePadding="4dp"

+                    android:paddingTop="15dp" />

+

+                <View

+                    android:id="@+id/iconPressRing"

+                    android:layout_width="match_parent"

+                    android:layout_height="match_parent"

+                    android:background="@drawable/edit_menu_circle"

+                    android:visibility="gone" />

+            </RelativeLayout>

+

+            <RelativeLayout

+                android:id="@+id/icon5"

+                android:layout_width="103dp"

+                android:layout_height="103dp" >

+

+                <TextView

+                    android:id="@+id/iconSelectedName"

+                    style="@style/IconText"

+                    android:layout_width="95dp"

+                    android:layout_height="wrap_content"

+                    android:layout_centerInParent="true"

+                    android:drawablePadding="4dp"

+                    android:paddingTop="15dp" />

+

+                <View

+                    android:id="@+id/iconPressRing"

+                    android:layout_width="match_parent"

+                    android:layout_height="match_parent"

+                    android:background="@drawable/edit_menu_circle"

+                    android:visibility="gone" />

+            </RelativeLayout>

+        </FrameLayout>

+    </FrameLayout>

+

+    <RelativeLayout

+        android:id="@+id/editGroup"

+        android:layout_width="103dp"

+        android:layout_height="103dp"

+        android:layout_margin="10dp"

+        android:visibility="invisible" >

+

+        <TextView

+            android:id="@+id/editText"

+            style="@style/SwipeMenuEditText"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_centerInParent="true"

+            android:drawableTop="@drawable/icon_edit"

+            android:drawablePadding="8dp"

+            android:text="@string/edit" />

+

+        <View

+            android:id="@+id/editRing"

+            android:layout_width="match_parent"

+            android:layout_height="match_parent"

+            android:background="@drawable/edit_menu_circle"

+            android:visibility="gone" />

+    </RelativeLayout>

+

+    <View

+        android:id="@+id/swipeMenuTopShadow"

+        android:layout_width="match_parent"

+        android:layout_height="66dp"

+        android:layout_marginTop="25dp"

+        android:background="@drawable/swipe_menu_shadow_top"

+        android:visibility="gone" />

+

+    <View

+        android:id="@+id/swipeMenuBottomShadow"

+        android:layout_width="match_parent"

+        android:layout_height="66dp"

+        android:layout_gravity="bottom"

+        android:background="@drawable/swipe_menu_shadow_bottom"

+        android:visibility="gone" />

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_favorites_all_apps_list_item.xml b/FairphoneHome/res/layout/fp_favorites_all_apps_list_item.xml
new file mode 100644
index 0000000..ea76a2b
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_favorites_all_apps_list_item.xml
@@ -0,0 +1,19 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center_horizontal"
+    android:orientation="vertical">
+
+    <ImageView
+        android:id="@+id/appPicture"
+        android:layout_width="@dimen/app_icon_size"
+        android:layout_height="@dimen/app_icon_size" />
+
+    <TextView
+        android:id="@+id/appText"
+        style="@style/IconText"
+        android:layout_width="95dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="5dp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_google_apps_installer_widget.xml b/FairphoneHome/res/layout/fp_google_apps_installer_widget.xml
new file mode 100644
index 0000000..cfde135
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_google_apps_installer_widget.xml
@@ -0,0 +1,330 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

+    android:id="@+id/googleAppsIntallerMain"

+    android:layout_width="wrap_content"

+    android:layout_height="wrap_content" >

+

+    <FrameLayout

+        android:id="@+id/installGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/installButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_install" />

+

+        <TextView

+            android:id="@+id/installText"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:text="@string/google_apps_initial_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18sp" />

+    </FrameLayout>

+

+    <LinearLayout

+        android:id="@+id/popupDisclaimerGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_title"

+            android:textColor="@color/google_blue"

+            android:ellipsize="marquee"

+            android:marqueeRepeatLimit="marquee_forever"

+            android:scrollHorizontally="true" 

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_disclaimer_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/disclaimerCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/disclaimerOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupFailedDownloadGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_failed_download_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="2" >

+

+            <Button

+                android:id="@+id/failedDownloadCancelButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/cancel"

+                android:textSize="12.5sp" />

+

+            <ImageView

+                android:layout_width="1dp"

+                android:layout_height="match_parent"

+                android:background="#727578" />

+

+            <Button

+                android:id="@+id/failedDownloadOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupProgressGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/progressDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <ProgressBar

+            android:id="@+id/progressBar"

+            android:layout_width="match_parent"

+            android:layout_height="2dp"

+            android:layout_marginBottom="35dp"

+            android:layout_marginLeft="15dp"

+            android:layout_marginRight="15dp"

+            android:layout_marginTop="35dp"

+            android:indeterminate="false"

+            android:indeterminateOnly="false"

+            android:max="100"

+            android:padding="0dp"

+            android:progressDrawable="@drawable/fp_gapps_progress" />

+    </LinearLayout>

+

+    <LinearLayout

+        android:id="@+id/popupRebootGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/rebootDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_reboot_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+            

+            <Button

+                android:id="@+id/rebootOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+    

+    <LinearLayout

+        android:id="@+id/popupPermissionsGroup"

+        android:layout_width="280dp"

+        android:layout_height="wrap_content"

+        android:background="@drawable/fp_gapps_alert_background"

+        android:orientation="vertical"

+        android:visibility="gone" >

+

+        <TextView

+            android:id="@+id/permissionsDialogTitle"

+            android:layout_width="match_parent"

+            android:layout_height="58dp"

+            android:layout_gravity="center_vertical"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_title"

+            android:textColor="@color/google_blue"

+            android:textSize="18.5sp" />

+

+        <TextView

+            android:layout_width="match_parent"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:fontFamily="sans-serif-light"

+            android:padding="15dp"

+            android:text="@string/google_apps_permissions_description"

+            android:textColor="@color/white"

+            android:textSize="13.5sp" />

+

+        <ImageView

+            android:layout_width="match_parent"

+            android:layout_height="1dp"

+            android:background="#727578" />

+

+        <LinearLayout

+            android:layout_width="match_parent"

+            android:layout_height="43.5dp"

+            android:orientation="horizontal"

+            android:weightSum="1" >

+

+            <Button

+                android:id="@+id/permissionsOkButton"

+                android:layout_width="0dp"

+                android:layout_height="match_parent"

+                android:layout_weight="1"

+                android:background="@drawable/fp_gaaps_alert_button"

+                android:text="@android:string/ok"

+                android:textSize="12.5sp" />

+        </LinearLayout>

+    </LinearLayout>

+

+    <FrameLayout

+        android:id="@+id/uninstallGroup"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:visibility="gone" >

+

+        <ImageButton

+            android:id="@+id/uninstallButton"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:background="@drawable/fp_gapps_widget_uninstall" />

+

+        <LinearLayout

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center_vertical"

+            android:layout_marginLeft="20dp"

+            android:orientation="vertical" >

+

+            <TextView

+                android:id="@+id/uninstallTitle"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:text="@string/google_apps_uninstall_title"

+                android:textColor="#c8c8c8"

+                android:textSize="13.3dp" />

+

+            <TextView

+                android:id="@+id/uninstallText"

+                android:layout_width="wrap_content"

+                android:layout_height="wrap_content"

+                android:layout_gravity="center_vertical"

+                android:text="@string/google_apps_uninstall_description"

+                android:textColor="#c8c8c8"

+                android:textSize="18.5sp" />

+        </LinearLayout>

+    </FrameLayout>

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_last_used_item.xml b/FairphoneHome/res/layout/fp_last_used_item.xml
new file mode 100644
index 0000000..137398d
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_last_used_item.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" >
+
+    <Button
+        android:id="@+id/recentButton"
+        android:layout_width="95dp"
+        android:layout_height="95dp"
+        android:background="@drawable/button_last_used_app" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:clickable="false"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        android:paddingTop="10dp" >
+
+        <ImageView
+            android:id="@android:id/background"
+            android:layout_width="@dimen/app_icon_size"
+            android:layout_height="@dimen/app_icon_size"
+            android:clickable="false" />
+
+        <TextView
+            android:id="@android:id/text1"
+            style="@style/IconText"
+            android:layout_width="95dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:clickable="false"
+            android:includeFontPadding="false"
+            android:lines="2" />
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_most_used_item.xml b/FairphoneHome/res/layout/fp_most_used_item.xml
new file mode 100644
index 0000000..d0e37e9
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_most_used_item.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/mostUsedRow"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginLeft="10dp"
+    android:layout_marginRight="10dp"
+    android:layout_marginTop="7dp" >
+
+    <Button
+        android:id="@+id/mostUsedButton"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/button_app_switcher_reset"
+        android:fontFamily="sans-serif-light"
+        android:gravity="center_vertical|left"
+        android:includeFontPadding="false"
+        android:lines="2"
+        android:paddingBottom="12dp"
+        android:paddingLeft="70dp"
+        android:paddingRight="12dp"
+        android:paddingTop="12dp"
+        android:textAllCaps="false"
+        android:textColor="@color/white"
+        android:textSize="17sp" />
+
+    <ImageView
+        android:id="@android:id/content"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginTop="10dp"
+        android:clickable="false"
+        android:gravity="center_vertical" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_oobe_activity.xml b/FairphoneHome/res/layout/fp_oobe_activity.xml
new file mode 100644
index 0000000..b657f67
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_oobe_activity.xml
@@ -0,0 +1,80 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/oobe_background"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/fp_oobe_background" >
+
+    <FrameLayout
+        android:id="@+id/tutorialAnimationViewContainer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginTop="55dp" >
+    </FrameLayout>
+
+    <include layout="@layout/fp_oobe_texts" />
+
+    <Button
+        android:id="@+id/skipButton"
+        style="@style/OOBEButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:tag="fontHannah"
+        android:text="@string/oobe_skip" />
+
+    <Button
+        android:id="@+id/startButton"
+        style="@style/OOBEButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:tag="fontHannah"
+        android:text="@string/oobe_start" />
+
+    <Button
+        android:id="@+id/nextButton"
+        style="@style/OOBEButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
+        android:layout_marginRight="25dp"
+        android:tag="fontHannah"
+        android:text="@string/oobe_next" />
+
+    <Button
+        android:id="@+id/backButton"
+        style="@style/OOBEButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentLeft="true"
+        android:layout_marginLeft="25dp"
+        android:tag="fontHannah"
+        android:text="@string/oobe_back" />
+
+    <RelativeLayout
+        android:id="@+id/oobeVideoViewGroup"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+
+        <VideoView
+            android:id="@+id/fp_oobe_video"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <Button
+            android:id="@+id/fp_oobe_video_skip_button"
+            style="@style/OOBEButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_centerHorizontal="true"
+            android:tag="fontHannah"
+            android:text="@string/oobe_skip" />
+    </RelativeLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/fp_oobe_texts.xml b/FairphoneHome/res/layout/fp_oobe_texts.xml
new file mode 100644
index 0000000..93f4df2
--- /dev/null
+++ b/FairphoneHome/res/layout/fp_oobe_texts.xml
@@ -0,0 +1,242 @@
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" >
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup1"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        android:paddingBottom="40dp"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="140dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitleBig"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_select_language" />
+
+        <ImageButton
+            android:id="@+id/selectLanguageButton"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="80dp"
+            android:background="@color/transparent"
+            android:src="@drawable/oobe_language_button" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup2"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        android:paddingBottom="40dp"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="140dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitleBig"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_setup_wifi" />
+
+        <ImageButton
+            android:id="@+id/setupWifiButton"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="80dp"
+            android:background="@color/transparent"
+            android:src="@drawable/oobe_wifi_button" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup3"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_intro_top" />
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="25dp"
+            android:src="@drawable/oobe_fairphone_logo" />
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="55dp"
+            android:tag="fontHannah"
+            android:text="@string/oobe_intro_bottom" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup4"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edge_swipe_title" />
+
+        <TextView
+            style="@style/OOBEText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-15dp"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edge_swipe_text" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup5"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_open_app_title" />
+
+        <TextView
+            style="@style/OOBEText"
+            android:layout_marginTop="-15dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_open_app_text" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup6"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/oobe_edit_drag_intro"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBEText"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_intro" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup7"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_add_title" />
+
+        <TextView
+            style="@style/OOBEText"
+            android:layout_marginTop="-15dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_add_text" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup8"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_remove_title" />
+
+        <TextView
+            style="@style/OOBEText"
+            android:layout_marginTop="-15dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_remove_text" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/oobeTextGroup9"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:paddingLeft="40dp"
+        android:paddingRight="40dp"
+        android:paddingTop="40dp"
+        android:visibility="gone" >
+
+        <TextView
+            style="@style/OOBETitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_trade_title" />
+
+        <TextView
+            style="@style/OOBEText"
+            android:layout_marginTop="-15dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:tag="fontHannah"
+            android:text="@string/oobe_edit_drag_trade_text" />
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/hotseat.xml b/FairphoneHome/res/layout/hotseat.xml
new file mode 100644
index 0000000..36ae994
--- /dev/null
+++ b/FairphoneHome/res/layout/hotseat.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<org.fairphone.launcher.Hotseat
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    launcher:cellCountX="@integer/hotseat_cell_count"
+    launcher:cellCountY="1">
+    <org.fairphone.launcher.CellLayout
+        android:id="@+id/layout"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center"
+        android:paddingTop="@dimen/button_bar_height_top_padding"
+        android:paddingBottom="@dimen/button_bar_height_bottom_padding"
+        android:paddingLeft="@dimen/button_bar_width_left_padding"
+        android:paddingRight="@dimen/button_bar_width_right_padding"
+
+        launcher:cellWidth="@dimen/hotseat_cell_width"
+        launcher:cellHeight="@dimen/hotseat_cell_height"
+        launcher:widthGap="@dimen/hotseat_width_gap"
+        launcher:heightGap="@dimen/hotseat_height_gap"
+        launcher:maxGap="@dimen/workspace_max_gap" />
+</org.fairphone.launcher.Hotseat>
diff --git a/FairphoneHome/res/layout/launcher.xml b/FairphoneHome/res/layout/launcher.xml
new file mode 100644
index 0000000..17edbd8
--- /dev/null
+++ b/FairphoneHome/res/layout/launcher.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<!-- android:background="@drawable/workspace_bg" -->
+<!-- android:background="@drawable/workspace_bg" -->
+
+<!-- Full screen view projects under the status bar and contains the background -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/launcher"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <org.fairphone.launcher.DragLayer
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+        android:id="@+id/drag_layer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:fitsSystemWindows="true" >
+
+        <!--
+             Keep these behind the workspace so that they are not visible when
+             we go into AllApps
+        -->
+        <!--
+     FPNOTE : Removed the view indicator
+        <include
+            android:id="@+id/dock_divider"
+            layout="@layout/workspace_divider"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/button_bar_height"
+            android:layout_gravity="bottom" />
+        -->
+
+        <include
+            android:id="@+id/paged_view_indicator"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom"
+            layout="@layout/scroll_indicator" />
+
+        <!--
+             android:paddingLeft="@dimen/workspace_left_padding"
+            android:paddingRight="@dimen/workspace_right_padding"
+            android:paddingTop="@dimen/workspace_top_padding"
+            android:paddingBottom="@dimen/workspace_bottom_padding"
+            launcher:pageSpacing="@dimen/workspace_page_spacing"
+            
+            launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
+            launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right"
+        -->
+
+
+        <!-- The workspace contains 5 screens of cells -->
+
+        <org.fairphone.launcher.Workspace
+            android:id="@+id/workspace"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingBottom="0dp"
+            android:paddingLeft="0dp"
+            android:paddingRight="0dp"
+            android:paddingTop="0dp"
+            launcher:cellCountX="@integer/cell_count_x"
+            launcher:cellCountY="@integer/cell_count_y"
+            launcher:defaultScreen="2"
+            launcher:pageSpacing="0dp"
+            launcher:scrollIndicatorPaddingLeft="0dp"
+            launcher:scrollIndicatorPaddingRight="0dp" >
+
+            <include
+                android:id="@+id/cell1"
+                layout="@layout/workspace_screen" />
+
+            <include
+                android:id="@+id/cell2"
+                layout="@layout/workspace_screen" />
+
+            <include
+                android:id="@+id/cell3"
+                layout="@layout/workspace_screen" />
+
+            <include
+                android:id="@+id/cell4"
+                layout="@layout/workspace_screen" />
+
+            <include
+                android:id="@+id/cell5"
+                layout="@layout/workspace_screen" />
+        </org.fairphone.launcher.Workspace>
+        <!--
+        <include layout="@layout/hotseat"
+            android:id="@+id/hotseat"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/button_bar_height_plus_padding"
+            android:layout_gravity="bottom" />
+        -->
+
+        <include
+            android:id="@+id/qsb_bar"
+            layout="@layout/qsb_bar" />
+
+        <!--
+             The Workspace cling must appear under the AppsCustomizePagedView below to ensure
+             that it is still visible during the transition to AllApps and doesn't overlay on
+             top of that view.
+        -->
+
+        <include
+            android:id="@+id/workspace_cling"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            layout="@layout/workspace_cling"
+            android:visibility="gone" />
+
+        <include
+            android:id="@+id/folder_cling"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            layout="@layout/folder_cling"
+            android:visibility="gone" />
+
+        <!--
+        FPNOTE Removed this because it launched the voice 
+        <org.fairphone.launcher.DrawableStateProxyView
+            android:id="@+id/voice_button_proxy"
+            android:layout_width="80dp"
+            android:layout_height="@dimen/qsb_bar_height"
+            android:layout_gravity="top|right"
+            android:clickable="true"
+            android:onClick="onClickVoiceButton"
+            android:importantForAccessibility="no"
+            launcher:sourceViewId="@+id/voice_button" />
+        -->
+
+        <include
+            android:id="@+id/apps_customize_pane"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            layout="@layout/apps_customize_pane"
+            android:visibility="invisible" />
+    </org.fairphone.launcher.DragLayer>
+
+    <FrameLayout
+        android:id="@+id/appMenuContainer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <FrameLayout
+        android:id="@+id/systemUpdater"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone" >
+
+        <LinearLayout
+            android:id="@+id/systemUpdaterLla"
+            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="@mipmap/icon_launcher_home"
+                android:drawablePadding="10dp"
+                android:gravity="center_vertical"
+                android:text="@string/application_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/updatingSystem"
+                android:textAllCaps="true"
+                android:textColor="#d3d3d3"
+                android:textSize="15sp" />
+            
+        </LinearLayout>
+    </FrameLayout>
+    <!--
+    <org.fairphone.launcher.edgeswipe.ui.AppEdgeSwipeInterceptorView
+        android:id="@+id/selectDetector"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        tools:context=".MainActivity" >
+
+        <FrameLayout
+            android:id="@+id/appMenuContainer"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </org.fairphone.launcher.edgeswipe.ui.AppEdgeSwipeInterceptorView>
+    -->
+
+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/market_button.xml b/FairphoneHome/res/layout/market_button.xml
new file mode 100644
index 0000000..41e6ec7
--- /dev/null
+++ b/FairphoneHome/res/layout/market_button.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/MarketButton"
+    android:onClick="onClickAppMarketButton"
+    android:gravity="center"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
+    android:background="@drawable/tab_widget_indicator_selector"
+    android:contentDescription="@string/market"
+    android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
+    android:shadowDx="0.0"
+    android:shadowDy="0.0"
+    android:shadowRadius="2.0"
+    android:focusable="true"
+    android:clickable="true" />
diff --git a/FairphoneHome/res/layout/qsb_bar.xml b/FairphoneHome/res/layout/qsb_bar.xml
new file mode 100644
index 0000000..4b0a4ea
--- /dev/null
+++ b/FairphoneHome/res/layout/qsb_bar.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<org.fairphone.launcher.SearchDropTargetBar
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/QSBBar"
+    android:focusable="false">
+
+    <!-- Search buttons container -->
+    
+    <!-- FP_NOTE : Removal of the serach bar 
+    <include android:id="@+id/qsb_search_bar"
+        layout="@layout/search_bar" />
+	-->
+	
+    <!-- Drag specific targets container -->
+    <LinearLayout
+        style="@style/SearchDropTargetBar"
+        android:id="@+id/drag_target_bar">
+
+        <include
+            layout="@layout/drop_target_bar" />
+    </LinearLayout>
+</org.fairphone.launcher.SearchDropTargetBar>
diff --git a/FairphoneHome/res/layout/rename_folder.xml b/FairphoneHome/res/layout/rename_folder.xml
new file mode 100644
index 0000000..75eb504
--- /dev/null
+++ b/FairphoneHome/res/layout/rename_folder.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:padding="20dip"
+    android:orientation="vertical">
+
+    <TextView 
+        android:id="@+id/label"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:text="@string/rename_folder_label"
+        android:gravity="left"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+            
+    <EditText
+        android:id="@+id/folder_name"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:scrollHorizontally="true"
+        android:autoText="false"
+        android:capitalize="none"
+        android:gravity="fill_horizontal"
+        android:maxLength="30"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</LinearLayout>
diff --git a/FairphoneHome/res/layout/scroll_indicator.xml b/FairphoneHome/res/layout/scroll_indicator.xml
new file mode 100644
index 0000000..4ea312b
--- /dev/null
+++ b/FairphoneHome/res/layout/scroll_indicator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:visibility="gone"
+    android:alpha="0"
+    android:scaleType="fitXY"
+    android:src="@drawable/hotseat_scrubber_holo" />
diff --git a/FairphoneHome/res/layout/search_bar.xml b/FairphoneHome/res/layout/search_bar.xml
new file mode 100644
index 0000000..37ac4f3
--- /dev/null
+++ b/FairphoneHome/res/layout/search_bar.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    style="@style/SearchDropTargetBar"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/search_bar_height"
+    android:layout_gravity="bottom|center_horizontal"
+    android:background="@drawable/search_frame">
+   <!-- Global search icon -->
+   <org.fairphone.launcher.HolographicLinearLayout
+        style="@style/SearchButton"
+        launcher:sourceImageViewId="@+id/search_button"
+        android:id="@+id/search_button_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:layout_toLeftOf="@+id/voice_button_container"
+        android:paddingLeft="8dp"
+        android:onClick="onClickSearchButton"
+        android:focusable="true"
+        android:clickable="true"
+        android:contentDescription="@string/accessibility_search_button">
+       <ImageView
+            android:id="@+id/search_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:src="@drawable/ic_home_search_normal_holo"
+            android:adjustViewBounds="true" />
+    </org.fairphone.launcher.HolographicLinearLayout>
+
+    <!-- Voice search icon -->
+    <org.fairphone.launcher.HolographicLinearLayout
+        style="@style/SearchButton"
+        launcher:sourceImageViewId="@+id/voice_button"
+        android:id="@+id/voice_button_container"
+        android:layout_width="@dimen/search_bar_height"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentTop="true"
+        android:paddingRight="8dp"
+        android:gravity="right"
+        android:onClick="onClickVoiceButton"
+        android:focusable="true"
+        android:clickable="true"
+        android:contentDescription="@string/accessibility_voice_search_button">
+        <ImageView
+            android:id="@+id/voice_button"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:src="@drawable/ic_home_voice_search_holo"
+            android:adjustViewBounds="true" />
+    </org.fairphone.launcher.HolographicLinearLayout>
+</RelativeLayout>
diff --git a/FairphoneHome/res/layout/tab_widget_indicator.xml b/FairphoneHome/res/layout/tab_widget_indicator.xml
new file mode 100644
index 0000000..d21d655
--- /dev/null
+++ b/FairphoneHome/res/layout/tab_widget_indicator.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<org.fairphone.launcher.AccessibleTabView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TabIndicator.AppsCustomize" />
diff --git a/FairphoneHome/res/layout/tutorial_edge_swipe_layout.xml b/FairphoneHome/res/layout/tutorial_edge_swipe_layout.xml
new file mode 100644
index 0000000..38737d3
--- /dev/null
+++ b/FairphoneHome/res/layout/tutorial_edge_swipe_layout.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout 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="#00000000">

+

+    <org.fairphone.oobe.animation.MenuTutorialAnimationView

+        android:id="@+id/swipeAnimationView"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent" />

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/tutorial_edit_fav_add_layout.xml b/FairphoneHome/res/layout/tutorial_edit_fav_add_layout.xml
new file mode 100644
index 0000000..80c9394
--- /dev/null
+++ b/FairphoneHome/res/layout/tutorial_edit_fav_add_layout.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout 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="#00000000">

+

+    <org.fairphone.oobe.animation.EditFavsTutorialAnimationView

+        android:id="@+id/editFavAddAnimationView"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent" />

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/tutorial_edit_fav_move_layout.xml b/FairphoneHome/res/layout/tutorial_edit_fav_move_layout.xml
new file mode 100644
index 0000000..bd3f0f1
--- /dev/null
+++ b/FairphoneHome/res/layout/tutorial_edit_fav_move_layout.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout 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="#00000000" >

+

+    <org.fairphone.oobe.animation.EditFavsTutorialAnimationView

+        android:id="@+id/editFavMoveAnimationView"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent" />

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/tutorial_edit_fav_remove_layout.xml b/FairphoneHome/res/layout/tutorial_edit_fav_remove_layout.xml
new file mode 100644
index 0000000..af43562
--- /dev/null
+++ b/FairphoneHome/res/layout/tutorial_edit_fav_remove_layout.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout 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="#00000000" >

+

+    <org.fairphone.oobe.animation.EditFavsTutorialAnimationView

+        android:id="@+id/editFavRemoveAnimationView"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent" />

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/tutorial_open_app_layout.xml b/FairphoneHome/res/layout/tutorial_open_app_layout.xml
new file mode 100644
index 0000000..869a419
--- /dev/null
+++ b/FairphoneHome/res/layout/tutorial_open_app_layout.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>

+<FrameLayout 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="#00000000" >

+

+    <org.fairphone.oobe.animation.MenuTutorialAnimationView

+        android:id="@+id/openAppAnimationView"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent" />

+

+</FrameLayout>
\ No newline at end of file
diff --git a/FairphoneHome/res/layout/user_folder.xml b/FairphoneHome/res/layout/user_folder.xml
new file mode 100644
index 0000000..42afc36
--- /dev/null
+++ b/FairphoneHome/res/layout/user_folder.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<org.fairphone.launcher.Folder
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:background="@drawable/portal_container_holo">
+
+    <org.fairphone.launcher.CellLayout
+        android:id="@+id/folder_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="@dimen/folder_padding"
+        android:paddingRight="@dimen/folder_padding"
+        android:paddingTop="@dimen/folder_padding"
+        android:paddingBottom="@dimen/folder_padding"
+        android:cacheColorHint="#ff333333"
+        android:hapticFeedbackEnabled="false"
+        launcher:widthGap="@dimen/folder_width_gap"
+        launcher:heightGap="@dimen/folder_height_gap"
+        launcher:cellWidth="@dimen/folder_cell_width"
+        launcher:cellHeight="@dimen/folder_cell_height" />
+
+    <org.fairphone.launcher.FolderEditText
+        android:id="@+id/folder_name"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:paddingTop="@dimen/folder_name_padding"
+        android:paddingBottom="@dimen/folder_name_padding"
+        android:background="#00000000"
+        android:hint="@string/folder_hint_text"
+        android:textSize="14sp"
+        android:textColor="#ff33b5e5"
+        android:textColorHighlight="#ff333333"
+        android:gravity="center_horizontal"
+        android:singleLine="true"
+        android:imeOptions="flagNoExtractUi"/>
+</org.fairphone.launcher.Folder>
diff --git a/FairphoneHome/res/layout/wallpaper_chooser.xml b/FairphoneHome/res/layout/wallpaper_chooser.xml
new file mode 100644
index 0000000..4993076
--- /dev/null
+++ b/FairphoneHome/res/layout/wallpaper_chooser.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:background="@drawable/wallpaper_gallery_background">
+
+        <Gallery android:id="@+id/gallery"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:spacing="-4dp" />
+            
+        <Button android:id="@+id/set"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/wallpaper_instructions"
+            android:layout_gravity="center_horizontal" />
+    </LinearLayout>
+</RelativeLayout>
+
diff --git a/FairphoneHome/res/layout/wallpaper_chooser_base.xml b/FairphoneHome/res/layout/wallpaper_chooser_base.xml
new file mode 100644
index 0000000..b6eeed4
--- /dev/null
+++ b/FairphoneHome/res/layout/wallpaper_chooser_base.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <fragment class="org.fairphone.launcher.WallpaperChooserDialogFragment"
+        android:id="@+id/wallpaper_chooser_fragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</FrameLayout>
diff --git a/FairphoneHome/res/layout/wallpaper_item.xml b/FairphoneHome/res/layout/wallpaper_item.xml
new file mode 100644
index 0000000..bd3fa2b
--- /dev/null
+++ b/FairphoneHome/res/layout/wallpaper_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/wallpaper_image"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@drawable/wallpaper_gallery_item"
+    android:scaleType="fitXY"
+    android:focusable="true" />
diff --git a/FairphoneHome/res/layout/workspace_cling.xml b/FairphoneHome/res/layout/workspace_cling.xml
new file mode 100644
index 0000000..7866ddf
--- /dev/null
+++ b/FairphoneHome/res/layout/workspace_cling.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<org.fairphone.launcher.Cling
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    launcher:drawIdentifier="workspace_portrait">
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="90dp">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <TextView
+                style="@style/ClingTitleText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/workspace_cling_title" />
+            <TextView
+                style="@style/ClingText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/workspace_cling_move_item" />
+        </LinearLayout>
+    </FrameLayout>
+    <TextView
+        style="@style/ClingText"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginBottom="130dp"
+        android:layout_gravity="bottom"
+        android:gravity="center"
+        android:text="@string/workspace_cling_open_all_apps" />
+    <Button
+        style="@style/ClingButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="15dp"
+        android:layout_marginRight="10dp"
+        android:layout_gravity="bottom|right"
+        android:onClick="dismissWorkspaceCling" />
+</org.fairphone.launcher.Cling>
diff --git a/FairphoneHome/res/layout/workspace_divider.xml b/FairphoneHome/res/layout/workspace_divider.xml
new file mode 100644
index 0000000..c9cbca6
--- /dev/null
+++ b/FairphoneHome/res/layout/workspace_divider.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:paddingLeft="@dimen/workspace_divider_padding_left"
+    android:paddingRight="@dimen/workspace_divider_padding_right"
+    android:paddingTop="@dimen/workspace_divider_padding_top"
+    android:paddingBottom="@dimen/workspace_divider_padding_bottom"
+    android:scaleType="fitXY"
+    android:src="@drawable/hotseat_track_holo" />
diff --git a/FairphoneHome/res/layout/workspace_screen.xml b/FairphoneHome/res/layout/workspace_screen.xml
new file mode 100644
index 0000000..b400abf
--- /dev/null
+++ b/FairphoneHome/res/layout/workspace_screen.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<!--
+FPNOTE : default values 
+android:paddingLeft="@dimen/cell_layout_left_padding"
+    android:paddingRight="@dimen/cell_layout_right_padding"
+    android:paddingTop="@dimen/cell_layout_top_padding"
+    android:paddingBottom="@dimen/cell_layout_bottom_padding"
+-->
+
+<org.fairphone.launcher.CellLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="#33002200"
+    android:hapticFeedbackEnabled="false"
+    android:paddingBottom="0dp"
+    android:paddingLeft="0dp"
+    android:paddingRight="0dp"
+    android:paddingTop="0dp"
+    launcher:cellHeight="@dimen/workspace_cell_height"
+    launcher:cellWidth="@dimen/workspace_cell_width"
+    launcher:heightGap="@dimen/workspace_height_gap"
+    launcher:maxGap="@dimen/workspace_max_gap"
+    launcher:widthGap="@dimen/workspace_width_gap" />
diff --git a/FairphoneHome/res/mipmap-hdpi/ic_launcher_application.png b/FairphoneHome/res/mipmap-hdpi/ic_launcher_application.png
new file mode 100644
index 0000000..b9aa101
--- /dev/null
+++ b/FairphoneHome/res/mipmap-hdpi/ic_launcher_application.png
Binary files differ
diff --git a/FairphoneHome/res/mipmap-hdpi/ic_launcher_wallpaper.png b/FairphoneHome/res/mipmap-hdpi/ic_launcher_wallpaper.png
new file mode 100644
index 0000000..affee85
--- /dev/null
+++ b/FairphoneHome/res/mipmap-hdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/FairphoneHome/res/mipmap-hdpi/icon_launcher_home.png b/FairphoneHome/res/mipmap-hdpi/icon_launcher_home.png
new file mode 100644
index 0000000..0919bfd
--- /dev/null
+++ b/FairphoneHome/res/mipmap-hdpi/icon_launcher_home.png
Binary files differ
diff --git a/FairphoneHome/res/raw/fp_buy_a_phone_start_a_movement.mp4 b/FairphoneHome/res/raw/fp_buy_a_phone_start_a_movement.mp4
new file mode 100644
index 0000000..9407968
--- /dev/null
+++ b/FairphoneHome/res/raw/fp_buy_a_phone_start_a_movement.mp4
Binary files differ
diff --git a/FairphoneHome/res/raw/public_key.pem b/FairphoneHome/res/raw/public_key.pem
new file mode 100644
index 0000000..e25387d
--- /dev/null
+++ b/FairphoneHome/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/FairphoneHome/res/values-af/strings.xml b/FairphoneHome/res/values-af/strings.xml
new file mode 100644
index 0000000..72ba855
--- /dev/null
+++ b/FairphoneHome/res/values-af/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Lanseerpoort"</string>
+    <string name="home" msgid="5921706419368316758">"Tuis"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Kernprogramme"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Kies muurpapier uit"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Stel muurpapier"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Muurpapiere"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Program is nie geïnstalleer nie."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Legstukke"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Raak en hou in om \'n legstuk op te tel."</string>
+    <string name="market" msgid="2652226429823445833">"Winkel"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Kan nie item op hierdie Tuis-skerm laat los nie."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Kies legstuk om te skep"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Vouernaam"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Hernoem vouer"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Kanselleer"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Voeg by Tuis-skerm"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Programme"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Kortpaaie"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Legstukke"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Muurpapier"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Geen spasie op tuisskerms oor nie."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Geen meer spasie op tuisskerm nie."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Geen plek meer op die warmlaai nie."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Hierdie legstuk is te groot vir die hoofposisie."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is geskep."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is verwyder."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" bestaan reeds."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Kies kortpad"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Kies program"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Programme"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Tuis"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Verwyder"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deïnstalleer"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Verwyder"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Deïnstalleer"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Programinligting"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Soek"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Stemsoektog"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Programme"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Verwyder"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Deïnstalleer opdatering"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Voeg by"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Bestuur programme"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Muurpapier"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Soek"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Kennisgewings"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Stelselinstellings"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Hulp"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Deïnstalleer program"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Programbesonderhede"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 program gekies"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 legstuk gekies"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 vouer gekies"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 kortpad gekies"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"installeer kortpaaie"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Stel \'n program in staat om kortpaaie by te voeg sonder gebruikerhandeling."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"deïnstalleer kortpaaie"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Laat die program toe om kortpaaie te sonder gebruikerhandeling te verwyder."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"lees Tuis-instellings en -kortpaaie"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Laat die program toe om die instellings en kortpaaie in Tuis te lees."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"skryf Tuis-instellings en -kortpaaie"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Laat die program toe om die instellings en kortpaaie in Tuis te verander."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Kon nie legstuk laai nie"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Hierdie is \'n stelselprogram en kan nie gedeïnstalleer word nie."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Vuurpyllanseerder"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Naamlose vouer"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Tuisskerm %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Bladsy %1$d van %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Tuisskerm %1$d van %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Programme-bladsy %1$d van %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Legstukke-bladsy %1$d van %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Maak jouself tuis"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Jy kan jou gunsteling programme hier berg."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Om al jou programme te sien, raak die sirkel."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Kies \'n paar programme"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Om \'n program by jou Tuisskerm te voeg, raak en hou dit."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organiseer jou programme met vouers"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Om \'n program te skuif, raak en hou dit."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Om \'n nuwe vouer op jou Tuisskerm te maak, stapel een program bo-op \'n ander."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Vouer oopgemaak, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Raak om vouer toe te maak"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Raak om stoor te hernoem"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Vouer is gesluit"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Vouer hernoem na <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Vouer: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-am/strings.xml b/FairphoneHome/res/values-am/strings.xml
new file mode 100644
index 0000000..a1bfb2e
--- /dev/null
+++ b/FairphoneHome/res/values-am/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"አስነሺ"</string>
+    <string name="home" msgid="5921706419368316758">"መነሻ"</string>
+    <string name="uid_name" msgid="3371120195364560632">"የAndroid ኮር ትግበራዎች"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"ልጣፍ ምረጥ ከ"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"ልጣፍ አዘጋጅ"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"ልጥፎች"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"ትግበራ አልተጫነም።"</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">" ፍርግሞች"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"ፍርግም ለማንሳት ይንክ እና በመጫን ይያዙ"</string>
+    <string name="market" msgid="2652226429823445833">"ሸምት"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"እዚህ የመነሻ ማያ ላይ ንጥል ማኖር አልተቻለም።"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"ለመፍጠር ምግብር  ምረጥ"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"አቃፊ ስም"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"አቃፊ እንደገና ሰይም"</string>
+    <string name="rename_action" msgid="6016003384693240896">"እሺ"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"ይቅር"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"ወደ መነሻ ማያ አክል"</string>
+    <string name="group_applications" msgid="2103752818818161976">"መተግበሪያዎች"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"አቋራጮች"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"ፍርግሞች"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"ልጣፍ"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"የመነሻ ማያ ገጾችህ ላይ ተጨማሪ ቦታ የለም።"</string>
+    <string name="out_of_space" msgid="8365249326091984698">"በዚህ መነሻ ማያ ላይ ምንም ቦታ የለም።"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"በመትከያ ቦታው ላይ ተጨማሪ ክፍል የለም።"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"ይህ ፍርግም ለማስቀመጫው በጣም ትልቅ ነው።"</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"አቋራጭ\"<xliff:g id="NAME">%s</xliff:g> \"ተፈጥሯል።"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"አቋራጭ \"<xliff:g id="NAME">%s</xliff:g>\" ተወግዶ ነበር።"</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"አቋራጭ \"<xliff:g id="NAME">%s</xliff:g>\" አስቀድሞ አለ።"</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"አቋራጭ ምረጥ"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"መተግበሪያ ምረጥ"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"ትግበራ"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"መነሻ"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"አስወግድ"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"አራግፍ"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"አስወግድ"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"አራግፍ"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"የትግበራ መረጃ"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"ፈልግ"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"የድምፅ ፍለጋ"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"መተግበሪያዎች"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"አስወግድ"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"ማዘመን አትጫን"</string>
+    <string name="menu_add" msgid="3065046628354640854">"አክል"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"ትግበራዎች አደራጅ"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"ልጣፍ"</string>
+    <string name="menu_search" msgid="4826514464423239041">" ፈልግ"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"ማሳወቂያዎች"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"የስርዓት ቅንብሮች"</string>
+    <string name="menu_help" msgid="4901160661634590633">"እገዛ"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"ትግበራ አራግፍ"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"የትግበራ ዝርዝር"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 መተግበሪያ  ተመርጧል"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 ፍርግም ተመርጧል"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 አቃፊ ተመርጧል"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 አቋራጭ ተመርጧል"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"አቋራጮችን ጫን።"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"መተግበሪያ  ያለተጠቃሚ ጣልቃ ገብነት አቋራጭ ለማከል ይፈቅዳል።"</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"አቋራጮችን አራግፍ"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"ያለተጠቃሚ ጣልቃ ገብነት አቋራጭ ለማስወገድ ለመተግበሪያ ይፈቅዳል።"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"የመነሻ ቅንብሮች እና አቋራጮችን ያንብቡ"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"ቅንብሮችን እና አቋራጮችን በመነሻ ለማንበብ ለትግበራ ይፈቅዳል።"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"መነሻ ቅንብሮች እና አቋራጮች ፃፍ"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"ቅንብሮችን እና አቋራጮችን በመነሻ ለመለወጥ ለመተግበሪያ ይፈቅዳል።"</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"ፍርግም የመጫን ችግር"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"ይህ የስርዓት ትግበራ ነው እና አለማራገፍ አይቻልም።"</string>
+    <string name="dream_name" msgid="2847171357608437154">"የሮኬት ማስነሻ"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"ስም አልባ አቃፊ"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"መነሻ ማያ ገጽ %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"ገጽ %1$d የ %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"መነሻ ማያ ገጽ %1$d ከ%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Appsገጽ %1$d የ %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"ፍርግሞች ገጽ %1$d የ %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"እቤትዎ እንዳሉ ሆነው ዘና ይበሉ"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"ተወዳጅ መተግበሪያዎችዎን እዚህ ላይ ማስቀመጥ ይችላሉ።"</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"ሁሉንም መተግበሪያዎችዎን ለማየት፣ ክቡን ይንኩ"</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"አንዳንድ መተግበሪያዎችን ይምረጡ"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"ወደ መነሻ ማያዎ፣ መተግበሪያ ለማከል፣ ይንኩት እና ይያዙ።"</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"መተግበሪያዎችዎን ከዓቃፊዎች ጋር ያደራጁ"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"መተግበሪያ ለማንቀሳቀስ፣ ይንኩት እና ይያዙት"</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"በመነሻ ማያዎ ላይ አዲስ ዓቃፊ ለመፍጠር፣ አንዱን መተግበሪያ በሌላው ላይ ይቆልሉ።"</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"እሺ"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"አቃፊ ተከፍቷል፣ <xliff:g id="WIDTH">%1$d</xliff:g> በ <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"አቃፊን ለመዝጋት ንካ"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"ዳግም ሰይምን ለማስቀመጥ ንካ"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"አቃፊ ተዘግቷል"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"አቃፊ ዳግም ወደ <xliff:g id="NAME">%1$s</xliff:g> ተሰይሟል"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"አቃፊ ስም፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ar/strings.xml b/FairphoneHome/res/values-ar/strings.xml
new file mode 100644
index 0000000..0ddd369
--- /dev/null
+++ b/FairphoneHome/res/values-ar/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"المشغل"</string>
+    <string name="home" msgid="5921706419368316758">"المنزل"</string>
+    <string name="uid_name" msgid="3371120195364560632">"تطبيقات Android المركزية"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"اختيار خلفية من"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"تعيين خلفية"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"الخلفيات"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"لم يتم تثبيت التطبيق."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"الأدوات"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"المس مع الاستمرار لاختيار إحدى الأدوات."</string>
+    <string name="market" msgid="2652226429823445833">"تسوق"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"تعذر إسقاط العنصر في هذه الشاشة الرئيسية."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"اختيار أداة لإنشائها"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"اسم المجلد"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"إعادة تسمية المجلد"</string>
+    <string name="rename_action" msgid="6016003384693240896">"موافق"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"إلغاء"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"إضافة إلى الشاشة الرئيسية"</string>
+    <string name="group_applications" msgid="2103752818818161976">"تطبيقات"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"الاختصارات"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"الأدوات"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"الخلفيات"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"ليس هناك مساحة أخرى في الشاشات الرئيسية."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"ليس هناك مساحة أخرى في هذه الشاشة الرئيسية."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"ليست هناك مساحة أخرى في منطقة الإرساء القابلة للتخصيص."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"حجم هذه الأداة كبير للغاية بحيث لا يتسع له الموقع المهم."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"تم إنشاء الاختصار \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"تمت إزالة الاختصار \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"الاختصار \"<xliff:g id="NAME">%s</xliff:g>\" موجود فعلاً."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"اختيار اختصار"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"اختيار تطبيق"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"التطبيقات"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"الرئيسية"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"إزالة"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"إزالة"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"إزالة"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"إزالة"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"معلومات التطبيق"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"بحث"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"البحث الصوتي"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"التطبيقات"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"إزالة"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"إزالة التحديث"</string>
+    <string name="menu_add" msgid="3065046628354640854">"إضافة"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"إدارة التطبيقات"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"خلفية"</string>
+    <string name="menu_search" msgid="4826514464423239041">"بحث"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"التنبيهات"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"إعدادات النظام"</string>
+    <string name="menu_help" msgid="4901160661634590633">"مساعدة"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"إزالة التطبيق"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"تفاصيل التطبيق"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"تم تحديد تطبيق واحد"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"تم تحديد أداة واحدة"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"تم تحديد مجلد واحد"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"تم تحديد اختصارٍ واحد"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"اختصارات التثبيت"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"للسماح لتطبيق ما بإضافة اختصارات بدون تدخل المستخدم."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"إزالة الاختصارات"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"للسماح للتطبيق بإزالة الاختصارات بدون تدخل المستخدم."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"قراءة إعدادات الشاشة الرئيسية والاختصارات"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"للسماح للتطبيق بقراءة الإعدادات والاختصارات في الصفحة الرئيسية."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"كتابة إعدادات الشاشة الرئيسية والاختصارات"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"للسماح للتطبيق بتغيير الإعدادات والاختصارات في الصفحة الرئيسية."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"حدثت مشكلة أثناء تحميل الأداة"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"هذا تطبيق نظام وتتعذر إزالته."</string>
+    <string name="dream_name" msgid="2847171357608437154">"راجمة"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"مجلد بدون اسم"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"الشاشة الرئيسية %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"الصفحة %1$d من %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"الشاشة الرئيسية %1$d من %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"صفحة التطبيقات %1$d من %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"صفحة الأدوات %1$d من %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"لك مطلق الحرية لتفعل ما تشاء"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"يمكنك وضع التطبيقات المفضلة هنا."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"للاطلاع على جميع التطبيقات، المس الدائرة."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"اختر بعض التطبيقات"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"لإضافة تطبيق إلى الشاشة الرئيسية، المسه مع الاستمرار."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"تنظيم التطبيقات باستخدام المجلدات"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"لنقل التطبيق، المسه مع الاستمرار."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"لإنشاء مجلد جديد على الشاشة الرئيسية، يمكنك تكديس أحد التطبيقات فوق تطبيق آخر."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"موافق"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"تم فتح المجلد، بحجم <xliff:g id="WIDTH">%1$d</xliff:g> في <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"المس لإغلاق المجلد"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"المس لحفظ إعادة التسمية"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"تم إغلاق المجلد"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"تمت إعادة تسمية المجلد إلى <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"المجلد: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-be/strings.xml b/FairphoneHome/res/values-be/strings.xml
new file mode 100644
index 0000000..150434f
--- /dev/null
+++ b/FairphoneHome/res/values-be/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Панэль запуску"</string>
+    <string name="home" msgid="5921706419368316758">"На галоўную старонку"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Асноўныя прыкладанні для Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Выбраць шпалеры"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Усталяваць шпалеры"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Шпалеры"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Прыкладанне не ўсталявана."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Віджэты"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Націсніце і ўтрымлiвайце віджэт, каб дадаць яго."</string>
+    <string name="market" msgid="2652226429823445833">"Крама"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Немагчыма выдалiць элемент на галоўным экране."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Выберыце віджэт для стварэння"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Назва тэчкі"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Пераназваць тэчку"</string>
+    <string name="rename_action" msgid="6016003384693240896">"ОК"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Адмяніць"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Дадаць на Галоўную старонку"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Прыкладаннi"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Хуткі доступ"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Віджэты"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Шпалеры"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"На галоўных экранах больш няма месца."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"На Галоўнай старонцы больш няма месца."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"На Hotseat больш няма месца."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Гэты віджэт занадта вялікі для hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Створаны цэтлік \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Цэтлік \"<xliff:g id="NAME">%s</xliff:g>\" быў выдалены."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Цэтлік \"<xliff:g id="NAME">%s</xliff:g>\" ужо існуе."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Выберыце шлях хуткага доступу"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Выберыце прыкладанне"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Прыкладанні"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Галоўная старонка"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Выдаліць"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Выдаліць"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Выдаліць"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Выдаліць"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Інфармацыя прыкладання"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Пошук"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Галасавы пошук"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Прыкладаннi"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Выдаліць"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Выдаліць абнаўленні"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Дадаць"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Кіраваць прыкладаннямі"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Шпалеры"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Пошук"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Абвесткі"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Сістэмныя налады"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Даведка"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Выдалiць прыкладанне"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Звесткi пра прыкладанне"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Выбрана 1 прыкладанне"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Выбраны 1 віджэт"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Выбрана 1 тэчка"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Выбраны 1 цэтлік"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"усталяваць хуткі доступ"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Дазваляе прыкладанням дадаваць цэтлікі без умяшання карыстальніка."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"выдаліць хуткі доступ"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Дазваляе прыкладанням выдаляць шляхi хуткага доступу без умяшання карыстальнiка."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"чытаць налады і спосабы хуткага доступу на Галоўнай старонцы"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Дазваляе прыкладанню чытаць налады і шляхі хуткага доступу на галоўнай старонцы."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"напісаць налады і спосабы хуткага доступа на Галоўнай старонцы"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Дазваляе прыкладанню змяняць налады і шляхi хуткага доступу на галоўнай старонцы."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Праблема пры загрузцы віджэта"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Гэта сістэмнае прыкладанне, і яго нельга выдаліць."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Папка без назвы"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Галоўны экран %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Старонка %1$d з %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Галоўны экран %1$d of %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Старонка з прыкладаннямi: %1$d з %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Старонка з вiджэтамi %1$d з %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Будзьце як дома"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Тут вы можаце змясціць свае любімыя прыкладанні."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Каб убачыць усе свае прыкладанні, дакраніцеся да круга."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Выберыце некалькі прыкладанняў"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Каб дадаць прыкладанне на галоўны экран, дакраніцеся і ўтрымлівайце яго."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Арганізуйце свае прыкладанні па тэчках"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Каб перамясціць прыкладанне, дакраніцеся дя яго і ўтрымлівайце."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Каб зрабіць новую тэчку на працоўным стале, перасуньце адно прыкладанне на другое."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"ОК"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Тэчка адкрыта, <xliff:g id="WIDTH">%1$d</xliff:g> на <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Нацiснiце, каб закрыць тэчку"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Краніце, каб захаваць новую назву"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Тэчка закрыта"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Тэчка перайменавана ў <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Тэчка <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-bg/strings.xml b/FairphoneHome/res/values-bg/strings.xml
new file mode 100644
index 0000000..f435ff6
--- /dev/null
+++ b/FairphoneHome/res/values-bg/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Стартов панел"</string>
+    <string name="home" msgid="5921706419368316758">"Начало"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Основни приложения на Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Избор на тапет от"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Задаване на тапет"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Тапети"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Приложението не е инсталирано."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Приспособления"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Докоснете и задръжте за избор на приспособление"</string>
+    <string name="market" msgid="2652226429823445833">"Магазин"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Не можа да се премести на началния екран."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Избор на приспособл. за създаване"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Име на папка"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Преименуване на папка"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Отказ"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Добавяне към началния екран"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Приложения"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Преки пътища"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Приспособления"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Тапети"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"На началните ви екрани няма повече място."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"На този начален екран няма повече място."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"В трамплина няма повече място."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Това приспособление е твърде голямо за трамплина."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Прекият път за „<xliff:g id="NAME">%s</xliff:g>“ бе създаден."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Прекият път към „<xliff:g id="NAME">%s</xliff:g>“ бе премахнат."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Прекият път за „<xliff:g id="NAME">%s</xliff:g>“ вече съществува."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Избор на пряк път"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Избор на приложение"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Приложения"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Начало"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Премахване"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталиране"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Премахване"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Деинсталиране"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Информация за приложението"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Търсене"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Гласово търсене"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Приложения"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Премахване"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинстал. на актуализацията"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Добавяне"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Управление на приложенията"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Тапет"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Търсене"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Известия"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Системни настройки"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Помощ"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Деинсталиране на приложението"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Подробности за приложението"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Избрано е 1 приложение"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Избрано е 1 приспособление"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Избрана е 1 папка"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Избран е 1 пряк път"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"инсталиране на преки пътища"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Разрешава на приложението да добавя преки пътища без намеса на потребителя."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"деинсталиране на преките пътища"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Разрешава на приложението да премахва преките пътища без намеса на потребителя."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"прочетете настройките за „Начало“ и преки пътища"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Разрешава на приложението да чете настройките и преките пътища в Начало."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"въведете настройките за „Начало“ и преки пътища"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Разрешава на приложението да променя настройките и преките пътища в Начало."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Проблем при зареждане на приспособление"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Това е системно приложение и не може да се деинсталира."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Ракетна площадка"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Папка без име"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Начален екран %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Страница %1$d от %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Начален екран %1$d от %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Страница с приложения %1$d от %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Страница с приспособления %1$d от %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Настанете се като у дома си"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Тук можете да поставите любимите си приложения."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"За да видите всичките си приложения, докоснете кръга."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Изберете някои приложения"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"За да добавите приложение към началния си екран, го докоснете и задръжте."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Организирайте приложенията си с папки"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"За да преместите приложение, го докоснете и задръжте."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"За да създадете нова папка на началния си екран, поставете едно приложение върху друго."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Папката е отворена – <xliff:g id="WIDTH">%1$d</xliff:g> на <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Докоснете, за да затворите папката"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Докоснете, за да запазите преименуването"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Папката бе затворена"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Папката е преименувана на „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ca/strings.xml b/FairphoneHome/res/values-ca/strings.xml
new file mode 100644
index 0000000..dc1f72f
--- /dev/null
+++ b/FairphoneHome/res/values-ca/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Menú d\'aplicacions"</string>
+    <string name="home" msgid="5921706419368316758">"Casa"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Aplicacions principals d\'Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Selecciona fons de pantalla de"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Estableix el fons de pantalla"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Fons de pantalla"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"L\'aplicació no s\'ha instal·lat."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Mantén premut un widget per triar-lo."</string>
+    <string name="market" msgid="2652226429823445833">"Botiga"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"No s\'ha pogut deixar anar aquest element a la pantalla d\'inici."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Selecciona el widget que vulguis crear"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nom de la carpeta"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Canvi de nom de carpeta"</string>
+    <string name="rename_action" msgid="6016003384693240896">"D\'acord"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Cancel·la"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Addició a la pantalla Inici"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplicacions"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Dreceres"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Fons de pantalla"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"No queda espai a les pantalles d\'inici."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Ja no queda espai en aquesta pantalla Inici."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"No queda espai al hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Aquest widget és massa gran per al hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"S\'ha creat la drecera \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"S\'ha eliminat la drecera \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"La drecera \"<xliff:g id="NAME">%s</xliff:g>\" ja existeix."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Tria una drecera"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Tria una aplicació"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplicacions"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Pàgina d\'inici"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Elimina"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstal·la"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Elimina"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstal·la"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informació de l\'aplicació"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Cerca"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Cerca per veu"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplicacions"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Elimina"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstal·la l\'actualització"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Afegeix"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Gestiona les aplicacions"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Fons de pantalla"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Cerca"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notificacions"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Configuració del sistema"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ajuda"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Desinstal·la aplicacions"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Detalls de l\'aplicació"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Una aplicació seleccionada"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget seleccionat"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 carpeta seleccionada"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 drecera seleccionada"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instal·lar dreceres"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permet a una aplicació afegir dreceres sense intervenció de l\'usuari."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstal·lar dreceres"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permet que l\'aplicació elimini dreceres sense la intervenció de l\'usuari."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"llegir la configuració i les dreceres de la pantalla Inici"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permet que una aplicació llegeixi la configuració i les dreceres de la pàgina d\'inici."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"escriure la configuració i les dreceres de la pantalla Inici"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permet que una aplicació canviï la configuració i les dreceres de la pàgina d\'inici."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"S\'ha produït un problema en carregar el widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Això és una aplicació del sistema i no es pot desinstal·lar."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Llançamíssils"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Carpeta sense nom"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Pantalla d\'inici %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Pàgina %1$d de %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Pantalla d\'inici %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Pàgina d\'aplicacions %1$d de %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Pàgina de widgets %1$d de %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Personalitza el teu escriptori"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Ací pots col·locar les teves aplicacions preferides."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Per veure totes les aplicacions, toca el cercle."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Tria algunes aplicacions"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Per afegir una aplicació a la pantalla d\'inici, mantén-la premuda."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organitza les teves aplicacions amb carpetes"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Per moure una aplicació, mantén-la premuda."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Per fer una carpeta nova a la pàgina d\'inici, apila una aplicació sobre una altra."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"D\'acord"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"S\'ha obert la carpeta, <xliff:g id="WIDTH">%1$d</xliff:g> per <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Toca per tancar la carpeta"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Toca per desar el canvi de nom"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Carpeta tancada"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"S\'ha canviat el nom de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-cs/strings.xml b/FairphoneHome/res/values-cs/strings.xml
new file mode 100644
index 0000000..dea19f6
--- /dev/null
+++ b/FairphoneHome/res/values-cs/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Plocha"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Vybrat tapetu:"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Nastavit tapetu"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Tapety"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Aplikace není nainstalována."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgety"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Widget vyberete dotykem a podržením."</string>
+    <string name="market" msgid="2652226429823445833">"Obchod"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Na tuto plochu položku nelze přesunout."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Vyberte widget k vytvoření"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Název složky"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Přejmenovat složku"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Zrušit"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Přidat na plochu"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplikace"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Zástupce"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgety"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Tapety"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Na plochách již není místo."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Na této ploše již není místo."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"V části hotseat již není místo."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Widget je pro hotseat příliš velký."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Zástupce <xliff:g id="NAME">%s</xliff:g> byl vytvořen."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Zástupce <xliff:g id="NAME">%s</xliff:g> byl odebrán."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Zástupce <xliff:g id="NAME">%s</xliff:g> již existuje."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Výběr zástupce"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Vybrat aplikaci"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplikace"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Plocha"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odebrat"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstalovat"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Odstranit"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Odinstalovat"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informace o aplikaci"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Hledat"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hlasové vyhledávání"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplikace"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Odebrat"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstalovat aktualizaci"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Přidat"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Spravovat aplikace"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Hledat"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Oznámení"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Systémová nastavení"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Nápověda"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Odinstalovat aplikaci"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Podrobnosti o aplikaci"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Vybrána 1 aplikace"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Vybrán 1 widget"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Vybrána 1 složka"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Vybrán 1 zástupce"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalovat zástupce"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Umožňuje aplikaci přidat zástupce bez zásahu uživatele."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"odinstalace zástupců"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Umožňuje aplikaci odstranit zástupce bez zásahu uživatele."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"čtení nastavení a odkazů plochy"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Umožňuje aplikaci číst nastavení a odkazy na ploše."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"zápis nastavení a odkazů plochy"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Umožňuje aplikaci změnit nastavení a odkazy na ploše."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problém s načtením widgetu"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Raketomet"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Složka bez názvu"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Plocha %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Strana %1$d z %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Plocha %1$d z %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Stránka aplikací %1$d z %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Stránka widgetů %1$d z %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Chovejte se jako doma"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Sem můžete umístit své oblíbené aplikace."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Chcete-li zobrazit všechny aplikace, dotkněte se kruhu."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Vyberte nějaké aplikace"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Chcete-li na plochu přidat aplikaci, dotkněte se jí a přidržte ji."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Uspořádat aplikace pomocí složek"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Chcete-li aplikaci přesunout, dotkněte se jí a přidržte ji."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Chcete-li na ploše vytvořit novou složku, přesuňte jednu aplikaci na druhou."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Složka otevřena, rozměry <xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Dotykem složku zavřete"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Dotykem uložíte změnu názvu"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Složka je uzavřena"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Složka přejmenována na <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Složka: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-da/strings.xml b/FairphoneHome/res/values-da/strings.xml
new file mode 100644
index 0000000..af00d82
--- /dev/null
+++ b/FairphoneHome/res/values-da/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Startside"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android-kerneprogrammer"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Vælg baggrund fra"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Angiv tapet"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Tapeter"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Appen er ikke installeret."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Tryk og hold nede for at vælge en widget."</string>
+    <string name="market" msgid="2652226429823445833">"Butik"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Elementet kunne ikke trækkes til startskærmen."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Vælg en widget for at oprette"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Mappenavn"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Omdøb mappe"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Annuller"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Føj til Startskærm"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apps"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Genveje"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Tapeter"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Der er ikke mere plads på dine startskærme."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Der er ikke mere plads på Startskærmen."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Der er ikke mere plads i hotseatet."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Denne widget er for stor til hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev oprettet."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev fjernet."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" findes allerede."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Vælg genvej"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Vælg app"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Applikationer"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Start"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Afinstaller"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Fjern"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Afinstaller"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Oplysninger om appen"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Søg"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Stemmesøgning"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apps"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Fjern"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Afinstaller opdatering"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Tilføj"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Administrer apps"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Tapet"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Søg"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Underretninger"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Systemindstillinger"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Hjælp"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Afinstaller appen"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Oplysninger om app"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 valgt app"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget er valgt"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mappe er valgt"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 genvej er valgt"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"installer genveje"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Tillader, at en app tilføjer genveje uden brugerens indgriben."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"afinstaller genveje"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Tillader, at appen fjerner genveje uden brugerens indgriben."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"læs indstillinger og genveje for Start"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Tillader, at appen læser indstillingerne og genvejene på startskærmen."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"skriv indstillinger og genveje for Start"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Tillader, at appen ændrer indstillingerne og genvejene på startskærmen."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Der er problemer med indlæsning af widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Dette er en systemapp, som ikke kan afinstalleres."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Unavngiven mappe"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Startskærm %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Side %1$d ud af %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Startskærm %1$d ud af %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Apps-side %1$d ud af %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widgets-side %1$d ud af %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Føl dig hjemme"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Du kan sætte dine yndlingsapps her."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Tryk på cirklen for at få vist alle dine apps."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Vælg nogle apps"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Hvis du vil føje en app til startskærmen, skal du trykke på den og holde den nede."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organiser dine apps med mapper"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Tryk på en app, og hold den nede for at flytte den."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Du kan oprette en ny mappe på din startskærm ved at stable apps oven på hinanden."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Åben mappe, <xliff:g id="WIDTH">%1$d</xliff:g> gange <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Tryk for at lukke mappen"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Tryk for at gemme det nye navn"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mappen er lukket"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mappen er omdøbt til <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-de/strings.xml b/FairphoneHome/res/values-de/strings.xml
new file mode 100644
index 0000000..1577d80
--- /dev/null
+++ b/FairphoneHome/res/values-de/strings.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Fairphone OS"</string>
+    <string name="home" msgid="5921706419368316758">"Startbildschirm"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Hintergrund auswählen"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Hintergrund festlegen"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Hintergrund-Bilder"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"App ist nicht installiert."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Zum Hinzufügen Widget berühren und halten"</string>
+    <string name="market" msgid="2652226429823445833">"Shop"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Element wurde nicht auf Startbildschirm abgelegt."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Widget zum Erstellen auswählen"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Ordnername"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Ordner umbenennen"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Abbrechen"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Zum Startbildschirm hinzufügen"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apps"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Verknüpfungen"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Hintergründe"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Auf Ihrem Startbildschirm ist kein Platz mehr vorhanden."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Auf dem Startbildschirm ist kein Platz mehr vorhanden."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Kein Platz mehr auf der App-Leiste"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Dieses Widget ist zu groß für die App-Leiste."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"\"<xliff:g id="NAME">%s</xliff:g>\"-Verknüpfung wurde erstellt."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"\"<xliff:g id="NAME">%s</xliff:g>\"-Verknüpfung wurde entfernt."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"\"<xliff:g id="NAME">%s</xliff:g>\"-Verknüpfung ist bereits vorhanden."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Verknüpfung auswählen"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"App wählen"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startseite"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Entfernen"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstallieren"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Entfernen"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Deinstallieren"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"App-Info"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Suchen"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Sprachsuche"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apps"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Entfernen"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update deinstallieren"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Hinzufügen"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Apps verwalten"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Hintergrund"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Suchen"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Benachrichtigungen"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Systemeinstellungen"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Hilfe"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"App deinstallieren"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"App-Details"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 App ausgewählt"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 Widget ausgewählt"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 Ordner ausgewählt"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 Verknüpfung ausgewählt"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"Verknüpfungen installieren"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Ermöglicht einer App das Hinzufügen von Verknüpfungen ohne Eingriff des Nutzers"</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"Verknüpfungen deinstallieren"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Ermöglicht einer App das Entfernen von Verknüpfungen ohne Eingriff des Nutzers"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Einstellungen und Shortcuts für Startseite lesen"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Ermöglicht einer App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu lesen"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Einstellungen und Shortcuts für Startseite schreiben"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Ermöglicht einer App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu ändern"</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Fehler beim Laden des Widgets"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Raketenstartgerät"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Unbenannter Ordner"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Startbildschirm %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Seite %1$d von %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Startbildschirm %1$d von %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"App-Seite %1$d von %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widget-Seite %1$d von %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Fühlen Sie sich wie zu Hause"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Hier können Sie Ihre Lieblings-Apps ablegen."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Berühren Sie den Kreis für eine Übersicht aller Apps."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Apps auswählen"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Berühren und halten Sie eine App, um sie zum Startbildschirm hinzuzufügen."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Apps mit Ordnern organisieren"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Berühren und halten Sie eine App, um sie zu verschieben."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Stapeln Sie Apps übereinander, um einen neuen Ordner auf Ihrem Startbildschirm zu erstellen."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Ordner geöffnet, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Ordner durch Berühren schließen"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Umbenennung durch Berühren speichern"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Ordner wurde geschlossen"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Ordner umbenannt in <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Ordner: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+    
+    <!-- Fairphone -->
+    <!-- Your Apps -->
+    <string name="your_apps">Your Apps</string>
+    
+    <string name="last_used_apps">Zuletzt benutzte Apps</string>
+    <string name="last_used">Zuletzt benutzte</string>
+    <string name="most_used_apps">Meistbenutzte\nApps</string>
+    <string name="most_used">Meistbenutzte</string>
+    <string name="no_apps_have_been_opened_yet">Noch keine Apps geöffnet? Fangen Sie einfach an, Ihr Handy zu benutzen und kommen Sie zu diesem Bildschirm zurück</string>
+    <string name="reset">Zurücksetzen</string>
+    <string name="app_switcher_reset_message">Bist Du sicher?</string>
+    
+    <!-- Settings -->
+    <string name="energy_mood">Energy Mood im Sperr-Bildschirm aktivieren</string>
+    <string name="energy_mood_summary">Akkuladestatus als Hintergrundbild im Sperr-Bildschirm aktivieren</string>
+    
+    
+    <!-- Quick Access -->
+    <string name="quick_access">Quick Access</string>
+    <string name="edit">Bearbeiten</string>
+    <string name="favourite_apps">Lieblings-Apps</string>
+    <string name="drag_here_to_add">Ziehen Sie\nhier, um\nhinzuzufügen</string>
+    <string name="drag_here_to_remove">Zum\nLöschen hierher\nbewegen</string>
+    
+    <!-- OOBE Texts -->
+	<string name="oobe_quick_access">Quick Access</string>
+	<string name="oobe_select_language">Sprache\nauswählen</string>
+	<string name="oobe_setup_wifi">Setup\nWi-Fi</string>
+	<string name="oobe_intro_top">Willkommen! Sie halten ein Handy in Ihren Händen, bei dessen Herstellung soziale Werte an erster Stelle standen. Aber natürlich kann man damit auch telefonieren.</string>
+	<string name="oobe_intro_bottom">Wir zeigen Ihnen, wie es funktioniert</string>
+	
+	<string name="oobe_edge_swipe_title">Streichen Sie mit</string>
+	<string name="oobe_edge_swipe_text">Ihrem Finger von rechts oder links, ohne ihn hochzuheben</string>
+	<string name="oobe_open_app_title">Lassen Sie den Finger</string>
+	<string name="oobe_open_app_text">über einer App los, um sie zu öffnen</string>
+	
+	<string name="oobe_edit_drag_intro">Apps lassen sich bewegen und sind somit einfach zu bearbeiten</string>
+	
+	<string name="oobe_edit_drag_add_title">Zur rechten Spalte</string>
+	<string name="oobe_edit_drag_add_text">ziehen und ablegen, um zu den Favoriten hinzufügen</string>
+	
+	<string name="oobe_edit_drag_remove_title">Zur linken Spalte</string>
+	<string name="oobe_edit_drag_remove_text">ziehen und ablegen, um aus den Favoriten zu löschen</string>
+	
+	<string name="oobe_edit_drag_trade_title">Ziehen Sie</string>
+	<string name="oobe_edit_drag_trade_text">die Favoriten, um ihre Position zu tauschen</string>
+	
+	<string name="oobe_your_apps_intro">Ihre meistbenutzten Apps alle an einem einzigen Ort</string>
+	<string name="oobe_your_apps_learning">Ihr Handy kennt die meistbenutzten Apps und merkt sie sich für Sie</string>
+	<string name="oobe_your_apps_last_ones">Sie können auch die zuletzt benutzten Apps sehen</string>
+	<string name="oobe_your_apps_start_using">Fangen Sie an, Ihr Handy zu benutzen; die Apps warten hier auf Sie</string>
+	
+	<string name="oobe_start">Start</string>
+	<string name="oobe_back">Zurück</string>
+	<string name="oobe_skip">Überspringen</string>
+	<string name="oobe_next">Weiter</string>
+	<string name="oobe_done">Beenden</string>
+	
+	<!-- Google Apps Install Widget -->
+    <string name="google_apps_installer_name">Google Apps-Installer</string>
+	<string name="google_apps_initial_title">Installieren Sie\ndie Google Apps</string>
+	<string name="google_apps_disclaimer_title">Installieren Sie die Google Apps</string>
+	<string name="google_apps_disclaimer_description">Für das vollkommene mobile Android- und Google-Erlebnis, wie z. B. Google Play store, benötigt Ihr Handy einen zusätzlichen Inhalt und eine Extra-Software. Leider können wir weder diesen Inhalt vorinstallieren noch können wir ihn direkt zur Verfügung stellen, da Fairphone noch keine Lizenz für diesen besitzt. Wir verhandeln aber im Moment mit dem Inhaltseigentümer, um diese Lizenz zu erhalten.\nTippen Sie unten auf "Ich akzeptiere", um diesen Inhalt von einer externen sicheren Quelle herunterzuladen. Sie installieren diesen Inhalt auf Ihre eigene Verantwortung.\nWenn Sie nicht zustimmen, wird Ihr Handy natürlich immer noch mit den grundlegenden Android-Apps arbeiten, aber Sie werden einige Dienste von Google nicht durchführen können.</string>
+	<string name="google_apps_disclaimer_agree">Ich akzeptiere</string>
+	<string name="google_apps_denied_permissions_title">Berechtigungen verweigert</string>
+	<string name="google_apps_denied_permissions_description">Fairphone Launcher konnte nicht die erforderlichen Berechtigungen erhalten, um die Google Apps zu installieren. Wenn Sie VERWEIGERN ausgewählt haben, starten Sie bitte Ihren Installer neu und ERLAUBEN Sie die Berechtigungen.</string>
+	<string name="google_apps_reboot_failed_title">Fehlgeschlagener Neustart</string>
+	<string name="google_apps_reboot_failed_description">Google Apps sind installiert. Konnte das Gerät nicht neu gestartet werden, starten Sie es bitte manuell.</string>
+	<string name="google_apps_download_title">Google Apps werden heruntergeladen</string>
+	<string name="google_apps_unzip_title">Google Apps werden extrahiert</string>
+	<string name="google_apps_install_title">Google Apps werden installiert</string>
+	<string name="google_apps_reboot_title">Gerät wird neugestartet</string>
+	<string name="google_apps_permissions_description">Der Fairphone OS wird Sie jetzt nach einem Superuser-Zugriff fragen. Wir versichern Ihnen, dass dieser absolut sicher ist. Wählen Sie bitte ERLAUBEN aus, wenn gefragt.</string>
+	<string name="google_apps_permissions_title">Systemberechtigungen</string>
+	<string name="google_apps_reboot_description">Das System muss neu gestartet werden, um die Installation abzuschließen.\nBefolgen Sie nach dem Neustart die Schritte, um die Google Apps einzurichten.</string>
+	<string name="google_apps_uninstall_title">Google Apps wurden installiert</string>
+	<string name="google_apps_uninstall_description">Löschen Sie\ndiesen Installer</string>
+	<string name="google_apps_failed_download_title">Download fehlgeschlagen</string>
+	<string name="google_apps_failed_download_description">Heruntergeladene Dateien sind beschädigt. Möchten Sie es erneut versuchen?</string>
+	<string name="google_apps_download_error">Fehler beim Herunterladen der Dateien. Bitte versuchen Sie es erneut.</string>
+	<string name="google_apps_connection_title">WLAN deaktiviert</string>
+	<string name="google_apps_connection_description">Die Datei, die Sie herunterladen möchten, ist zu groß für mobile Verbindungen (~100 MB). Bitte aktivieren Sie die WLAN-Verbindung und versuchen Sie es erneut.</string>
+	
+</resources>
diff --git a/FairphoneHome/res/values-de/styles.xml b/FairphoneHome/res/values-de/styles.xml
new file mode 100644
index 0000000..a43afb5
--- /dev/null
+++ b/FairphoneHome/res/values-de/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="SubTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">11.3sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-4dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEDescriptionText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">13sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values-el/strings.xml b/FairphoneHome/res/values-el/strings.xml
new file mode 100644
index 0000000..78e153a
--- /dev/null
+++ b/FairphoneHome/res/values-el/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Αρχική σελίδα"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Βασικές εφαρμογές Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Επιλογή ταπετσαρίας από"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Ορισμός ταπετσαρίας"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Ταπετσαρίες"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Η εφαρμογή δεν έχει εγκατασταθεί."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Γραφικά στοιχεία"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Αγγίξτε παρατεταμένα για να πάρετε ένα γραφ.στοιχ."</string>
+    <string name="market" msgid="2652226429823445833">"Αγορές"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Αδυναμία τοποθέτησης στοιχείου στην Αρχική οθόνη."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Επιλ. γραφ. στοιχείο για δημιουργία"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Όνομα φακέλου"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Μετονομασία φακέλου"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Ακύρωση"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Προσθήκη στην αρχική οθόνη"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Εφαρμογές"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Συντομεύσεις"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Γραφικά στοιχεία"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Ταπετσαρίες"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Δεν υπάρχει άλλος χώρος στις Αρχικές οθόνες σας."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Δεν υπάρχει χώρος σε αυτήν την αρχική οθόνη."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Δεν υπάρχει άλλος χώρος στο hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Αυτό το γραφικό στοιχείο είναι πολύ μεγάλο για το hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Δημιουργήθηκε η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" καταργήθηκε."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" υπάρχει ήδη."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Επιλέξτε συντόμευση"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Επιλογή εφαρμογής"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Εφαρμογές"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Αρχική σελίδα"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Κατάργηση"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Κατάργηση εγκατάστασης"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Κατάργηση"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Κατάργηση εγκατάστασης"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Πληροφορίες εφαρμογής"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Αναζήτηση"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Φωνητική αναζήτηση"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Εφαρμογές"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Κατάργηση"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Κατάργηση εγκατάστασης ενημέρωσης"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Προσθήκη"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Διαχείριση εφαρμογών"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Ταπετσαρία"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Αναζήτηση"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Ειδοποιήσεις"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Ρυθμίσεις συστήματος"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Βοήθεια"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Κατάργηση εγκατάστασης εφαρμογής"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Λεπτομέρειες εφαρμογής"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Επιλέχθηκε 1 εφαρμογή"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Επιλέχθηκε 1 γραφικό στοιχείο"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Επιλέχθηκε 1 φάκελος"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Επιλέχθηκε 1 συντόμευση"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"εγκατάσταση συντομεύσεων"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων χωρίς την παρέμβαση του χρήστη."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"κατάργηση εγκατάστασης συντομεύσεων"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Επιτρέπει στην εφαρμογή την κατάργηση συντομεύσεων χωρίς την παρέμβαση του χρήστη."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"ανάγνωση ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"εγγραφή ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Επιτρέπει στην εφαρμογή την αλλαγή των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Παρουσιάστηκε πρόβλημα στη φόρτωση του γραφικού στοιχείου"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Αυτή είναι μια εφαρμογή συστήματος και δεν είναι δυνατή η κατάργηση της εγκατάστασής της."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Φάκελος χωρίς όνομα"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Αρχική οθόνη %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Σελίδα %1$d από %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Αρχική οθόνη %1$d από %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Σελίδα εφαρμογών %1$d από %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Σελίδα γραφικών στοιχείων %1$d από %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Νιώστε σαν να είστε στο σπίτι σας"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Μπορείτε να τοποθετήσετε εδώ τις αγαπημένες σας εφαρμογές."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Για να δείτε όλες τις εφαρμογές σας, αγγίξτε τον κύκλο."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Επιλέξτε κάποιες εφαρμογές"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Για να προσθέσετε μια εφαρμογή στην αρχική σας οθόνη, αγγίξτε την παρατεταμένα."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Οργανώστε τις εφαρμογές σας με φακέλους"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Για να μετακινήσετε μια εφαρμογή, αγγίξτε την παρατεταμένα."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Για να δημιουργήσετε ένα νέο φάκελο στην αρχική οθόνη, τοποθετήστε μια εφαρμογή πάνω σε μια άλλη."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Άνοιγμα φακέλου, <xliff:g id="WIDTH">%1$d</xliff:g> επί <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Αγγίξτε για να κλείσετε τον φάκελο"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Αγγίξτε για να αποθηκεύσετε το νέο όνομα"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Ο φάκελος έκλεισε"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Ο φάκελος μετονομάστηκε σε <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-en-rGB/strings.xml b/FairphoneHome/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..a792281
--- /dev/null
+++ b/FairphoneHome/res/values-en-rGB/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Fairphone Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Home"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Choose wallpaper from"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Set wallpaper"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Wallpaper"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"App isn\'t installed."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Touch &amp; hold to pick up a widget."</string>
+    <string name="market" msgid="2652226429823445833">"Shop"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Couldn\'t drop item on this Home screen."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Choose widget to create"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Folder name"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Rename folder"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Cancel"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Add to Home screen"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apps"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Shortcuts"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Wallpaper"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"No more room on your Home screens."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"No more room on this Home screen."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"No more room on the hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"This widget is too large for the hot-seat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" created."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" was removed."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Shortcut \"<xliff:g id="NAME">%s</xliff:g>\" already exists."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Choose shortcut"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Choose app"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remove"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Uninstall"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Remove"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Uninstall"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"App info"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Search"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Voice Search"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apps"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Remove"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Uninstall update"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Add"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Manage apps"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Wallpaper"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Search"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notifications"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"System settings"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Help"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Uninstall app"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"App details"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 app selected"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget selected"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 folder selected"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 shortcut selected"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"install shortcuts"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Allows an app to add shortcuts without user intervention."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"uninstall shortcuts"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Allows the app to remove shortcuts without user intervention."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"read Home settings and short cuts"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Allows an app to read the settings and shortcuts in Home."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"write Home settings and shortcuts"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Allows the app to change the settings and shortcuts in Home."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problem loading widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"This is a system application and cannot be uninstalled."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Unnamed Folder"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Home screen %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Page %1$d of %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Home screen %1$d of %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Apps page %1$d of %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widgets page %1$d of %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Make yourself at home"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"You can put your favourite apps here."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"To see all your apps, touch the circle."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Choose some apps"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"To add an app to your Home screen, touch &amp; hold it."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organise your apps with folders"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"To move an app, touch &amp; hold it."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"To make a new folder on your Home screen, stack one app on top of another."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Folder opened, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Touch to close folder"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Touch to save rename"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Folder closed"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-es-rUS/strings.xml b/FairphoneHome/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..faf1de9
--- /dev/null
+++ b/FairphoneHome/res/values-es-rUS/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"FairLauncher"</string>
+    <string name="home" msgid="5921706419368316758">"Casa"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Aplicaciones del núcleo de Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Elegir un fondo de pantalla de"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Definir como fondo de pantalla"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Papeles tapiz"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"No se instaló la aplicación."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Mantén presionado el widget que deseas elegir."</string>
+    <string name="market" msgid="2652226429823445833">"Comprar"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Error al soltar elemento en la pantalla principal"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Elegir los widgets para crear"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nombre de carpeta"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Cambiar nombre de carpeta"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Aceptar"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Cancelar"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Agregar a la pantalla Página principal"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplicaciones"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Accesos directos"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Papeles tapiz"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"No hay más espacio en tus pantallas principales."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"No hay más espacio en esta pantalla de la página principal"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"No queda espacio en la barra de accesos directos."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Este widget es demasiado grande para el banquillo."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" creado."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ha sido eliminado."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Elegir acceso directo"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Elegir una aplicación"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplicaciones"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Página principal"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Quitar"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Eliminar"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstalar"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Información de la aplicación"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Buscar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Búsqueda por voz"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplicaciones"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminar"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar la actualización"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Agregar"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Papel tapiz"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Buscar"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notificaciones"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Configuración del sistema"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ayuda"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Desinstalar la aplicación"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Detalles de la aplicación"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Se seleccionó una aplicación."</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Se seleccionó 1 widget"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Se seleccionó 1 carpeta"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Se seleccionó 1 acceso directo"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalar accesos directos"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permite que una aplicación agregue accesos directos sin que el usuario intervenga."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstalar papel tapiz"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permite que la aplicación elimine accesos directos sin que el usuario intervenga."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"leer configuración y accesos directos de la página principal"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permite que la aplicación lea la configuración y los accesos directos de la página principal."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"escribir configuración y accesos directos de la página principal"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permite que la aplicación cambie la configuración y los accesos directos de la página principal."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problema al cargar el widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Esta es una aplicación del sistema y no se puede desinstalar."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Lanzacohetes"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Carpeta sin nombre"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Pantalla principal %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Página %1$d de %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Pantalla principal %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Página de aplicaciones %1$d de %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Página de widgets %1$d de %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Ponte cómodo."</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Puedes colocar tus aplicaciones favoritas aquí."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Para ver todas las aplicaciones, toca el círculo."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Elige algunas aplicaciones."</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Mantén presionada la aplicación que deseas agregar a tu pantalla principal."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organiza tus aplicaciones en carpetas."</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Para mover una aplicación, tócala &amp; mantenla presionada."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Para crear una carpeta nueva en tu pantalla principal, coloca una aplicación encima de la otra."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Aceptar"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Carpeta abierta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Toca para cerrar la carpeta."</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Toca para guardar el nuevo nombre."</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Se cerró la carpeta."</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"El nombre de la carpeta se cambió a <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-es/strings.xml b/FairphoneHome/res/values-es/strings.xml
new file mode 100644
index 0000000..9a96684
--- /dev/null
+++ b/FairphoneHome/res/values-es/strings.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Fairphone OS"</string>
+    <string name="home" msgid="5921706419368316758">"Casa"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Aplicaciones básicas de Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Seleccionar fondo de pantalla de"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Establecer fondo de pantalla"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Fondos de pantalla"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"La aplicación no está instalada."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Mantén pulsado el widget que quieras seleccionar."</string>
+    <string name="market" msgid="2652226429823445833">"Tienda"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Error al arrastrar elemento a este escritorio"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Selecciona el widget que quieres añadir"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nombre de carpeta"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Cambiar nombre de carpeta"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Aceptar"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Cancelar"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Añadir al escritorio"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplicaciones"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Accesos directos"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Fondos de pantalla"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"No queda espacio en las pantallas del escritorio."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"No queda espacio en el escritorio."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"No queda espacio en la barra de accesos directos."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Este widget es demasiado grande para la barra de accesos directos."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Se ha creado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Se ha eliminado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Elegir acceso directo"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Selecciona una aplicación"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplicaciones"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Inicio"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminar del  escritorio"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Eliminar"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstalar"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Información de la aplicación"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Buscar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Búsqueda por voz"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplicaciones"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminar"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar actualización"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Añadir"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Fondo de pantalla"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Buscar"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notificaciones"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Ajustes del sistema"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ayuda"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Desinstalar la aplicación"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Información de la aplicación"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 aplicación seleccionada"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Se ha seleccionado un widget."</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Se ha seleccionado una carpeta."</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Se ha seleccionado un acceso directo."</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalar accesos directos"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permite que una aplicación añada accesos directos sin intervención del usuario."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstalar accesos directos"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permite que la aplicación elimine accesos directos sin intervención del usuario."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"leer información de accesos directos y de configuración del escritorio"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permite que la aplicación lea los ajustes y los accesos directos del escritorio."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"escribir información de accesos directos y de configuración del escritorio"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permite que las aplicaciones cambien los ajustes y los accesos directos del escritorio."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problema al cargar el widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Esta aplicación es del sistema y no se puede desinstalar."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Carpeta sin nombre"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Pantalla principal %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Página %1$d de %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Pantalla principal %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Página de aplicaciones %1$d de %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Página de widgets %1$d de %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Personaliza tu escritorio"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Aquí puedes poner tus aplicaciones favoritas."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Para ver todas las aplicaciones, toca el círculo."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Selecciona algunas aplicaciones"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Para añadir una aplicación al escritorio, solo tienes que mantenerla pulsada."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organiza tus aplicaciones en carpetas"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Para mover una aplicación, solo tienes que mantenerla pulsada."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Para crear una carpeta nueva en el escritorio, coloca una aplicación encima de otra."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Aceptar"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Carpeta abierta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Toca para cerrar la carpeta."</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Toca para cambiar el nuevo nombre."</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Carpeta cerrada"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Se ha cambiado el nombre de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>."</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+    
+    
+    <!-- Fairphone -->
+    <!-- Your Apps -->
+    <string name="your_apps">Your Apps</string>
+    
+    <string name="last_used_apps">Últimas aplicaciones usadas</string>
+    <string name="last_used">Últimas usadas</string>
+    <string name="most_used_apps">Aplicaciones\nmás usadas</string>
+    <string name="most_used">Más usadas</string>
+    <string name="no_apps_have_been_opened_yet">Aún no has usado tus aplicaciones?\nEmpieza a usar tu teléfono y regresa a esta pantalla.</string>
+    <string name="reset">Borrar</string>
+    <string name="app_switcher_reset_message">¿Estás seguro</string>
+    
+    <!-- Settings -->
+    <string name="energy_mood">Fondo de estado en la pantalla de bloqueo</string>
+    <string name="energy_mood_summary">Muestra el nivel de carga de la batería como color de fondo en la pantalla de bloqueo</string>
+   	
+   	<!-- Quick Access -->
+    <string name="quick_access">Quick Access</string>
+    <string name="edit">Editar</string>
+    <string name="favourite_apps">Aplicaciones favoritas</string>
+    <string name="drag_here_to_add">Arrastre\naquí para\nañadir</string>
+    <string name="drag_here_to_remove">Arrastre\naquí para\neliminar</string>
+    
+   	<!-- OOBE Textos -->
+   	<string name="oobe_quick_access">Quick Access</string>
+   	<string name="oobe_select_language">Seleccione\nIdioma</string>
+	<string name="oobe_setup_wifi">Configuración\nWi-Fi</string>
+	<string name="oobe_intro_top">Bienvenido! Tienes en tus manos un móvil hecho priorizando valores sociales. Pero sí, tambien puedes llamar con él.</string>
+	<string name="oobe_intro_bottom">Vamos a enseñarte como utilizarlo</string>
+	
+	<string name="oobe_edge_swipe_title">Desliza el dedo</string>
+	<string name="oobe_edge_swipe_text">la izquierda o la derecha sin levantarlo</string>
+	
+	<string name="oobe_open_app_title">Levanta el dedo</string>
+	<string name="oobe_open_app_text">sobre una aplicación para abrirla</string>
+	
+	<string name="oobe_edit_drag_intro">Arrastra los iconos de las aplicaciones para editarlos</string>
+	
+	<string name="oobe_edit_drag_add_title">Arrastra a la columna</string>
+	<string name="oobe_edit_drag_add_text">de la derecha para añadir a tus favoritos</string>
+	
+	<string name="oobe_edit_drag_remove_title">Arrastra a la columna</string>
+	<string name="oobe_edit_drag_remove_text">de la izquierda para borrar de tus favoritos</string>
+	
+	<string name="oobe_edit_drag_trade_title">Arrastra los iconos</string>
+	<string name="oobe_edit_drag_trade_text">para cambiar de posición</string>
+	
+	<string name="oobe_your_apps_intro">Tus aplicaciones más usadas en un solo lugar</string>
+	<string name="oobe_your_apps_learning">Tu teléfono recuerda las aplicaciones más usadas</string>
+	<string name="oobe_your_apps_last_ones">También puedes acceder a las usadas por última vez</string>
+	<string name="oobe_your_apps_start_using">Empieza a usar su teléfono, las aplicaciones estarán aquí esperándote</string>
+	
+	<string name="oobe_start">Empezar</string>
+	<string name="oobe_back">Anterior</string>
+	<string name="oobe_skip">Pasar</string>
+	<string name="oobe_next">Siguiente</string>
+	<string name="oobe_done">Terminar</string>
+	
+	<!-- Google Apps Install Widget -->
+    <string name="google_apps_installer_name">Instalador Google Apps</string>
+	<string name="google_apps_initial_title">Instalar\nGoogle Apps</string>
+	<string name="google_apps_disclaimer_title">Instalar Google Apps</string>
+	<string name="google_apps_disclaimer_description">Para tener acceso a la experiencia Google y Android completa como la Google Play Store, su teléfono necesita contenido y software adicional. Desafortunadamente, como Fairphone no tiene la licencia necesaria, no podemos pre-instalar este contenido, ni lo podemos providenciar directamente. Estamos trabajando con el propietario de los contenidos para lograr hacerlo.\nElija “Acepto” de seguida para descargar el contenido de una fuente externa segura. La instalación de este contenido es de su responsabilidad.\nSi no aceptar, su teléfono seguirá trabajando con aplicaciones Android basicas, pero va a perder algunos servicios Google.</string>
+	<string name="google_apps_disclaimer_agree">Acepto</string>
+	<string name="google_apps_denied_permissions_title">Permisiones negadas</string>
+	<string name="google_apps_denied_permissions_description">Fairphone OS no ha podido obtener las permisiones para instalar Google Apps. Si ha elegido NEGAR, reinicie el instalador e elija AUTORIZAR.</string>
+	<string name="google_apps_reboot_failed_title">Fallo al reiniciar</string>
+	<string name="google_apps_reboot_failed_description">Google Apps ha sido instalado. Fallo al reiniciar, por favor reinicie manualmente.</string>
+	<string name="google_apps_download_title">Descargando Google Apps</string>
+	<string name="google_apps_unzip_title">Extrayendo Google Apps</string>
+	<string name="google_apps_install_title">Instalando Google Apps</string>
+	<string name="google_apps_reboot_title">Reiniciando dispositivo</string>
+	<string name="google_apps_permissions_description">Fairphone OS le pedirá acceso de Superusuario. Le garantizamos que esta operación es completamente segura. Por favor elija PERMITIR cuando solicitado.</string>
+	<string name="google_apps_permissions_title">Permisiones de sistema</string>
+	<string name="google_apps_reboot_description">Necesita reiniciar el sistema para completar la instalación.\nDespués de la instalación, siga los pasos para configurar Google Apps.</string>
+	<string name="google_apps_uninstall_title">Google Apps instalado</string>
+	<string name="google_apps_uninstall_description">Borrar\neste instalador</string>
+	<string name="google_apps_failed_download_title">Fallo al descargar</string>
+	<string name="google_apps_failed_download_description">Los archivos descargados están corrompidos. Intentar otra vez?</string>
+	<string name="google_apps_download_error">Error al descargar los archivos. Por favor intente otra vez.</string>
+	<string name="google_apps_connection_title">Wi-Fi desconectado</string>
+	<string name="google_apps_connection_description">El archivo que está intentando descargar es muy largo para conexiones móviles (~100mb). Por favor conéctese al Wi-Fi e intente otra vez.</string>
+	
+</resources>
diff --git a/FairphoneHome/res/values-es/styles.xml b/FairphoneHome/res/values-es/styles.xml
new file mode 100644
index 0000000..bf29f45
--- /dev/null
+++ b/FairphoneHome/res/values-es/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="SubTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">11.3sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">14.5sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-2dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEDescriptionText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">13sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values-et/strings.xml b/FairphoneHome/res/values-et/strings.xml
new file mode 100644
index 0000000..78c983a
--- /dev/null
+++ b/FairphoneHome/res/values-et/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Käivitaja"</string>
+    <string name="home" msgid="5921706419368316758">"Kodu"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Androidi tuumrakendused"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Taustapildi valimiskoht:"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Määra taustapilt"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Taustapildid"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Rakendus pole installitud."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Vidinad"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Vidina valimiseks puudutage seda pikalt."</string>
+    <string name="market" msgid="2652226429823445833">"Pood"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Üksust ei saa sellele avaekraanile tuua."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Valige loomiseks vidin"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Kausta nimi"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Nimeta kaust ümber"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Tühista"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Lisa avamenüüsse"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Rakendused"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Otseteed"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Vidinad"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Taustapildid"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Teie avakuvadel ei ole enam ruumi."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Sellel avalehel pole enam ruumi."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Kohandataval dokialal pole rohkem ruumi."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"See vidin on tööpunkti jaoks liiga suur."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” loodud."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” eemaldatud."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Otsetee „<xliff:g id="NAME">%s</xliff:g>” on juba olemas."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Otsetee valimine"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Rakenduse valimine"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Rakendused"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Kodu"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eemalda"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalli"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Eemalda"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstalli"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Rakenduse teave"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Otsing"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Häälotsing"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Rakendused"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eemalda"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalli värskendus"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Lisa"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Rakenduste haldamine"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Taustapilt"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Otsing"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Teadistused"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Süsteemiseaded"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Abi"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Rakenduse desinstallimine"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Rakenduse üksikasjad"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Valitud on 1 rakendus"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 vidin on valitud"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 kaust on valitud"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 otsetee on valitud"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"otseteede installimine"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Võimaldab rakendusel lisada otseteid kasutaja sekkumiseta."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"otseteede desinstallimine"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Võimaldab rakendusel eemaldada otseteid kasutaja sekkumiseta."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"avalehe seadete ja otseteede lugemine"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Võimaldab rakendusel lugeda avalehe seadeid ja otseteid."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"avalehe seadete ja otseteede kirjutamine"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Võimaldab rakendusel muuta avalehel seadeid ja otseteid."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Probleem vidina laadimisel"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"See on süsteemirakendus ja seda ei saa desinstallida."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Nimeta kaust"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Avakuva %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Leht %1$d/%2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Avakuva %1$d/%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Rakenduste leht %1$d/%2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Vidinate leht %1$d/%2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Tunne end nagu kodus"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Võite panna oma lemmikrakendused siia."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Kõikide oma rakenduste nägemiseks puudutage ringi."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Valige mõned rakendused"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Rakenduse lisamiseks avakuvale puudutage seda pikalt."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Korraldage oma rakendused kaustadesse"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Rakenduse liigutamiseks pange sõrm rakendusele ja hoidke seda."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Avakuval uue kausta tegemiseks virnastage üks rakendus teisele."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Kaust on avatud, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Puudutage kausta sulgemiseks"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Puudutage uue nime salvestamiseks"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Kaust suletud"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Kausta uus nimi: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-fa/strings.xml b/FairphoneHome/res/values-fa/strings.xml
new file mode 100644
index 0000000..abdb30a
--- /dev/null
+++ b/FairphoneHome/res/values-fa/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"راه انداز"</string>
+    <string name="home" msgid="5921706419368316758">"صفحهٔ اصلی"</string>
+    <string name="uid_name" msgid="3371120195364560632">"برنامه‌های Android Core"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"انتخاب تصویر زمینه از"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"تنظیم تصویر زمینه"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"تصاویر زمینه"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"برنامه نصب نشده است."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"ابزارک‌ها"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"برای انتخاب یک ابزارک لمس کنید و نگه دارید."</string>
+    <string name="market" msgid="2652226429823445833">"فروشگاه"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"این مورد را نمی‌توان در این صفحهٔ اصلی رها کرد."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"انتخاب ابزارک برای ایجاد"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"نام پوشه"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"تغییر نام پوشه"</string>
+    <string name="rename_action" msgid="6016003384693240896">"تأیید"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"لغو"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"افزودن به صفحهٔ اصلی"</string>
+    <string name="group_applications" msgid="2103752818818161976">"برنامه‌ها"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"میانبرها"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"ابزارک‌ها"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"تصاویر زمینه"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"فضای بیشتری در صفحات نمایش اصلی شما موجود نیست."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"اتاق دیگری در این صفحهٔ اصلی موجود نیست."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"فضای بیشتری در صندلی داغ نیست."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"این ابزارک بیش از حد برای صندلی داغ بزرگ است."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"میانبر \"<xliff:g id="NAME">%s</xliff:g>\" ایجاد شد."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"میانبر \"<xliff:g id="NAME">%s</xliff:g>\" حذف شد."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"میانبر \"<xliff:g id="NAME">%s</xliff:g>\" در حال حاضر وجود دارد."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"انتخاب میانبر"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"انتخاب برنامه"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"برنامه‌های کاربردی"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"صفحهٔ اصلی"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"حذف"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"حذف نصب"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"حذف"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"حذف نصب"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"اطلاعات برنامه"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"جستجو"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"جستجوی صوتی"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"برنامه‌ها"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"حذف"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"حذف نصب به‌روزرسانی"</string>
+    <string name="menu_add" msgid="3065046628354640854">"افزودن"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"مدیریت برنامه‌ها"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"تصویر زمینه"</string>
+    <string name="menu_search" msgid="4826514464423239041">"جستجو"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"اعلان‌ها"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"تنظیمات سیستم"</string>
+    <string name="menu_help" msgid="4901160661634590633">"راهنما"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"حذف نصب برنامه"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"جزئیات برنامه"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 برنامه انتخاب شد"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 ابزارک انتخاب شد"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 پوشه انتخاب شد"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 میانبر انتخاب شد"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"نصب میانبرها"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"به یک برنامه اجازه می‌دهد میانبرها را بدون دخالت کاربر اضافه کند."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"حذف نصب میانبرها"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"به یک برنامه اجازه می‌دهد میانبرها را بدون دخالت کاربر حذف کند."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"خواندن تنظیمات صفحهٔ اصلی و میانبرها"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"به برنامه اجازه خواندن تنظیمات و میانبرها را در صفحهٔ اصلی می‌دهد."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"نوشتن تنظیمات صفحهٔ اصلی و میانبرها"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"به برنامه اجازه تغییر تنظیمات و میانبرها را در صفحهٔ اصلی می‌دهد."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"مشکل در بارگیری ابزارک"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"این یک برنامه سیستمی است و حذف نصب نمی‌شود."</string>
+    <string name="dream_name" msgid="2847171357608437154">"پرتاب کننده موشک"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"پوشه بی‌نام"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"صفحهٔ اصلی %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"صفحه %1$d از %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"صفحهٔ اصلی %1$d از %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"صفحه برنامه‌ها %1$d از %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"صفحه ابزارک‌ها %1$d از %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"منزل خودتان است"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"می‌توانید برنامه‌های دلخواه خود را اینجا بگذارید."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"برای مشاهدهٔ تمام برنامه‌های خود، حلقه را لمس کنید."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"چندتا برنامه انتخاب کنید"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"اگر می‌خواهید برنامه‌ای را به صفحهٔ اصلی خود اضافه کنید، آن را لمس کرده و نگه دارید."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"برنامه‌های خود را با پوشه‌ها سازماندهی کنید"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"برای جابجا کردن یک برنامه، آن را لمس کرده و نگهدارید."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"برای ایجاد یک پوشه جدید در صفحهٔ اصلی خود، یک برنامه را در بالای دیگری قرار دهید."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"تأیید"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"پوشه باز شده، <xliff:g id="WIDTH">%1$d</xliff:g> در <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"برای بستن پوشه لمس کنید"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"برای ذخیره تغییر نام لمس کنید"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"پوشه بسته شد"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"نام پوشه به <xliff:g id="NAME">%1$s</xliff:g> تغییر کرد"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"پوشه: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-fi/strings.xml b/FairphoneHome/res/values-fi/strings.xml
new file mode 100644
index 0000000..29f3826
--- /dev/null
+++ b/FairphoneHome/res/values-fi/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Käynnistysohjelma"</string>
+    <string name="home" msgid="5921706419368316758">"Aloitusruutu"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core -sovellukset"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Valitse taustakuva"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Aseta taustakuva"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Taustakuvat"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Sovellusta ei ole asennettu."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgetit"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Valitse widget painamalla sitä pitkään."</string>
+    <string name="market" msgid="2652226429823445833">"Myymälä"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Kohteen lisääminen tähän aloitusruutuun epäonnistui."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Valitse luotava widget"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Kansion nimi"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Nimeä kansio uudelleen"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Peruuta"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Lisää etusivulle"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Sovellukset"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Pikakuvakkeet"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgetit"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Taustakuvat"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Aloitusruuduilla ei ole enää tilaa."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Etusivulla ei ole enää tilaa."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Hotseatissa ei ole enää tilaa."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Tämä widget on liian suuri tähän paikkaan."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> luotu"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> poistettiin."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Pikakuvake <xliff:g id="NAME">%s</xliff:g> on jo olemassa."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Valitse pikakuvake"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Valitse sovellus"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Sovellukset"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Etusivu"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Poista"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Poista"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Poista"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Poista"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Sovelluksen tiedot"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Haku"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Puhehaku"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Sovellukset"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Poista"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Poista päivitys"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Lisää"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Hallinnoi sovelluksia"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Taustakuva"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Haku"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Ilmoitukset"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Järjestelmän asetukset"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ohje"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Poista sovellus"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Sovelluksen tiedot"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 sovellus valittu"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget valittu"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 kansio valittu"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 pikakuvake valittu"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"asentaa pikakuvakkeita"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Antaa sovelluksen lisätä pikakuvakkeita itsenäisesti ilman käyttäjän valintaa."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"poistaa pikakuvakkeita"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Antaa sovelluksen poistaa pikakuvakkeita ilman käyttäjän valintaa."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"lukea etusivun asetuksia ja pikakuvakkeita"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Antaa sovelluksen lukea aloitusruudun asetukset ja pikakuvakkeet."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"kirjoittaa etusivun asetuksia ja pikakuvakkeita"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Antaa sovelluksen muuttaa aloitusruudun asetuksia ja pikakuvakkeita."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Ongelma ladattaessa widgetiä"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Tämä on järjestelmäsovellus, eikä sitä voi poistaa."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Sinko"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Nimetön kansio"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Aloitusruutu %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Sivu %1$d / %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Aloitusruutu %1$d/%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Apps-sivu %1$d / %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widgetin sivu %1$d / %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Ole kuin kotonasi"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Voit siirtää suosikkisovelluksesi tänne."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Näet kaikki sovellukset koskettamalla ympyrää."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Valitse joitakin sovelluksia"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Voit lisätä sovelluksen aloitusruutuun koskettamalla sitä pitkään."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Järjestä sovelluksesi kansioihin"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Voit siirtää sovelluksia koskettamalla sovellusta pitkään."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Voit luoda uuden kansion aloitusruutuun pinoamalla yhden sovelluksen toisen päälle."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Kansio avattu, koko <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Sulje kansio koskettamalla"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Tallenna uudella nimellä koskettamalla"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Kansio on suljettu"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Kansion nimeksi vaihdettiin <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Kansio: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-fr/strings.xml b/FairphoneHome/res/values-fr/strings.xml
new file mode 100644
index 0000000..8a8aec2
--- /dev/null
+++ b/FairphoneHome/res/values-fr/strings.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="application_name" msgid="8424725141379931883">"Système d’exploitation (OS) du Fairphone"</string>
+    <string name="home" msgid="5921706419368316758">"Accueil"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Applications de base Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Sélectionnez un fond d\'écran dans"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Sélectionner"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Fonds d\'écran"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"L\'application n\'est pas installée."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Appuyez de manière prolongée pour ajouter widget."</string>
+    <string name="market" msgid="2652226429823445833">"Acheter"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Impossible de déposer élément sur écran d\'accueil."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Sélectionnez le widget à créer"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nom du dossier"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Renommer le dossier"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Annuler"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Ajouter à l\'écran d\'accueil"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Applications"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Raccourcis"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Fonds d\'écran"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Vous n\'avez plus d\'espace libre sur vos écrans d\'accueil."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Plus d\'espace libre sur l\'écran d\'accueil."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Vous n\'avez plus de place sur la barre d\'accès rapide."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Ce widget est trop volumineux pour la barre d\'accès rapide."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été créé."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été supprimé."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" existe déjà."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Sélectionner un raccourci"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Sélectionner une application"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Applications"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Page d\'accueil"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Supprimer"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Désinstaller"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Supprimer"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Désinstaller"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informations sur l\'application"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Rechercher"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Recherche vocale"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Applications"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Supprimer"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Désinstaller la mise à jour"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Ajouter"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Gérer les applications"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Fond d\'écran"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Rechercher"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notifications"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Paramètres système"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Aide"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Désinstaller l\'application"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Détails de l\'application"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 application sélectionnée."</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget sélectionné"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 dossier sélectionné"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 raccourci sélectionné"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"installer des raccourcis"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"désinstaller les raccourcis"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permet à l\'application de supprimer des raccourcis sans l\'intervention de l\'utilisateur."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Lire les paramètres et les raccourcis de la page d\'accueil"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permet à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Enregistrer les paramètres de la page d\'accueil et des raccourcis"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problème lors du chargement du widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Lance-missile"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Dossier sans nom"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Écran d\'accueil %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Page %1$d sur %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Écran d\'accueil %1$d sur %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Page des applications : %1$d sur %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Page des widgets : %1$d sur %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Faites comme chez vous"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Vous pouvez placer vos applications préférées ici."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Pour voir toutes vos applications, appuyez sur le cercle."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Sélectionner des applications"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Pour ajouter une application à votre écran d\'accueil, appuyez dessus de manière prolongée."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organisez vos applications en dossiers"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Pour déplacer une application, appuyez dessus de manière prolongée."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Pour créer un dossier sur votre écran d\'accueil, superposez les applications les unes sur les autres."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Dossier ouvert, <xliff:g id="WIDTH">%1$d</xliff:g> par <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Appuyez pour fermer le dossier."</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Appuyez pour enregistrer le nouveau nom."</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Dossier fermé"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Nouveau nom du dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+
+    <!-- Fairphone -->
+    <!-- Your Apps -->
+    <string name="your_apps">Your Apps</string>
+    <string name="last_used_apps">Dernières applications utilisées</string>
+    <string name="last_used">Moins utilisée</string>
+    <string name="most_used_apps">Applications\nles plus\nutilisées</string>
+    <string name="most_used">Plus utilisée</string>
+    <string name="no_apps_have_been_opened_yet">Les applications ne s\'ouvrent toujours pas? Commencez à utiliser votre téléphone et revenez à cet écran</string>
+    <string name="reset">Réinitialisation</string>
+    <string name="app_switcher_reset_message">Etes-vous sûr?</string>
+
+    <!-- Settings -->
+    <string name="energy_mood">Modulateur d\'ambiance (Energy Mood) dans l\'écran de verrouillage</string>
+    <string name="energy_mood_summary">Afficher le niveau de la batterie comme couleur de fond sur l\'écran de verrouillage</string>
+
+    <!-- Quick Access -->
+    <string name="quick_access">Quick Access</string>
+    <string name="edit">Modifier</string>
+    <string name="favourite_apps">Applications préférées</string>
+    <string name="drag_here_to_add">Glisser\nici pour\najouter</string>
+    <string name="drag_here_to_remove">Glisser\nici pour\nenlever</string>
+
+    <!-- OOBE Texts -->
+    <string name="oobe_quick_access">Quick Access</string>
+    <string name="oobe_select_language">Sélectionnez\nla langue</string>
+    <string name="oobe_setup_wifi">Configuration\nWi-Fi</string>
+    <string name="oobe_intro_top">Bienvenue! Vous avez dans les mains un téléphone qui met en avant des valeurs sociales. Mais bien sûr vous pouvez faire des appels.</string>
+    <string name="oobe_intro_bottom">Nous alons vous montrer comment l\'utiliser</string>
+    <string name="oobe_edge_swipe_title">Glissez votre doigt</string>
+    <string name="oobe_edge_swipe_text">de la gauche ou de la droite sans le relever</string>
+    <string name="oobe_open_app_title">Relâcher votre doigt</string>
+    <string name="oobe_open_app_text">au-dessus d\'une application pour la démarrer</string>
+    <string name="oobe_edit_drag_intro">Vous pouvez glisser et relâcher les icônes de vos applications et sont ainsi facilement modifiables</string>
+    <string name="oobe_edit_drag_add_title">Glissez et relâchez</string>
+    <string name="oobe_edit_drag_add_text">les icônes de la colonne de droite pour les rajouter à vos favorites</string>
+    <string name="oobe_edit_drag_remove_title">Glissez et relâchez</string>
+    <string name="oobe_edit_drag_remove_text">les icônes vers la colonne de gauche pour les retirer de vos favorites</string>
+    <string name="oobe_edit_drag_trade_title">Glissez les favorites</string>
+    <string name="oobe_edit_drag_trade_text">pour changer leur position</string>
+    <string name="oobe_your_apps_intro">Les applications que vous utilisez le plus souvent, réunies au même endroit</string>
+    <string name="oobe_your_apps_learning">Votre téléphone connaît vos applications préférées et les mémorise pour vous</string>
+    <string name="oobe_your_apps_last_ones">Vous pouvez également voir quelles sont les dernières que vous avez utilisées</string>
+    <string name="oobe_your_apps_start_using">Commencez à utiliser votre téléphone et vous verrez apparaître les applications</string>
+    <string name="oobe_start">Début</string>
+    <string name="oobe_back">Retour</string>
+    <string name="oobe_skip">Passer</string>
+    <string name="oobe_next">Suivant</string>
+    <string name="oobe_done">Fin</string>
+
+    <!-- Google Apps Install Widget -->
+    <string name="google_apps_installer_name">Programme d’installation de Google Apps</string>
+	<string name="google_apps_initial_title">Installer\nles Google Apps</string>
+	<string name="google_apps_disclaimer_title">Installer les Google Apps</string>
+	<string name="google_apps_disclaimer_description">Pour une expérience mobile Android et Google complète, telle que la boutique Google Play, votre téléphone a besoin de contenus et de logiciels supplémentaires. Comme Fairphone ne possède pas, pour l’heure, de licence, il ne nous est malheureusement pas possible de préinstaller ce contenu ni de le fournir directement. Nous travaillons actuellement avec le propriétaire du contenu en vue d’atteindre cet objectif.\nCliquez sur « J’accepte », ci-dessous, pour télécharger ce contenu à partir d’une source externe sécurisée. L’installation de ce contenu est de votre entière responsabilité.\nSi vous n’acceptez pas, votre téléphone fonctionnera, bien entendu, avec les applications de base pour Android, mais vous regretterez certainement de ne pas pouvoir utiliser certains services proposés par Google.</string>
+	<string name="google_apps_disclaimer_agree">J’accepte</string>
+	<string name="google_apps_denied_permissions_title">Autorisations refusées</string>
+	<string name="google_apps_denied_permissions_description">Le Concepteur de Fairphone ne parvient pas à obtenir les permissions nécessaires pour installer les Google Apps. Si vous avez choisi l’option REFUSER, veuillez redémarrer le programme d’installation et cliquer sur AUTORISER afin d’activer cette option.</string>
+	<string name="google_apps_reboot_failed_title">Redémarrage échoué</string>
+	<string name="google_apps_reboot_failed_description">Les Google Apps sont installées. Si vous ne parvenez pas à redémarrer l’appareil, faite-le manuellement.</string>
+	<string name="google_apps_download_title">Téléchargement des Google Apps</string>
+	<string name="google_apps_unzip_title">Extraction des Google Apps</string>
+	<string name="google_apps_install_title">Installation des Google Apps</string>
+	<string name="google_apps_reboot_title">Redémarrage de l’appareil</string>
+	<string name="google_apps_permissions_description">Le Concepteur de Fairphone va maintenant vous demander d’activer l’accès de Super-utilisateur. Nous vous assurons que cela est absolument sans risque. Vous devrez alors sélectionner l’option AUTORISER.</string>
+	<string name="google_apps_permissions_title">Autorisations du système</string>
+	<string name="google_apps_reboot_description">Pour conclure l’installation, il est nécessaire de redémarrer le système.\nAprès le redémarrage de l’appareil, suivez les étapes pour configurer les Google Apps.</string>
+	<string name="google_apps_uninstall_title">Google Apps installées</string>
+	<string name="google_apps_uninstall_description">Éliminer ce\nprogramme d’installation</string>
+	<string name="google_apps_failed_download_title">Téléchargement échoué</string>
+	<string name="google_apps_failed_download_description">Les fichiers téléchargés sont endommagés. Souhaitez-vous essayer à nouveau?</string>
+	<string name="google_apps_download_error">Une erreur est survenue lors du téléchargement des fichiers. Essayez à nouveau.</string>
+	<string name="google_apps_connection_title">Fonction Wi-Fi désactivée</string>
+	<string name="google_apps_connection_description">Le fichier que vous essayez de télécharger est trop volumineux pour les connexions mobiles (~100 MB). Veuillez activer la connexion Wi-Fi et essayer à nouveau.</string>
+	
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values-fr/styles.xml b/FairphoneHome/res/values-fr/styles.xml
new file mode 100644
index 0000000..bf29f45
--- /dev/null
+++ b/FairphoneHome/res/values-fr/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="SubTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">11.3sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">14.5sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-2dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEDescriptionText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">13sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values-hi/strings.xml b/FairphoneHome/res/values-hi/strings.xml
new file mode 100644
index 0000000..c5ae89a
--- /dev/null
+++ b/FairphoneHome/res/values-hi/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"लॉन्चर"</string>
+    <string name="home" msgid="5921706419368316758">"मुखपृष्ठ"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android मुख्य एप्लिकेशन"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"वॉलपेपर यहां से चुनें:"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"वॉलपेपर सेट करें"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"वॉलपेपर"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"एप्‍लिकेशन इंस्‍टॉल नहीं है."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"विजेट"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"किसी विजेट को चुनने के लिए स्‍पर्श करके रखें."</string>
+    <string name="market" msgid="2652226429823445833">"दुकान"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"इस मुखपृष्ठ स्‍क्रीन पर आइटम को नहीं छोड़ा जा सका."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"बनाने के लिए विजेट चुनें"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"फ़ोल्‍डर का नाम"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"फ़ोल्‍डर का नाम बदलें"</string>
+    <string name="rename_action" msgid="6016003384693240896">"ठीक"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"रद्द करें"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"होम स्‍क्रीन में जोड़ें"</string>
+    <string name="group_applications" msgid="2103752818818161976">"एप्लिकेशन"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"शॉर्टकट"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"विजेट"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"वॉलपेपर"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"आपकी मुखपृष्ठ स्‍क्रीन पर अधिक स्थान नहीं है."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"इस होम स्‍क्रीन पर और स्थान नहीं है."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"हॉटसीट पर अधिक स्‍थान नहीं है."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"हॉटसीट के लि‍ए यह वि‍जेट बहुत बड़ा है."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"\"<xliff:g id="NAME">%s</xliff:g>\" शार्टकट बना दिया गया."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"\"<xliff:g id="NAME">%s</xliff:g>\" शॉर्टकट हटाया गया."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"शार्टकट \"<xliff:g id="NAME">%s</xliff:g>\" पहले से मौजूद है."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"शॉर्टकट चुनें"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"एप्‍लिकेशन चुनें"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"एप्लिकेशन"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"होम"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"निकालें"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"अनइंस्टॉल करें"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"निकालें"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"अनइंस्टॉल करें"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"एप्‍लिकेशन जानकारी"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"खोजें"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"ध्वनि खोज"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"एप्लिकेशन"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"निकालें"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"अपडेट अनइंस्‍टॉल करें"</string>
+    <string name="menu_add" msgid="3065046628354640854">"जोड़ें"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"एप्लिकेशन प्रबंधित करें"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"वॉलपेपर"</string>
+    <string name="menu_search" msgid="4826514464423239041">"खोज"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"सूचनाएं"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"सिस्टम सेटिंग"</string>
+    <string name="menu_help" msgid="4901160661634590633">"सहायता"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"एप्‍लिकेशन अनइंस्‍टॉल करें"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"एप्‍लिकेशन विवरण"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 एप्‍लिकेशन चयनित"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 विज़ेट चयनित"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 फ़ोल्‍डर का चयन किया"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 शार्टकट चयनित"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"शॉर्टकट स्‍थापित करें"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"एप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देता है."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"शॉर्टकट अनइंस्टॉल करें"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"एप्लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट निकालने देता है."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"होम सेटिंग और शॉर्टकट पढ़ें"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"एप्लिकेशन को मुखपृष्ठ पर सेटिंग और शॉर्टकट पढ़ने देता है."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"होम सेटिंग और शॉर्टकट लिखें"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"एप्लिकेशन को मुखपृष्ठ पर सेटिंग और शॉर्टकट बदलने देता है."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"विजेट लोड करने में समस्‍या"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"यह सिस्‍टम एप्लिकेशन है और इसे अनइंस्‍टॉल नहीं किया जा सकता."</string>
+    <string name="dream_name" msgid="2847171357608437154">"रॉकेट लॉन्‍चर"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"अनामित फ़ोल्डर"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"होम स्‍क्रीन %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"%2$d में से %1$d पृष्ठ"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"%2$d में %1$d होम स्‍क्रीन"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"%2$d में से %1$d एप्लिकेशन पृष्ठ"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"%2$d में %1$d विजेट पृष्ठ"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"जैसा चाहें वैसा उपयोग करें"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"आप अपने पसंदीदा एप्लिकेशन यहां रख सकते हैं."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"अपने सभी एप्लिकेशन देखने के लिए, मंडली को स्‍पर्श करें."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"कुछ एप्लिकेशन चुनें"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"किसी एप्लिकेशन को अपनी मुखपृष्ठ स्‍क्रीन से जोड़ने के लिए, उसे स्‍पर्श करके रखें."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"अपने एप्लिकेशन को फ़ोल्डर के साथ व्‍यवस्थित करें"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"किसी एप्लिकेशन को ले जाने के लिए, उसे स्‍पर्श करके रखें."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"अपनी मुखपृष्ठ स्‍क्रीन पर कोई नया फ़ोल्डर बनाने के लिए, एक एप्लिकेशन को दूसरे के शीर्ष पर स्‍टैक करें."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"ठीक"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"फ़ोल्डर खोला गया, <xliff:g id="WIDTH">%1$d</xliff:g> गुणा <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"फ़ोल्‍डर बंद करने के लिए स्‍पर्श करें"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"परिवर्तित नाम सहेजने के लिए स्पर्श करें"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"फ़ोल्डर बंद किया गया"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"फ़ोल्डर का नाम बदलकर <xliff:g id="NAME">%1$s</xliff:g> किया गया"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-hr/strings.xml b/FairphoneHome/res/values-hr/strings.xml
new file mode 100644
index 0000000..665d7b3
--- /dev/null
+++ b/FairphoneHome/res/values-hr/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Pokretač"</string>
+    <string name="home" msgid="5921706419368316758">"Početna"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Matične aplikacije za Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Odabir pozadinske slike iz"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Postavi pozadinsku sliku"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Pozadinske slike"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Aplikacija nije instalirana."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgeti"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Dodirnite i držite kako biste preuzeli widget."</string>
+    <string name="market" msgid="2652226429823445833">"Trgovina"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Nije bilo moguće spustiti stavku na početni zaslon."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Odabir widgeta za stvaranje"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Naziv mape"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Preimenuj mapu"</string>
+    <string name="rename_action" msgid="6016003384693240896">"U redu"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Odustani"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Dodaj na početni zaslon"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplikacije"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Prečaci"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgeti"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Pozadinske slike"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Na vašim početnim zaslonima više nema mjesta."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Na ovom početnom zaslonu više nema mjesta."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Na hotseatu više nema mjesta."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Ovaj je widget prevelik za hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Izrađen je prečac za \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Prečac za \"<xliff:g id="NAME">%s</xliff:g>\" je uklonjen."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Prečac za \"<xliff:g id="NAME">%s</xliff:g>\" već postoji."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Odabir prečaca"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Odabir aplikacije"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplikacije"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Početna"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ukloni"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstaliraj"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Uklanjanje"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Deinstaliranje"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informacije o aplikaciji"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Pretraži"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Glasovno pretraživanje"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplikacije"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Ukloni"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Deinstalacija ažuriranja"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj aplikacijama"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Pozadinska slika"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Pretraži"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Obavijesti"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Postavke sustava"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Pomoć"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Deinstaliraj aplikaciju"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Pojedinosti o aplikaciji"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Odabrana je 1 aplikacija"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget odabran"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mapa odabrana"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 prečac odabran"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instaliraj prečace"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Omogućuje aplikaciji dodavanje prečaca bez intervencije korisnika."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"deinstaliraj prečace"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Dopušta aplikaciji uklanjanje prečaca bez intervencije korisnika."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"pročitaj postavke početnog zaslona i prečaca"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Dopušta aplikaciji čitanje postavki i prečaca na početnom zaslonu."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"zapiši postavke početnog zaslona i prečaca"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Dopušta aplikaciji promjenu postavki i prečaca na početnom zaslonu."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problem pri učitavanju widgeta"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Ovo je aplikacija sustava i ne može se ukloniti."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Neimenovana mapa"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Početni zaslon %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Stranica %1$d od %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Početni zaslon %1$d od %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Stranica aplikacija %1$d od %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Stranica widgeta %1$d od %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Osjećajte se kao kod kuće"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Ovdje možete staviti svoje omiljene aplikacije."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Da biste vidjeli sve aplikacije, dodirnite krug."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Odaberite neke aplikacije"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Da biste početnom zaslonu dodali aplikaciju, dodirnite je i zadržite."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organizirajte svoje aplikacije putem mapa"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Da biste premjestili aplikaciju, dodirnite je i zadržite."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Da biste napravili novu mapu na početnom zaslonu, stavite jednu aplikaciju na drugu."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"U redu"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Mapa je otvorena, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Dodirnite za zatvaranje mape"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Dodirnite da biste spremili preimenovanje"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mapa zatvorena"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mapa je preimenovana u <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-hu/strings.xml b/FairphoneHome/res/values-hu/strings.xml
new file mode 100644
index 0000000..761ee72
--- /dev/null
+++ b/FairphoneHome/res/values-hu/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Indító"</string>
+    <string name="home" msgid="5921706419368316758">"Főoldal"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Alap Android-alkalmazások"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Válasszon tapétát innen:"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Háttérkép kiválasztása"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Háttérképek"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Az alkalmazás nincs telepítve."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Modulok"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Modul felvételéhez érintse meg, és tartsa lenyomva"</string>
+    <string name="market" msgid="2652226429823445833">"Bolt"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Nem lehet elemeket dobni erre a Kezdőképernyőre."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"A létrehozáshoz válasszon modult"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Mappa neve"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Mappa átnevezése"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Mégse"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Hozzáadás a főoldalhoz"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Alkalmazások"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Parancsikonok"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Modulok"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Háttérképek"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Nincs több hely a Kezdőképernyőkön."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Nincs több hely ezen a főoldalon."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Nincs több hely a hotseaten."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Ez a modul túl nagy a hotseat számára."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"\"<xliff:g id="NAME">%s</xliff:g>\" parancsikon létrehozva."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"A(z) \"<xliff:g id="NAME">%s</xliff:g>\" parancsikon eltávolításra került."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"\"<xliff:g id="NAME">%s</xliff:g>\" parancsikon már létezik."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Parancsikon választása"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Válasszon alkalmazást"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Alkalmazások"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Főoldal"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eltávolítás"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Eltávolítás"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Eltávolítás"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Eltávolítás"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Alkalmazásinformáció"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Keresés"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hangalapú keresés"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Alkalmazások"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Törlés"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Eltávolítja a frissítést"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Hozzáadás"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Alkalmazások kezelése"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Háttérkép"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Keresés"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Értesítések"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Rendszerbeállítások"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Súgó"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Alkalmazás eltávolítása"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Az alkalmazás adatai"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 kiválasztott alkalmazás"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 modul kiválasztva"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mappa kiválasztva"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 parancsikon kiválasztva"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"parancsikonok telepítése"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"parancsikonok eltávolítása"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül távolítson el parancsikonokat."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Főoldal beállításainak és parancsikonjainak beolvasása"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Lehetővé teszi az alkalmazás számára, hogy beolvassa a Kezdőképernyő beállításait és parancsikonjait."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Főoldal beállításainak és parancsikonjainak írása"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a Kezdőképernyő beállításait és parancsikonjait."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Probléma történt a modul betöltésekor"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Ez egy rendszeralkalmazás, és nem lehet eltávolítani."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Aknavető"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Névtelen mappa"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"%1$d. kezdőképernyő"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"%2$d/%1$d. oldal"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"%2$d/%1$d. kezdőképernyő"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"%2$d/%1$d. alkalmazásoldal"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"%2$d/%1$d. moduloldal"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Érezze magát otthon"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Ide rakhatja kedvenc alkalmazásait."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Az összes saját alkalmazás megtekintéséhez érintse meg a kört."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Válasszon ki néhány alkalmazást"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Ha egy alkalmazást el szeretne helyezni a kezdőképernyőn, érintse meg, és tartsa lenyomva."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Rendezze alkalmazásait mappákba"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Ha egy alkalmazást át szeretne helyezni, érintse meg, és tartsa lenyomva."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Ha egy új mappát szeretne létrehozni a kezdőképernyőn, helyezzen egymásra két alkalmazást."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Mappa megnyitva -- szélesség: <xliff:g id="WIDTH">%1$d</xliff:g>; magasság: <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Érintse meg a mappa bezárásához"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Érintse meg az átnevezés mentéséhez"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mappa lezárva"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mappa új neve: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-in/strings.xml b/FairphoneHome/res/values-in/strings.xml
new file mode 100644
index 0000000..3ba6225
--- /dev/null
+++ b/FairphoneHome/res/values-in/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Peluncur"</string>
+    <string name="home" msgid="5921706419368316758">"Beranda"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Pilih wallpaper dari"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Setel wallpaper"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Wallpaper"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Apl tidak dipasang."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widget"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Sentuh &amp; tahan untuk memilih widget."</string>
+    <string name="market" msgid="2652226429823445833">"Belanja"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Tidak dapat melepas item ke layar Utama ini."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Pilih widget untuk membuat"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nama folder"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Ganti nama folder"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Oke"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Batal"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Tambahkan ke Layar Utama"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apl"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Pintasan"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Wallpaper"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Tidak ada ruang lagi pada layar Utama Anda."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Tidak ada ruang lagi pada layar Utama ini."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Tidak ada ruang lagi di hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Widget ini terlalu besar untuk hotseat tersebut."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah dibuat."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dihapus."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah ada."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Pilih pintasan"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Pilih apl"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Rumah"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Hapus"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Copot pemasangan"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Hapus"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Copot pemasangan"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Info apl"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Telusuri"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Penelusuran Suara"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apl"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Hapus"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Copot pemasangan pembaruan"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Tambahkan"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Kelola apl"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Wallpaper"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Telusuri"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Pemberitahuan"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Setelan sistem"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Bantuan"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Copot pemasangan apl"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Detail apl"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 apl dipilih"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget dipilih"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 folder dipilih"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 pintasan dipilih"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"pasang pintasan"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Mengizinkan apl menambahkan pintasan tanpa campur tangan pengguna."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"copot pemasangan pintasan"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Mengizinkan apl menghapus pintasan tanpa campur tangan pengguna."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"baca setelan dan pintasan Beranda"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Mengizinkan apl membaca setelan dan pintasan di layar Utama."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"tuliskan setelan dan pintasan Beranda"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Mengizinkan apl mengubah setelan dan pintasan di layar Utama."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Masalah memuat widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Ini adalah apl sistem dan tidak dapat dicopot pemasangannya."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Folder Tanpa Nama"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Layar utama %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Laman %1$d dari %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Layar utama %1$d dari %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Laman apl %1$d dari %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Laman widget %1$d dari %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Anggap rumah sendiri"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Anda dapat meletakkan apl favorit Anda di sini."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Untuk melihat semua apl Anda, sentuh lingkaran."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Pilih beberapa apl"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Untuk menambah apl ke layar Utama Anda, sentuh &amp; tahan apl tersebut."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Atur apl Anda dengan folder"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Untuk memindahkan apl, sentuh &amp; tahan apl tersebut."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Untuk membuat folder baru di layar Utama Anda, tumpuk satu apl di atas apl yang lain."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Oke"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> kali <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Sentuh untuk menutup folder"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Sentuh untuk menyimpan pengubahan nama"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Folder ditutup"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Folder diubah namanya menjadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-it/strings.xml b/FairphoneHome/res/values-it/strings.xml
new file mode 100644
index 0000000..9a73872
--- /dev/null
+++ b/FairphoneHome/res/values-it/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Avvio applicazioni"</string>
+    <string name="home" msgid="5921706419368316758">"Home"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Scegli sfondo da"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Imposta sfondo"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Sfondi"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Applicazione non installata."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widget"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Tocca e tieni premuto per scegliere un widget."</string>
+    <string name="market" msgid="2652226429823445833">"Acquista"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Rilascio elemento in schermata Home non riuscito."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Scegli il widget da creare"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nome cartella"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Rinomina cartella"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Annulla"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Aggiungi a schermata Home"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Applicazioni"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Scorciatoie"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Sfondi"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Spazio nelle schermate Home esaurito."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Spazio nella schermata Home esaurito."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Spazio nell\'area hotseat esaurito."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Questo widget è troppo grande per l\'area hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" creata."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"La scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" è stata rimossa."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" già presente."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Scegli scorciatoia"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Scegli applicazione"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Applicazioni"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Rimuovi"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Disinstalla"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Rimuovi"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Disinstalla"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informazioni applicazione"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Cerca"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Ricerca vocale"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Applicazioni"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Rimuovi"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Disinstalla aggiornamento"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Aggiungi"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Gestisci applicazioni"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Sfondo"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Cerca"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notifiche"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Impostazioni sistema"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Guida"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Disinstalla applicazione"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Dettagli applicazione"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 applicazione selezionata"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget selezionato"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 cartella selezionata"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 scorciatoia selezionata"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"aggiungere scorciatoie"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Consente a un\'applicazione di aggiungere scorciatoie automaticamente."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"eliminare scorciatoie"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Consente all\'applicazione di rimuovere scorciatoie automaticamente."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"leggere impostazioni e scorciatoie in Home"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Consente all\'applicazione di leggere le impostazioni e le scorciatoie in Home."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"creare impostazioni e scorciatoie in Home"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Consente all\'applicazione di modificare le impostazioni e le scorciatoie in Home."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Errore durante il caricamento del widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Questa è un\'applicazione di sistema e non può essere disinstallata."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Lanciamissili"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Cartella senza nome"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Schermata Home %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Pagina %1$d di %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Schermata Home %1$d di %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Pagina di applicazioni %1$d di %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Pagina di widget %1$d di %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Personalizza la schermata home"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Puoi posizionare le tue applicazioni preferite qui."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Per visualizzare tutte le tue applicazioni, tocca il cerchio."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Scegli alcune applicazioni"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Per aggiungere un\'applicazione alla schermata Home, tocca e tieni premuto."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organizza le tue applicazioni in cartelle"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Per spostare un\'applicazione, tocca e tieni premuto."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Per creare una nuova cartella sulla schermata Home, impila un\'applicazione su un\'altra."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Cartella aperta, <xliff:g id="WIDTH">%1$d</xliff:g> per <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Tocca per chiudere la cartella"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Tocca per salvare nuovo nome"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Cartella chiusa"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Cartella rinominata in <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-iw/strings.xml b/FairphoneHome/res/values-iw/strings.xml
new file mode 100644
index 0000000..8dd6cd9
--- /dev/null
+++ b/FairphoneHome/res/values-iw/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"מפעיל"</string>
+    <string name="home" msgid="5921706419368316758">"בית"</string>
+    <string name="uid_name" msgid="3371120195364560632">"יישומי ליבה של Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"בחר טפט מ-"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"הגדר טפט"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"טפטים"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"היישום לא מותקן."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"רכיבי Widget"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"גע בפריט והחזק בו כדי לבחור Widget."</string>
+    <string name="market" msgid="2652226429823445833">"קנה"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"לא ניתן לשחרר את הפריט במסך דף בית זה."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"בחר Widget ליצירה"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"שם תיקיה"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"שנה את שם התיקיה"</string>
+    <string name="rename_action" msgid="6016003384693240896">"אישור"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"ביטול"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"הוסף למסך דף הבית"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Google Apps"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"קיצורי דרך"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"רכיבי Widget"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"טפטים"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"אין יותר מקום במסכי דף הבית."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"אין עוד מקום במסך דף הבית הזה."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"אין יותר מקום בפס היישומים."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Widget זה גדול מדי עבור אזור העגינה."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"הקיצור \'<xliff:g id="NAME">%s</xliff:g>\' נוצר."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"הקיצור \'<xliff:g id="NAME">%s</xliff:g>\' הוסר."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"הקיצור \'<xliff:g id="NAME">%s</xliff:g>\' כבר קיים."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"בחר קיצור דרך"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"בחר יישום"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"יישומים"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"בית"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"הסר"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"הסר התקנה"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"הסר"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"הסר התקנה"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"פרטי יישום"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"חפש"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"חיפוש קולי"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"יישומים"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"הסר"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"הסר את התקנת העדכון"</string>
+    <string name="menu_add" msgid="3065046628354640854">"הוסף"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"נהל יישומים"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"טפט"</string>
+    <string name="menu_search" msgid="4826514464423239041">"חפש"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"התראות"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"הגדרות מערכת"</string>
+    <string name="menu_help" msgid="4901160661634590633">"עזרה"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"הסר יישום"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"פרטי היישום"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"נבחר יישום אחד"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"נבחר Widget אחד"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"נבחרה תיקיה אחת"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"נבחר קיצור דרך אחד"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"התקן קיצורי דרך"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"מאפשר ליישום להוסיף קיצורי דרך ללא התערבות המשתמש."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"הסר קיצורי דרך"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"מאפשר ליישום להסיר קיצורי דרך ללא התערבות המשתמש."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"קרא הגדרות וקיצורי דרך של דף הבית"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"מאפשר ליישום לקרוא את ההגדרות וקיצורי הדרך בדף הבית."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"כתוב הגדרות וקיצורי דרך של דף הבית"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"מאפשר ליישום לשנות את ההגדרות וקיצורי הדרך בדף הבית."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"בעיה בטעינת Widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"זהו יישום מערכת ולא ניתן להסיר את התקנתו."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"תיקיה ללא שם"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"מסך דף הבית %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"דף %1$d מתוך %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"מסך דף הבית %1$d מתוך %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"יישומים דף %1$d מתוך %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"דף Widgets ‏%1$d מתוך %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"תרגישו בבית"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"תוכל למקם את היישומים המועדפים עליך כאן."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"כדי לראות את כל היישומים שלך, גע במעגל."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"בחר כמה יישומים"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"כדי להוסיף יישום למסך דף הבית, גע ביישום והחזק אותו."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"סדר את היישומים שלך בתיקיות"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"כדי להעביר יישום, גע בו והחזק אותו."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"כדי ליצור תיקיה חדשה במסך דף הבית, הצב יישום אחד בערימה מעל יישום אחר."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"בסדר"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"תיקיה פתוחה, <xliff:g id="WIDTH">%1$d</xliff:g> על <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"גע כדי לסגור את התיקייה"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"גע כדי לשמור שינוי שם"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"התיקייה נסגרה"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"שם התיקיה שונה ל-<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"תיקיה: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ja/strings.xml b/FairphoneHome/res/values-ja/strings.xml
new file mode 100644
index 0000000..a049d2e
--- /dev/null
+++ b/FairphoneHome/res/values-ja/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"ランチャー"</string>
+    <string name="home" msgid="5921706419368316758">"Home"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"壁紙の選択"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"壁紙に設定"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"壁紙"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"このアプリはインストールされていません。"</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"ウィジェット"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"ウィジェットを追加するには押し続けます。"</string>
+    <string name="market" msgid="2652226429823445833">"ショップ"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"このホーム画面にアイテムをドロップできませんでした。"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"作成するウィジェットの選択"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"フォルダ名"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"フォルダ名を変更"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"キャンセル"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"ホーム画面に追加"</string>
+    <string name="group_applications" msgid="2103752818818161976">"アプリ"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"ショートカット"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"ウィジェット"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"壁紙"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"ホーム画面に空きスペースがありません。"</string>
+    <string name="out_of_space" msgid="8365249326091984698">"ホーム画面に空きスペースがありません。"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"ホットシートに空きスペースがありません。"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"このウィジェットはホットシートには大きすぎます。"</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を作成しました。"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を削除しました。"</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」は既に存在します。"</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"ショートカットを選択"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"アプリの選択"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"アプリ"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"ホーム"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"削除"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"アンインストール"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"削除"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"アンインストール"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"アプリケーション情報"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"検索"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"音声検索"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"アプリ"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"削除"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"アップデートを削除"</string>
+    <string name="menu_add" msgid="3065046628354640854">"追加"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"アプリの管理"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"壁紙"</string>
+    <string name="menu_search" msgid="4826514464423239041">"検索"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"システム設定"</string>
+    <string name="menu_help" msgid="4901160661634590633">"ヘルプ"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"アプリをアンインストール"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"アプリの詳細"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1つのアプリが選択されています"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1つのウィジェットが選択されています"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1つのフォルダが選択されています"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1つのショートカットが選択されています"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"ショートカットのインストール"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"ユーザー操作なしでショートカットを追加することをアプリに許可します。"</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"ショートカットのアンインストール"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"ユーザー操作なしでショートカットを削除することをアプリに許可します。"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"ホーム設定とショートカットの読み取り"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"ホームの設定とショートカットの読み取りをアプリに許可します。"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"ホームの設定とショートカットの書き込み"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"ホームの設定とショートカットの変更をアプリに許可します。"</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"ウィジェットを表示できません"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"このシステムアプリはアンインストールできません。"</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"名前のないフォルダ"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"ホーム画面: %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"%1$d/%2$dページ"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"ホーム画面: %1$d/%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"アプリの%1$d/%2$dページ"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"ウィジェットの%1$d/%2$dページ"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"ここがあなたのホームです"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"お気に入りのアプリをここに置くことができます。"</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"すべてのアプリを見るにはサークルをタップします。"</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"アプリの選択"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"アプリをホーム画面に追加するにはアプリを押し続けます。"</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"フォルダでアプリを整理"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"アプリを移動するにはアプリを押し続けます。"</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"ホーム画面に新しいフォルダを作成するには、アプリを他のアプリの上に重ねます。"</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"フォルダが開いています。<xliff:g id="WIDTH">%1$d</xliff:g>x<xliff:g id="HEIGHT">%2$d</xliff:g>の大きさです"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"タップしてフォルダを閉じます"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"タップして名前の変更を保存します"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"フォルダは閉じています"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"フォルダの名前を「<xliff:g id="NAME">%1$s</xliff:g>」に変更しました"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"フォルダ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ko/strings.xml b/FairphoneHome/res/values-ko/strings.xml
new file mode 100644
index 0000000..990dcfb
--- /dev/null
+++ b/FairphoneHome/res/values-ko/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"홈"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core 애플리케이션"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"배경화면 선택"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"배경화면 설정"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"배경화면"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"앱이 설치되지 않았습니다."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"위젯"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"위젯을 선택하려면 길게 터치하세요."</string>
+    <string name="market" msgid="2652226429823445833">"쇼핑"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"홈 화면에 항목을 놓을 수 없습니다."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"만들 위젯 선택"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"폴더 이름"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"폴더 이름 바꾸기"</string>
+    <string name="rename_action" msgid="6016003384693240896">"확인"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"취소"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"홈 화면에 추가"</string>
+    <string name="group_applications" msgid="2103752818818161976">"앱"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"바로가기"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"위젯"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"배경화면"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"홈 화면에 더 이상 공간이 없습니다."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"홈 화면에 더 이상 공간이 없습니다."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"즐겨찾는 앱 모음에 더 이상 빈 공간이 없습니다."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"이 위젯은 핫시트에 너무 큽니다."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 생성되었습니다."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 삭제되었습니다."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 이미 있습니다."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"바로가기 선택"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"앱 선택"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"애플리케이션"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"홈"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"삭제"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"제거"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"삭제"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"제거"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"앱 정보"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"검색"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"음성 검색"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"앱"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"삭제"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"업데이트 제거"</string>
+    <string name="menu_add" msgid="3065046628354640854">"추가"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"애플리케이션 관리"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"배경화면"</string>
+    <string name="menu_search" msgid="4826514464423239041">"검색"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"알림"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"시스템 설정"</string>
+    <string name="menu_help" msgid="4901160661634590633">"도움말"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"앱 제거"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"앱 세부정보"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"앱 1개 선택됨"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1개 위젯 선택"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1개 폴더 선택"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1개 바로가기 선택"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"바로가기 설치"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"앱이 사용자의 작업 없이 바로가기를 추가할 수 있도록 합니다."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"바로가기 제거"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"앱이 사용자의 작업 없이 바로가기를 삭제할 수 있도록 합니다."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"홈 설정 및 바로가기 읽기"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"앱이 홈에 있는 설정 및 바로가기를 읽을 수 있도록 합니다."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"홈 설정 및 바로가기 쓰기"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"앱이 홈에 있는 설정 및 바로가기를 변경할 수 있도록 합니다."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"위젯을 로드하는 중 문제가 발생했습니다."</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"시스템 앱은 제거할 수 없습니다."</string>
+    <string name="dream_name" msgid="2847171357608437154">"로켓 실행기"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"이름이 없는 폴더"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"홈 화면 %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"페이지 %2$d 중 %1$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"홈 화면 %1$d/%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"앱 페이지 %2$d 중 %1$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"위젯 페이지 %2$d 중 %1$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"나만의 홈 화면 만들기"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"자주 사용하는 앱을 홈 화면으로 가져오세요."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"전체 앱을 보려면 원을 터치합니다."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"앱 선택하기"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"홈 화면에 앱을 추가하려면 길게 터치합니다."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"폴더를 사용하여 앱을 정리하세요."</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"앱을 이동하려면 길게 터치합니다."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"홈 화면에 새로운 폴더를 만들려면 앱 하나를 다른 앱 위에 겹쳐 놓습니다."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"확인"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"폴더 열림(<xliff:g id="WIDTH">%1$d</xliff:g>X<xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"터치하여 폴더를 닫음"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"터치하여 바꾼 이름을 저장"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"폴더 닫음"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"폴더 이름 변경: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"폴더: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-land/config.xml b/FairphoneHome/res/values-land/config.xml
new file mode 100644
index 0000000..fc20456
--- /dev/null
+++ b/FairphoneHome/res/values-land/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<resources>
+<!-- Workspace -->
+    <!-- Whether or not the drop targets drop down as opposed to fade in -->
+    <bool name="config_useDropTargetDownTransition">false</bool>
+    <!-- Whether or not to fade the side pages -->
+    <bool name="config_workspaceFadeAdjacentScreens">false</bool>
+
+    <!-- Folder max bounds and max number of items.
+         Note: folder_max_count_x * folder_max_count_y >= folder_max_num_items. -->
+    <integer name="folder_max_count_x">6</integer>
+    <integer name="folder_max_count_y">3</integer>
+</resources>
diff --git a/FairphoneHome/res/values-land/dimens.xml b/FairphoneHome/res/values-land/dimens.xml
new file mode 100644
index 0000000..5edd143
--- /dev/null
+++ b/FairphoneHome/res/values-land/dimens.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<resources>
+<!-- QSB -->
+    <dimen name="toolbar_button_vertical_padding">8dip</dimen>
+    <dimen name="toolbar_button_horizontal_padding">0dip</dimen>
+
+<!-- Workspace -->
+    <dimen name="hotseat_cell_width">64dp</dimen>
+    <dimen name="hotseat_cell_height">58dp</dimen>
+    <!-- We really want the page spacing to be the max of either the button bar
+     height or the qsb bar height -->
+    <dimen name="workspace_page_spacing">-1dp</dimen>
+    <dimen name="workspace_divider_padding_left">0dp</dimen>
+    <dimen name="workspace_divider_padding_right">0dp</dimen>
+    <dimen name="workspace_divider_padding_top">12dp</dimen>
+    <dimen name="workspace_divider_padding_bottom">12dp</dimen>
+
+    <!-- Block spacing on each side of the screen.  And also padding
+         for the portals to look right. -->
+    <dimen name="cell_layout_left_padding">@dimen/cell_layout_left_padding_land</dimen>
+    <dimen name="cell_layout_right_padding">@dimen/cell_layout_right_padding_land</dimen>
+    <dimen name="cell_layout_top_padding">@dimen/cell_layout_top_padding_land</dimen>
+    <dimen name="cell_layout_bottom_padding">@dimen/cell_layout_bottom_padding_land</dimen>
+    <!-- Workspace padding -->
+    <dimen name="workspace_left_padding">@dimen/workspace_left_padding_land</dimen>
+    <dimen name="workspace_right_padding">@dimen/workspace_right_padding_land</dimen>
+    <dimen name="workspace_top_padding">@dimen/workspace_top_padding_land</dimen>
+    <dimen name="workspace_bottom_padding">@dimen/workspace_bottom_padding_land</dimen>
+
+    <dimen name="app_icon_padding_top">6dp</dimen>
+
+    <!-- height of the bottom row of controls -->
+    <dimen name="button_bar_height">68dip</dimen>
+    <!-- Because portal animations go beyond the bounds of an icon, we need
+         to make the dock layout slightly larger than the button_bar_height -->
+    <dimen name="button_bar_height_top_padding">8dp</dimen>
+    <dimen name="button_bar_height_bottom_padding">0dp</dimen>
+    <dimen name="button_bar_width_left_padding">0dp</dimen>
+    <dimen name="button_bar_width_right_padding">0dp</dimen>
+    <dimen name="button_bar_height_plus_padding">76dp</dimen>
+
+<!-- AppsCustomize -->
+    <dimen name="apps_customize_cell_width">80dp</dimen>
+    <!-- The width can be 76dp because we don't have B padding -->
+    <dimen name="apps_customize_cell_height">76dp</dimen>
+    <dimen name="apps_customize_pageLayoutWidthGap">-1dp</dimen>
+    <dimen name="apps_customize_pageLayoutHeightGap">-1dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingTop">5dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingBottom">5dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingLeft">5dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingRight">5dp</dimen>
+    <dimen name="apps_customize_tab_bar_height">42dp</dimen>
+    <dimen name="apps_customize_widget_cell_width_gap">30dp</dimen>
+    <dimen name="apps_customize_widget_cell_height_gap">5dp</dimen>
+    <integer name="apps_customize_widget_cell_count_x">3</integer>
+    <integer name="apps_customize_widget_cell_count_y">2</integer>
+    <integer name="apps_customize_cling_focused_x">2</integer>
+    <integer name="apps_customize_cling_focused_y">1</integer>
+
+<!-- Folders -->
+    <!-- The size of the image which sits behind the preview of the folder contents -->
+    <dimen name="folder_preview_size">58dp</dimen>
+
+<!-- Workspace cell size -->
+    <dimen name="workspace_cell_width">@dimen/workspace_cell_width_land</dimen>
+    <dimen name="workspace_cell_height">@dimen/workspace_cell_height_land</dimen>
+    <dimen name="workspace_width_gap">@dimen/workspace_width_gap_land</dimen>
+    <dimen name="workspace_height_gap">@dimen/workspace_height_gap_land</dimen>
+</resources>
diff --git a/FairphoneHome/res/values-land/strings.xml b/FairphoneHome/res/values-land/strings.xml
new file mode 100644
index 0000000..ec4c7e7
--- /dev/null
+++ b/FairphoneHome/res/values-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Manifest configuration. -->
+    <skip />
+</resources>
diff --git a/FairphoneHome/res/values-land/styles.xml b/FairphoneHome/res/values-land/styles.xml
new file mode 100644
index 0000000..5b9de3e
--- /dev/null
+++ b/FairphoneHome/res/values-land/styles.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources>
+<!-- Search Bar -->
+    <style name="QSBBar">
+        <item name="android:orientation">vertical</item>
+        <item name="android:layout_width">@dimen/qsb_bar_height</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">left</item>
+    </style>
+    <style name="SearchDropTargetBar">
+        <item name="android:orientation">vertical</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_gravity">center_horizontal</item>
+    </style>
+    <style name="SearchButton">
+        <item name="android:layout_gravity">center_horizontal</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+    </style>
+    <style name="DropTargetButtonContainer">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">0dp</item>
+    </style>
+    <style name="DropTargetButton">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:gravity">center</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:shadowColor">#DD000000</item>
+        <item name="android:shadowDx">0.0</item>
+        <item name="android:shadowDy">1.0</item>
+        <item name="android:shadowRadius">4.0</item>
+    </style>
+
+<!-- AppsCustomize -->
+    <style name="TabIndicator.AppsCustomize">
+        <item name="android:maxWidth">200dp</item>
+    </style>
+</resources>
+
diff --git a/FairphoneHome/res/values-lt/strings.xml b/FairphoneHome/res/values-lt/strings.xml
new file mode 100644
index 0000000..885ecf0
--- /dev/null
+++ b/FairphoneHome/res/values-lt/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Paleidimo priemonė"</string>
+    <string name="home" msgid="5921706419368316758">"Pagrindinis"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Pagrindinės „Android“ programos"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Pasirinkti darbalaukio foną iš"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Nustatyti darbalaukio foną"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Darbalaukio fonai"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Programa neįdiegta."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Valdikliai"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Kad pasirinkt. valdiklį, palieskite ir laikykite."</string>
+    <string name="market" msgid="2652226429823445833">"Parduotuvė"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Nepavyko nuvilkti elemento į šį pagrind. ekraną."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Pasirinkite norimą kurti valdiklį"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Aplanko pavadinimas"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Sukurti aplankui naują pavadinimą"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Gerai"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Atšaukti"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Pridėti prie pagrindinio ekrano"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Programos"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Spartieji klavišai"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Valdikliai"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Darbalaukio fonai"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Pagrindiniuose ekranuose vietos nebėra."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Šiame pagrindiniame ekrane vietos nebėra."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Įtvirtintoje srityje nebėra vietos."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Šis valdiklis per didelis keliems žaidėjams."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Sukurtas „<xliff:g id="NAME">%s</xliff:g>“ spartusis klavišas."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ pašalintas."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Spartusis klavišas „<xliff:g id="NAME">%s</xliff:g>“ jau yra."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Pasirinkite spartųjį klavišą"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Pasirinkite programą"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Pagrindinis"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Pašalinti"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Pašalinti"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Pašalinti"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Pašalinti"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Programos informacija"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Ieškoti"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Balso paieška"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Programos"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Pašalinti"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Pašalinti naujinį"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Pridėti"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Valdyti programas"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Darbalaukio fonas"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Ieškoti"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Įspėjimai"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Sistemos nustatymai"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Pagalba"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Pašalinti programą"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Išsami programos informacija"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Pasirinkta programų: 1"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Pasirinktas 1 valdiklis"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Pasirinktas 1 aplankas"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Pasirinktas 1 spartusis klavišas"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"įdiegti sparčiuosius klavišus"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Leidžiama programai pridėti sparčiuosius klavišus be naudotojo įsikišimo."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"pašalinti sparčiuosius klavišus"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Programai leidžiama pašalinti sparčiuosius klavišus be naudotojo įsikišimo."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"skaityti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Programai leidžiama skaityti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"rašyti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Programai leidžiama keisti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problema įkeliant valdiklį"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Tai sistemos programa ir jos negalima pašalinti."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Raketinis prieštankinis šautuvas"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Aplankas be pavadinimo"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"%1$d pagrindinis ekranas"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"%1$d psl. iš %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"%1$d iš %2$d pagrindinis ekranas"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Programų puslapis: %1$d iš %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Valdiklių puslapis: %1$d iš %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Jauskitės kaip namie"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Čia galite dėti mėgstamiausias savo programas."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Jei norite matyti visas programas, palieskite apskritimą."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Pasirinkite kelias programas"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Jei norite prie pagrindinio ekrano pridėti programą, palieskite ją ir laikykite."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Tvarkykite programas kurdami aplankus"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Jei norite perkelti programą, palieskite ją ir laikykite."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Jei pagrindiniame ekrane norite sukurti naują aplanką, uždėkite vieną programą ant kitos."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Gerai"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Atidarytas aplankas, <xliff:g id="WIDTH">%1$d</xliff:g> ir <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Palieskite, kad uždarytumėte aplanką"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Palieskite, kad išsaugotumėte naują pavadinimą"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Aplankas uždarytas"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Aplankas pervardytas kaip „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Aplankas: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-lv/strings.xml b/FairphoneHome/res/values-lv/strings.xml
new file mode 100644
index 0000000..c1cd545
--- /dev/null
+++ b/FairphoneHome/res/values-lv/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Palaidējs"</string>
+    <string name="home" msgid="5921706419368316758">"Sākums"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android kodola lietojumprogrammas"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Fona tapetes izvēle:"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Iestatīt tapeti"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Tapetes"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Lietotne nav instalēta."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Logrīki"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Lai izvēlētos logrīku, pieskarieties tam un turiet to."</string>
+    <string name="market" msgid="2652226429823445833">"Iepirkties"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Nevarēja nomest vienumu šajā sākuma ekrānā."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Izveidojamā logrīka izvēlēšanās"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Mapes nosaukums"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Mapes pārdēvēšana"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Labi"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Atcelt"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Pievienot sākuma ekrānam"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Lietotnes"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Saīsnes"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Logrīki"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Tapetes"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Sākuma ekrānos vairs nav vietas."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Šajā sākuma ekrānā vairs nav vietas."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Režīmā Hotseat vairs nav vietas."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Šis logrīks ir pārāk liels režīmam “hotseat”."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Saīsne “<xliff:g id="NAME">%s</xliff:g>” tika izveidota."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Saīsne “<xliff:g id="NAME">%s</xliff:g>” tika noņemta."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Saīsne “<xliff:g id="NAME">%s</xliff:g>” jau pastāv."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Saīsnes izvēle"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Lietotnes izvēlēšanās"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Lietotnes"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Sākums"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Noņemt"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Atinstalēt"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Noņemt"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Atinstalēt"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Lietotnes informācija"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Meklēt"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Balss meklēšana"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Lietotnes"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Noņemt"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Atinstalēt atjauninājumu"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Pievienot"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Lietotņu pārvaldība"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Fona tapete"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Meklēt"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Paziņojumi"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Sistēmas iestatījumi"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Palīdzība"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Atinstalēt lietotni"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Lietotnes informācija"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Atlasīta 1 lietotne"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Atlasīts 1 logrīks"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Atlasīta 1 mape"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Atlasīta 1 saīsne"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"ievietot saīsnes"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Ļauj lietotnei pievienot saīsnes, nejautājot lietotājam."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"atinstalēt saīsnes"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Ļauj lietotnei noņemt saīsnes, nejautājot lietotājam."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"lasīt sākuma ekrāna iestatījumus un saīsnes"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Ļauj lietotnei lasīt iestatījumus un saīsnes sākuma ekrānā."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"rakstīt sākuma ekrāna iestatījumus un saīsnes"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Ļauj lietotnei mainīt iestatījumus un saīsnes sākuma ekrānā."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Radās problēma, ielādējot logrīku"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Šī ir sistēmas lietotne, un to nevar atinstalēt."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Mape bez nosaukuma"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Sākuma ekrāns: %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"%1$d. lapa no %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Sākuma ekrāns: %1$d no %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"%1$d. lietotņu lapa no %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"%1$d. logrīku lapa no %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Jūtieties kā mājās"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Šeit varat ievietot savas iecienītākās lietotnes."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Lai skatītu visas lietotnes, pieskarieties aplim."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Izvēlieties dažas lietotnes"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Lai sākuma ekrānam pievienotu lietotni, pieskarieties tai un turiet to nospiestu."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Kārtojiet lietotnes mapēs"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Lai pārvietotu lietotni, pieskarieties tai un turiet to nospiestu."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Lai sākuma ekrānā izveidotu jaunu mapi, novietojiet vienu lietotni virs citas lietotnes."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Labi"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Atvērta mape: <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Pieskarieties, lai aizvērtu mapi."</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Pieskarieties, lai saglabātu pārdēvēto nosaukumu."</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mape aizvērta"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mape pārdēvēta par: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mape: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ms/strings.xml b/FairphoneHome/res/values-ms/strings.xml
new file mode 100644
index 0000000..3f2d0d8
--- /dev/null
+++ b/FairphoneHome/res/values-ms/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Pelancar"</string>
+    <string name="home" msgid="5921706419368316758">"Laman Utama"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Apl Teras Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Pilih kertas dinding dari"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Tetapkan kertas dinding"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Kertas dinding"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Aplikasi tidak dipasang."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widget"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Sentuh &amp; tahan untuk mengambil widget."</string>
+    <string name="market" msgid="2652226429823445833">"Kedai"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Tidak dapat melepaskan item pada skrin Utama ini."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Pilih widget untuk dibuat"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nama folder"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Namakan semula folder"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Batal"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Tambah ke Skrin utama"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplikasi"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Pintasan"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Kertas dinding"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Tiada lagi ruang pada skrin Utama anda."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Tiada lagi ruang pada skrin Utama ini"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Tiada lagi ruang pada kerusi panas."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Widget ini terlalu besar untuk kerusi panas."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" diwujudkan."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" telah dialih keluar."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Pintasan \"<xliff:g id="NAME">%s</xliff:g>\" sudah pun wujud."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Pilih pintasan"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Pilih aplikasi"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apl"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Laman Utama"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Alih keluar"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Nyahpasang"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Alih keluar"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Nyahpasang"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Maklumat apl"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Carian"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Carian Suara"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplikasi"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Alih keluar"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Nyahpasang kemas kini"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Tambah"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Mengurus apl"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Kertas dinding"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Cari"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Pemberitahuan"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Tetapan sistem"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Bantuan"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Nyahpasang aplikasi"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Butiran aplikasi"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 aplikasi dipilih"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget dipilih"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 folder dipilih"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 pintasan dipilih"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"pasang pintasan"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Membenarkan aplikasi menambah pintasan tanpa campur tangan pengguna."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"nyahpasang pintasan"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Membenarkan apl mengalih keluar pintasan tanpa campur tangan pengguna."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"membaca tetapan dan pintasan Laman Utama"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Membenarkan apl membaca tetapan dan pintasan di Laman Utama."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"menulis tetapan dan pintasan Laman Utama"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Membenarkan apl menukar tetapan dan pintasan di Laman Utama."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Masalah memuatkan widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Ini adalah aplikasi sistem dan tidak boleh dinyahpasang."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Pelancar Roket"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Folder Tanpa Nama"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Skrin utama %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Halaman %1$d dari %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Skrin utama %1$d dari %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Halaman apl %1$d dari %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Halaman widget %1$d dari %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Buat diri anda seperti di rumah"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Anda boleh meletakkan aplikasi kegemaran anda di sini."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Untuk melihat semua aplikasi anda, sentuh bulatan."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Pilih beberapa aplikasi"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Untuk menambahkan aplikasi pada skrin Utama anda, sentuh &amp; tahankannya."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Susun aplikasi anda dengan folder"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Untuk memindahkan aplikasi, sentuh &amp; tahankannya."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Untuk membuat folder baharu pada skrin Utama anda, tindihkan satu aplikasi di atas yang lain."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Folder dibuka, <xliff:g id="WIDTH">%1$d</xliff:g> kali <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Sentuh untuk menutup folder"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Sentuh untuk menyimpan penamaan semula"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Folder ditutup"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Folder dinamakan semula kepada <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-nb/strings.xml b/FairphoneHome/res/values-nb/strings.xml
new file mode 100644
index 0000000..a345516
--- /dev/null
+++ b/FairphoneHome/res/values-nb/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Utskytingsrampe"</string>
+    <string name="home" msgid="5921706419368316758">"Home"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android-kjerneapplikasjoner"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Velg bakgrunnsbilde fra"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Velg som bakgrunnsbilde"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Bakgrunner"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Appen er ikke installert."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Moduler"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Trykk og hold inne for å plukke opp en modul."</string>
+    <string name="market" msgid="2652226429823445833">"Butikk"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Kunne ikke slippe elementet på denne startsiden."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Velg modul for oppretting"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Mappenavn"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Gi nytt navn til mappe"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Avbryt"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Legg til skrivebord"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apper"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Snarveier"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Skrivebordselementer"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Bakgrunner"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Det er ikke mer plass på startsidene dine."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Ikke nok plass på skrivebordet."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Dokksonen er full."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Denne modulen er for stor for hotseat-feltet."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Opprettet snarveien «<xliff:g id="NAME">%s</xliff:g>»."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Fjernet snarveien «<xliff:g id="NAME">%s</xliff:g>»."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» fins allerede."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Valg av snarvei"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Velg app"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apper"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsiden"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstaller"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Fjern"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Avinstaller"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"App-info"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Søk"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Talesøk"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apper"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Fjern"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstaller oppdateringen"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Legg til"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Administrer apper"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Bakgrunnsbilde"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Søk"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Varslinger"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Systeminnstillinger"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Hjelp"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Avinstaller appen"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Informasjon om appen"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Én app er valgt"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 modul valgt"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mappe valgt"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 snarvei valgt"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"installere snarveier"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Gir apper tillatelse til å legge til snarveier uten innblanding fra brukeren."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"avinstallere snarveier"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"La appen fjerne snarveier uten innblanding fra brukeren."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"lese skrivebordsinnstillinger og -snarveier"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Lar appen lese innstillingene og snarveiene på startsiden."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"skrive skrivebordsinnstillinger og -snarveier"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Lar appen endre innstillingene og snarveiene på startsiden."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problem under lasting av gadget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Dette er en systemapp som ikke kan avinstalleres."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Mappe uten navn"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Startside %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Side %1$d av %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Startside %1$d av %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Appside %1$d av %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Modulside %1$d av %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Føl deg hjemme"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Her kan du plassere favorittappene dine."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Trykk på sirkelen for å se alle appene dine."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Velg noen apper"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Trykk og hold inne på en app for å legge den til på startsiden."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Bruk mapper for å holde orden på appene dine"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Berør og hold nede en app for å flytte den."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Du kan lage en ny mappe på startsiden ved å stable én app oppå en annen."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Mappen er åpnet – <xliff:g id="WIDTH">%1$d</xliff:g> ganger <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Trykk for å lukke mappen"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Trykk for å lagre nytt navn"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mappen ble lukket"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mappen heter nå <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-nl/strings.xml b/FairphoneHome/res/values-nl/strings.xml
new file mode 100644
index 0000000..048d04d
--- /dev/null
+++ b/FairphoneHome/res/values-nl/strings.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Fairphone OS"</string>
+    <string name="home" msgid="5921706419368316758">"Startpagina"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android-kerntoepassingen"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Achtergrond kiezen van"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Achtergrond instellen"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Achtergronden"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"App is niet geïnstalleerd."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Blijf aanraken om een widget toe te voegen"</string>
+    <string name="market" msgid="2652226429823445833">"Winkel"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Kan item niet neerzetten in dit startscherm."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Widget selecteren om te maken"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Mapnaam"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Naam van map wijzigen"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Annuleren"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Toevoegen aan startpagina"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apps"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Sneltoetsen"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Achtergronden"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Er is geen ruimte meer op uw startschermen."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Er is geen ruimte meer op dit startscherm."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Er is geen ruimte meer op de hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Deze widget is te groot voor de hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is gemaakt."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is verwijderd."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' bestaat al."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Snelkoppeling selecteren"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"App selecteren"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startpagina"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Verwijderen"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Verwijderen"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Verwijderen"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Installatie ongedaan maken"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"App-info"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Zoeken"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Gesproken zoekopdrachten"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apps"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Verwijderen"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update verwijderen"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Toevoegen"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Apps beheren"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Achtergrond"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Zoeken"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Meldingen"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Systeeminstellingen"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Help"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"App verwijderen"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"App-details"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 app geselecteerd"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget geselecteerd"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 map geselecteerd"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 snelkoppeling geselecteerd"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"snelkoppelingen installeren"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"snelkoppelingen verwijderen"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Toestaan dat de app snelkoppelingen verwijdert zonder tussenkomst van de gebruiker."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"instellingen en snelkoppelingen voor de startpagina lezen"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Toestaan dat de app de instellingen en snelkoppelingen op de startpagina leest."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"instellingen en snelkoppelingen voor de startpagina schrijven"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Toestaan dat de app de instellingen en snelkoppelingen op de startpagina wijzigt."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Probleem bij het laden van widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Dit is een systeemapp die niet kan worden verwijderd."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Naamloze map"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Startscherm %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Pagina %1$d van %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Startscherm %1$d van %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"App-pagina %1$d van %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widgetpagina %1$d van %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Doe maar alsof u thuis bent"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"U kunt hier uw favoriete apps plaatsen."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Als u al uw apps wilt bekijken, raakt u de cirkel aan."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Enkele apps selecteren"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Als u een app wilt toevoegen aan het startscherm, blijft u de app aanraken."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Uw apps ordenen met mappen"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Als u een app wilt verplaatsen, blijft u de app aanraken."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Als u een nieuwe map op het startscherm wilt maken, stapelt u een app boven op een andere app."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Map geopend, <xliff:g id="WIDTH">%1$d</xliff:g> bij <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Raak dit aan om de map te sluiten"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Raak dit aan om naam wijzigen op te slaan"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Map gesloten"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"De naam van de map is gewijzigd in <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Map: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+    
+    <!-- Fairphone -->
+    <!-- Your Apps -->
+    <string name="your_apps">Your Apps</string>
+    
+    <string name="last_used_apps">Laatst gebruikte applicaties</string>
+    <string name="last_used">Laatst gebruikt</string>
+    <string name="most_used_apps">Meeste gebruikte applicaties</string>
+    <string name="most_used">Meest gebruikt</string>
+    <string name="no_apps_have_been_opened_yet">Nog geen applicaties geopend? Begin met het gebruiken van je telefoon en kom terug naar dit scherm</string>
+    <string name="reset">Reset</string>
+    <string name="app_switcher_reset_message">Weet je het zeker?</string>
+    
+    <!-- Settings -->
+    <string name="energy_mood">Energie Mood op slot scherm</string>
+    <string name="energy_mood_summary">Weergave batterij niveau als achtergrondkleur op slot scherm</string>
+    
+    <!-- Quick Access -->
+    <string name="quick_access">Quick Access</string>
+    <string name="edit">Bewerken</string>
+    <string name="favourite_apps">Favoriete applicaties</string>
+    <string name="drag_here_to_add">Sleep hier\nom toe\nte voegen</string>
+    <string name="drag_here_to_remove">Sleep hierheen\nom te\nverwijderen</string>
+    
+    <!-- OOBE Texts -->
+	<string name="oobe_quick_access">Quick Access</string>
+	<string name="oobe_select_language">Selecteer\nTaal</string>
+	<string name="oobe_setup_wifi">Setup\nWi-Fi</string>
+	<string name="oobe_intro_top">Welkom! In je handen ligt een telefoon geproduceerd met sociale waardes op de eerste plaats. En ja, je kan er ook nog mee bellen!</string>
+	<string name="oobe_intro_bottom">We laten je zien hoe het werkt</string>
+	
+	<string name="oobe_edge_swipe_title">Veeg van links</string>
+	<string name="oobe_edge_swipe_text">of rechts om de applicatie te starten</string>
+	
+	<string name="oobe_open_app_title">Tik op de juiste</string>
+	<string name="oobe_open_app_text">applicatie om te openen</string>
+	
+	<string name="oobe_edit_drag_intro">De applicaties zijn versleepbaar, dus gemakkelijk te verplaatsen</string>
+	
+	<string name="oobe_edit_drag_add_title">Versleep naar</string>
+	<string name="oobe_edit_drag_add_text">de rechterzijde om toe te voegen aan favorieten</string>
+	
+	<string name="oobe_edit_drag_remove_title">Versleep naar</string>
+	<string name="oobe_edit_drag_remove_text">de linkerzijde om uit favorieten te verwijderen</string>
+	
+	<string name="oobe_edit_drag_trade_title">Versleep de favorieten</string>
+	<string name="oobe_edit_drag_trade_text">om van positie te veranderen</string>
+	
+	<string name="oobe_your_apps_intro">Al je meest gebruikte applicaties op één plaats</string>
+	<string name="oobe_your_apps_learning">Je telefoon leert van jouw gebruik en onthoudt de meest gebruikte applicaties</string>
+	<string name="oobe_your_apps_last_ones">Zie ook de applicaties die je als laatst hebt gebruikt</string>
+	<string name="oobe_your_apps_start_using">Begin met het gebruiken van je telefoon, de applicaties wachten hier op je</string>
+	
+	<string name="oobe_start">Start</string>
+	<string name="oobe_back">Terug</string>
+	<string name="oobe_skip">Overslaan</string>
+	<string name="oobe_next">Volgende</string>
+	<string name="oobe_done">Sluiten</string>
+	
+	<!-- Google Apps Install Widget -->
+    <string name="google_apps_installer_name">Google Apps Installer</string>
+	<string name="google_apps_initial_title">Installeer\nGoogle Apps</string>
+	<string name="google_apps_disclaimer_title">Installeer Google Apps</string>
+	<string name="google_apps_disclaimer_description">Voor de volledige Android en Google mobile toepassingen, zoals de Google Play store, heeft je telefoon extra inhoud en software nodig. Omdat Fairphone nog geen licentie heeft kunnen we die inhoud jammer genoeg niet van tevoren installeren en we kunnen het ook niet rechtstreeks ter beschikking stellen. We zijn hierover in overleg met de eigenaar van de inhoud.\nDruk op “Accepteren” hieronder om de inhoud te downloaden van een externe, veilige bron. Het installeren van deze inhoud is voor eigen verantwoordelijkheid.\nAls je hier niet mee akkoord gaat, zal je telefoon natuurlijk nog werken met de basis apps voor Android, maar je zult een aantal diensten van Google niet kunnen gebruiken.</string>
+	<string name="google_apps_disclaimer_agree">Accepteren</string>
+	<string name="google_apps_denied_permissions_title">Geen toestemming</string>
+	<string name="google_apps_denied_permissions_description">Fairphone OS heeft geen toestemming voor het installeren van Google Apps. Als je NEGEREN kiest, start dan de installer opnieuw en geef TOESTEMMING.</string>
+	<string name="google_apps_reboot_failed_title">Herstarten mislukt</string>
+	<string name="google_apps_reboot_failed_description">Google Apps zijn geïnstalleerd. Herstart van het apparaat niet gelukt, a.u.b. handmatige herstarten.</string>
+	<string name="google_apps_download_title">Bezig met de download van\nGoogle Apps</string>
+	<string name="google_apps_unzip_title">Bezig met het uitpakken van\nGoogle Apps</string>
+	<string name="google_apps_install_title">Bezig met het installeren van\nGoogle Apps</string>
+	<string name="google_apps_reboot_title">Apparaat aan het herstarten</string>
+	<string name="google_apps_permissions_description">Fairphone OS vraagt nu om toegang als Superuser. We verzekeren je dat het helemaal veilig is. Kies TOESTAAN als daarom wordt gevraagd.</string>
+	<string name="google_apps_permissions_title">Toegangsrechten tot het systeem</string>
+	<string name="google_apps_reboot_description">Het systeem moet opnieuw worden gestart om de installatie af te ronden.\nVolg na het herstarten de stappen voor het opzetten van Google Apps.</string>
+	<string name="google_apps_uninstall_title">Google Apps geïnstalleerd</string>
+	<string name="google_apps_uninstall_description">Deze installer\nverwijderen</string>
+	<string name="google_apps_failed_download_title">Downloaden mislukt</string>
+	<string name="google_apps_failed_download_description">De gedownloade bestanden zijn corrupt. Opnieuw proberen?</string>
+	<string name="google_apps_download_error">Fout bij het downloaden van de bestanden. Probeer het opnieuw.</string>
+	<string name="google_apps_connection_title">Wi-Fi niet beschikbaar</string>
+	<string name="google_apps_connection_description">Het bestand dat je probeert te downloaden is te groot voor mobiele verbindingen (~100MB). Breng de Wi-Fi verbinding tot stand en probeer het opnieuw.</string>
+	
+</resources>
diff --git a/FairphoneHome/res/values-nl/styles.xml b/FairphoneHome/res/values-nl/styles.xml
new file mode 100644
index 0000000..bf29f45
--- /dev/null
+++ b/FairphoneHome/res/values-nl/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="SubTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">11.3sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">14.5sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-2dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEDescriptionText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">13sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values-pl/strings.xml b/FairphoneHome/res/values-pl/strings.xml
new file mode 100644
index 0000000..20b4217
--- /dev/null
+++ b/FairphoneHome/res/values-pl/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Program uruchamiający"</string>
+    <string name="home" msgid="5921706419368316758">"Strona główna"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Aplikacje główne systemu Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Wybierz tapetę z..."</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Ustaw tapetę"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Tapety"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Aplikacja nie jest zainstalowana."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widżety"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Aby dodać widżet, dotknij go i przytrzymaj."</string>
+    <string name="market" msgid="2652226429823445833">"Sklep"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Nie można upuścić elementu na tym ekranie głównym."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Wybierz widżet, który chcesz dodać"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nazwa folderu"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Zmień nazwę folderu"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Anuluj"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Dodaj do strony głównej"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplikacje"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Skróty"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widżety"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Tapety"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Brak miejsca na Twoich ekranach głównych."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Brak miejsca na tej stronie głównej"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Brak miejsca w kieszonce."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Ten widżet jest za duży, aby umieścić go w kieszonce."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został utworzony."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został usunięty."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Skrót „<xliff:g id="NAME">%s</xliff:g>” już istnieje."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Wybierz skrót"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Wybierz aplikację"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplikacje"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekran główny"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Usuń"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstaluj"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Usuń"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Odinstaluj"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"O aplikacji"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Szukaj"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Wyszukiwanie głosowe"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplikacje"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Usuń"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstaluj aktualizację"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Zarządzaj aplikacjami"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Szukaj"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Powiadomienia"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Ustawienia systemu"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Pomoc"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Odinstaluj aplikację"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Szczegóły aplikacji"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Wybrano 1 aplikację"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Zaznaczono 1 widżet"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Zaznaczono 1 folder"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Zaznaczono 1 skrót"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"zainstaluj skróty"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Pozwala aplikacji dodawać skróty bez interwencji użytkownika."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"odinstaluj skróty"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Pozwala aplikacji usuwać skróty bez interwencji użytkownika."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"odczytywanie ustawień i skrótów strony głównej"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Umożliwia aplikacji odczytywanie ustawień i skrótów na ekranie głównym."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"zapisywanie ustawień i skrótów strony głównej"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Umożliwia aplikacji zmianę ustawień i skrótów na ekranie głównym."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problem podczas ładowania widżetu"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"To jest aplikacja systemowa, której nie możesz odinstalować."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Wyrzutnia rakiet"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Folder bez nazwy"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Ekran główny %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Strona %1$d z %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Ekran główny %1$d z %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Strona aplikacji: %1$d z %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Strona widżetów: %1$d z %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Rozgość się"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Dodaj tu swoje ulubione aplikacje."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Aby zobaczyć wszystkie aplikacje, dotknij okręgu."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Wybierz kilka aplikacji"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"By dodać aplikację na ekran główny, dotknij i przytrzymaj jej ikonę."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Uporządkuj swoje aplikacje za pomocą folderów"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Dotknij i przytrzymaj, aby przenieść aplikację."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Aby utworzyć nowy folder na ekranie głównym, ułóż aplikacje jedna na drugiej."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Folder otwarty, <xliff:g id="WIDTH">%1$d</xliff:g> na <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Dotknij, aby zamknąć folder"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Dotknij, aby zapisać zmianę nazwy"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Folder zamknięty"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Nazwa folderu zmieniona na <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-port/dimens.xml b/FairphoneHome/res/values-port/dimens.xml
new file mode 100644
index 0000000..969d335
--- /dev/null
+++ b/FairphoneHome/res/values-port/dimens.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<resources>
+<!-- QSB -->
+    <dimen name="qsb_bar_height_inset">37dp</dimen>
+    <dimen name="qsb_bar_height">43dp</dimen>
+    <dimen name="qsb_padding_left">3dp</dimen>
+    <dimen name="qsb_padding_right">3dp</dimen>
+
+<!-- Workspace -->
+    <!-- Block spacing on each side of the screen.  And also padding
+         for the portals to look right. -->
+    <dimen name="cell_layout_left_padding">@dimen/cell_layout_left_padding_port</dimen>
+    <dimen name="cell_layout_right_padding">@dimen/cell_layout_right_padding_port</dimen>
+    <dimen name="cell_layout_top_padding">@dimen/cell_layout_top_padding_port</dimen>
+    <dimen name="cell_layout_bottom_padding">@dimen/cell_layout_bottom_padding_port</dimen>
+    <!-- Workspace padding -->
+    <dimen name="workspace_left_padding">@dimen/workspace_left_padding_port</dimen>
+    <dimen name="workspace_right_padding">@dimen/workspace_right_padding_port</dimen>
+    <dimen name="workspace_top_padding">@dimen/workspace_top_padding_port</dimen>
+    <dimen name="workspace_bottom_padding">@dimen/workspace_bottom_padding_port</dimen>
+
+    <dimen name="workspace_page_spacing">-1dp</dimen>
+
+<!-- AppsCustomize -->
+    <dimen name="apps_customize_pageLayoutWidthGap">-1dp</dimen>
+    <dimen name="apps_customize_pageLayoutHeightGap">-1dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingTop">10dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingBottom">10dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingLeft">5dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingRight">5dp</dimen>
+    <integer name="apps_customize_cling_focused_x">1</integer>
+    <integer name="apps_customize_cling_focused_y">1</integer>
+
+    <dimen name="apps_customize_widget_cell_width_gap">20dp</dimen>
+    <dimen name="apps_customize_widget_cell_height_gap">10dp</dimen>
+    <integer name="apps_customize_widget_cell_count_x">2</integer>
+    <integer name="apps_customize_widget_cell_count_y">3</integer>
+
+<!-- Workspace cell size -->
+    <dimen name="workspace_cell_width">@dimen/workspace_cell_width_port</dimen>
+    <dimen name="workspace_cell_height">@dimen/workspace_cell_height_port</dimen>
+    <dimen name="workspace_width_gap">@dimen/workspace_width_gap_port</dimen>
+    <dimen name="workspace_height_gap">@dimen/workspace_height_gap_port</dimen>
+</resources>
diff --git a/FairphoneHome/res/values-port/styles.xml b/FairphoneHome/res/values-port/styles.xml
new file mode 100644
index 0000000..ab6a1eb
--- /dev/null
+++ b/FairphoneHome/res/values-port/styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 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.
+*/
+-->
+
+<resources>
+<!-- AppsCustomize -->
+    <style name="TabIndicator.AppsCustomize">
+        <item name="android:maxWidth">130dp</item>
+    </style>
+</resources>
diff --git a/FairphoneHome/res/values-pt-rPT/strings.xml b/FairphoneHome/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..d7cedc0
--- /dev/null
+++ b/FairphoneHome/res/values-pt-rPT/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Página Inicial"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Aplicações Principais do Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Escolher imagem de fundo de"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Definir imagem de fundo"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Imagens de fundo"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"A aplicação não está instalada."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Prima sem soltar para escolher um widget."</string>
+    <string name="market" msgid="2652226429823445833">"Loja"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Não foi possível largar o item neste Ecrã Principal."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Escolher um widget para criar"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nome da pasta"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Mudar o nome da pasta"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Cancelar"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Adicionar ao ecrã principal"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplicações"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Atalhos"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Imagens de fundo"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Sem espaço nos Ecrãs principais."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Não existe espaço suficiente neste ecrã principal."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Não existe espaço suficiente na barra personalizável."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Este widget é demasiado grande para a barra inferior."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi criado."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi removido."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" já existe."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Escolher atalho"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Escolher aplicação"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplicações"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Remover"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstalar"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informações da aplicação"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Pesquisar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Pesquisa por Voz"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplicações"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Remover"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Gerir aplicações"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Imagem de fundo"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Pesquisar"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notificações"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Definições do sistema"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ajuda"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Desinstalar a aplicação"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Detalhes da aplicação"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 aplicação selecionada"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget selecionado"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 pasta selecionada"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 atalho selecionado"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalar atalhos"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permite que uma aplicação adicione atalhos sem a intervenção do utilizador."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstalar atalhos"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permite que a aplicação remova atalhos sem intervenção do utilizador."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"ler definições e atalhos do ecrã principal"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permite que a aplicação leia as definições e os atalhos no Ecrã Principal."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"escrever definições e atalhos do ecrã principal"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permite que uma aplicação altere as definições e os atalhos no Ecrã Principal."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Erro ao carregar o widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"É uma aplicação de sistema e não pode ser desinstalada."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Lança-mísseis"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Pasta sem nome"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Ecrã principal %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Página %1$d de %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Ecrã principal %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Página de aplicações %1$d de %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Página de widgets %1$d de %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Sinta-se em casa"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Pode colocar as suas aplicações favoritas aqui."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Para ver todas as aplicações, toque no círculo."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Escolher algumas aplicações"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Para adicionar uma aplicação ao Ecrã principal, toque na mesma sem largar."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organizar as aplicações com pastas"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Para mover uma aplicação, toque na mesma sem largar."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Para criar uma nova pasta no Ecrã principal, empilhe uma aplicação por cima de outra."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Pasta aberta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Toque para fechar a pasta"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Toque para guardar o nome novo"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Pasta fechada"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Nome de pasta alterado para <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-pt/strings.xml b/FairphoneHome/res/values-pt/strings.xml
new file mode 100644
index 0000000..3b60b8b
--- /dev/null
+++ b/FairphoneHome/res/values-pt/strings.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Fairphone OS"</string>
+    <string name="home" msgid="5921706419368316758">"Início"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Principais aplicativos do Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Selecionar plano de fundo de"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Definir plano de fundo"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Papéis de parede"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"O aplicativo não está instalado."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Toque e pressione para selecionar um widget."</string>
+    <string name="market" msgid="2652226429823445833">"Comprar"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Não foi possível soltar este item na tela inicial."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Selecione um widget para criar"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nome da pasta"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Renomear pasta"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Cancelar"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Adicionar à tela inicial"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplicativos"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Atalhos"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Papéis de parede"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Não há mais espaço nas telas iniciais."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Não há mais espaço nesta tela da Página inicial."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Não há mais espaço no hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Este widget é muito grande para o hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Atalho \"<xliff:g id="NAME">%s</xliff:g>\" criado."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi removido."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" já existe."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Escolher atalho"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Selecione um aplicativo"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplicativos"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Remover"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Desinstalar"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informações do aplicativo"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Pesquisar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Pesquisa por voz"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplicativos"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Remover"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Gerenciar aplicativos"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Plano de fundo"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Pesquisa"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notificações"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Configurações do sistema"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ajuda"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Desinstalar aplicativo"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Detalhes do aplicativo"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Um aplicativo selecionado"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Um widget selecionado"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Uma pasta selecionada"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Um atalho selecionado"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalar atalhos"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permite que um aplicativo adicione atalhos sem intervenção do usuário."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstalar atalhos"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permite que o aplicativo remova atalhos sem a intervenção do usuário."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"ler configurações e atalhos da Página inicial"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permite que o aplicativo leia as configurações e os atalhos na Página inicial."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"gravar configurações e atalhos da Página inicial"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permite que o aplicativo altere as configurações e os atalhos na Página inicial."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problema ao carregar o widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Este é um aplicativo do sistema e não pode ser desinstalado."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Pasta sem nome"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Tela inicial %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Página %1$d de %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Tela inicial %1$d de %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Página de aplicativos, %1$d de %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Página de widgets, %1$d de %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Sinta-se em casa"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Você pode colocar seus aplicativos favoritos aqui."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Para ver todos os seus aplicativos, toque no círculo."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Escolha alguns aplicativos"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Para adicionar um aplicativo a sua tela inicial, toque e mantenha-o pressionado."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organize seus aplicativos com pastas"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Para mover um aplicativo, toque e mantenha-o pressionado."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Para criar uma nova pasta em sua tela inicial, coloque um aplicativo em cima do outro."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Pasta aberta, <xliff:g id="WIDTH">%1$d</xliff:g> por <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Toque para fechar a pasta"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Toque para salvar o novo nome"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Pasta fechada"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Pasta renomeada para <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+    
+    <!-- Fairphone -->
+    
+    <!-- Your Apps -->
+    
+    <!-- Fairphone -->
+    <!-- Your Apps -->
+    <string name="your_apps">Your Apps</string>
+    
+    <string name="last_used_apps">Últimas aplicações usadas</string>
+    <string name="last_used">Últimas usadas</string>
+    <string name="most_used_apps">Aplicações\nmais usadas</string>
+    <string name="most_used">Mais usadas</string>
+    <string name="no_apps_have_been_opened_yet">Ainda não abriu aplicações? Basta começar a utilizar o seu telefone e voltar a este ecrã</string>
+    <string name="reset">Limpar</string>
+    <string name="app_switcher_reset_message">Tem a certeza?</string>
+	
+    <!-- Settings -->
+    <string name="energy_mood">Energy Mood no bloqueio de ecrã</string>
+    <string name="energy_mood_summary">Apresenta o nível da bateria como fundo de ecrã</string>
+    
+    <!-- Quick Access -->
+    <string name="quick_access">Quick Access</string>
+    <string name="edit">Editar</string>
+    <string name="favourite_apps">Aplicações favoritas</string>
+    <string name="drag_here_to_add">Arraste até\naqui para\nadicionar</string>
+    <string name="drag_here_to_remove">Arraste até\naqui para\nremover</string>
+    
+    <string name="menu_edit_favorites">Editar favoritos</string>
+    <string name="menu_show_OOBE">Tutorial</string>
+    <string name="menu_change_edge_swipe">Mudar menu</string>
+    <string name="menu_change_edge_swipe_change_to">Mudado para</string>
+	<string name="menu_change_edge_swipe_normal">menu normal</string>
+	<string name="menu_change_edge_swipe_alternative">menu alternativo</string>    
+	
+	
+	
+	<!-- OOBE Texts -->
+	<string name="oobe_quick_access">Quick Access</string>
+	<string name="oobe_select_language">Selecione\no idioma</string>
+	<string name="oobe_setup_wifi">Configurar\nWi-Fi</string>
+	<string name="oobe_intro_top">Bem-vindo. Tem nas suas mãos um telefone que dá prioridade a valores sociais. E sim, também faz chamadas.</string>
+	<string name="oobe_intro_bottom">Vamos mostrar como usá-lo</string>
+	
+	<string name="oobe_edge_swipe_title">Deslize o dedo</string>
+	<string name="oobe_edge_swipe_text">para a esquerda ou direita sem o levantar</string>
+	
+	<string name="oobe_open_app_title">Levante o dedo</string>
+	<string name="oobe_open_app_text">sobre uma aplicação para abrir</string>
+	
+	<string name="oobe_edit_drag_intro">Arraste os ícones das aplicações para editar</string>
+	
+	<string name="oobe_edit_drag_add_title">Arraste para a coluna</string>
+	<string name="oobe_edit_drag_add_text">da direita para acrescentar aos favoritos</string>
+	
+	<string name="oobe_edit_drag_remove_title">Arraste para a coluna</string>
+	<string name="oobe_edit_drag_remove_text">da esquerda para remover dos favoritos</string>
+	
+	<string name="oobe_edit_drag_trade_title">Arraste os favoritos</string>
+	<string name="oobe_edit_drag_trade_text">para trocar de posição</string>
+	
+	<string name="oobe_your_apps_intro">As suas aplicações mais usadas num único sítio</string>
+	<string name="oobe_your_apps_learning">O seu telefone aprende consigo e lembra-se das aplicações mais usadas</string>
+	<string name="oobe_your_apps_last_ones">Também pode consultar as últimas utilizadas</string>
+	<string name="oobe_your_apps_start_using">Comece a utilizar o seu telefone, as aplicações vão estar aqui à sua espera</string>
+	
+	<string name="oobe_start">Iniciar</string>
+	<string name="oobe_back">Anterior</string>
+	<string name="oobe_skip">Saltar</string>
+	<string name="oobe_next">Seguinte</string>
+	<string name="oobe_done">Terminar</string>
+	
+	<!-- Google Apps Install Widget -->
+    <string name="google_apps_installer_name">Instalador Google Apps</string>
+	<string name="google_apps_initial_title">Instalar\nGoogle Apps</string>
+	<string name="google_apps_disclaimer_title">Instalar Google Apps</string>
+	<string name="google_apps_disclaimer_description">Para ter acesso à experiência Android e Google completa como a Google Play Store, o seu telefone precisa de conteúdo e software adicional. Infelizmente, como a Fairphone ainda não tem a licença necessária, não podemos pré-instalar este conteúdo, nem o podemos providenciar directamente. Estamos a trabalhar com o proprietário dos conteúdos para alterar isto.\nEscolha “Concordo” de seguida para descarregar o conteúdo de uma fonte externa segura. A instalação deste conteúdo é da sua responsabilidade.\nSe não concordar, o seu telefone continua a trabalhar com aplicações de Android básicas, mas irá perder alguns serviços Google.</string>
+	<string name="google_apps_disclaimer_agree">Concordo</string>
+	<string name="google_apps_denied_permissions_title">Permissões negadas</string>
+	<string name="google_apps_denied_permissions_description">Fairphone OS não conseguiu obter as permissões para instalar o Google Apps. Se escolheu NEGAR, reinicie o instalador e seleccione PERMITIR.</string>
+	<string name="google_apps_reboot_failed_title">Falha ao reiniciar</string>
+	<string name="google_apps_reboot_failed_description">O Google Apps está instalado. Falha ao reiniciar, por favor reinicie manualmente.</string>
+	<string name="google_apps_download_title">A descarregar Google Apps</string>
+	<string name="google_apps_unzip_title">A extrair Google Apps</string>
+	<string name="google_apps_install_title">A instalar Google Apps</string>
+	<string name="google_apps_reboot_title">A reiniciar dispositivo</string>
+	<string name="google_apps_permissions_description">Fairphone OS vai pedir-lhe a permissão Superuser. Garantimos que esta operação é completamente segura. Por favor escolha PERMITIR ao ser questionado.</string>
+	<string name="google_apps_permissions_title">Permissões de sistema</string>
+	<string name="google_apps_reboot_description">O sistema precisa de reiniciar para completar a instalação.\n\nDepois da instalação, siga os passos para configurar o Google Apps.</string>
+	<string name="google_apps_uninstall_title">Google Apps instalado</string>
+	<string name="google_apps_uninstall_description">Apagar\neste instalador</string>
+	<string name="google_apps_failed_download_title">Falha ao descarregar</string>
+	<string name="google_apps_failed_download_description">Os ficheiros descarregados estão corrompidos. Tentar outra vez?</string>
+	<string name="google_apps_download_error">Erro ao descarregar os ficheiros. Por favor tente outra vez.</string>
+	<string name="google_apps_connection_title">Wi-Fi desligado</string>
+	<string name="google_apps_connection_description">O ficheiro que está a tentar descarregar é muito grande para ligações móveis (~100mb). Por favor ligue-se ao Wi-Fi e tente outra vez.</string>
+	
+</resources>
diff --git a/FairphoneHome/res/values-pt/styles.xml b/FairphoneHome/res/values-pt/styles.xml
new file mode 100644
index 0000000..a43afb5
--- /dev/null
+++ b/FairphoneHome/res/values-pt/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="SubTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">11.3sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-4dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEDescriptionText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">13sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values-rm/strings.xml b/FairphoneHome/res/values-rm/strings.xml
new file mode 100644
index 0000000..99f72bb
--- /dev/null
+++ b/FairphoneHome/res/values-rm/strings.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Lantschader"</string>
+    <!-- no translation found for home (5921706419368316758) -->
+    <skip />
+    <string name="uid_name" msgid="3371120195364560632">"Applicaziuns da basa dad Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <!-- no translation found for chooser_wallpaper (6063168087625352235) -->
+    <skip />
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Definir in fund davos"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Maletgs da fund davos"</string>
+    <!-- no translation found for activity_not_found (217823393239365967) -->
+    <skip />
+    <!-- no translation found for widgets_tab_label (9145860100000983599) -->
+    <skip />
+    <!-- no translation found for long_press_widget_to_add (7395697462851217506) -->
+    <skip />
+    <!-- no translation found for market (2652226429823445833) -->
+    <skip />
+    <!-- no translation found for external_drop_widget_error (2285187188524172774) -->
+    <skip />
+    <!-- no translation found for external_drop_widget_pick_title (7040647073452295370) -->
+    <skip />
+    <string name="rename_folder_label" msgid="5646236631298452787">"Num da l\'ordinatur"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Renumnar l\'ordinatur"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Interrumper"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Agiuntar al visur da partenza"</string>
+    <!-- no translation found for group_applications (2103752818818161976) -->
+    <skip />
+    <string name="group_shortcuts" msgid="9133529424900391877">"Scursanidas"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgets"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Funds davos"</string>
+    <!-- no translation found for completely_out_of_space (1759078539443491182) -->
+    <skip />
+    <string name="out_of_space" msgid="8365249326091984698">"Nagin spazi liber sin il visur da partenza."</string>
+    <!-- no translation found for hotseat_out_of_space (6304886797358479361) -->
+    <skip />
+    <!-- no translation found for invalid_hotseat_item (6545340627805449250) -->
+    <skip />
+    <string name="shortcut_installed" msgid="7071557296331322355">"\"Creà ina scursanida \"\"<xliff:g id="NAME">%s</xliff:g>\"\".\""</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"\"La scursanida \"\"<xliff:g id="NAME">%s</xliff:g>\"\" è vegnida stizzada.\""</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"\"La scursanida \"\"<xliff:g id="NAME">%s</xliff:g>\"\" exista gia.\""</string>
+    <!-- no translation found for title_select_shortcut (1873670208166882222) -->
+    <skip />
+    <!-- no translation found for title_select_application (1793455815754848652) -->
+    <skip />
+    <!-- no translation found for all_apps_button_label (2578400570124163469) -->
+    <skip />
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Pagina da partenza"</string>
+    <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
+    <skip />
+    <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
+    <skip />
+    <!-- no translation found for delete_target_label (665300185123139530) -->
+    <skip />
+    <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+    <skip />
+    <!-- no translation found for info_target_label (4019495079517426980) -->
+    <skip />
+    <!-- no translation found for accessibility_search_button (816822994629942611) -->
+    <skip />
+    <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+    <skip />
+    <!-- no translation found for accessibility_all_apps_button (8803738611398979849) -->
+    <skip />
+    <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+    <skip />
+    <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+    <skip />
+    <string name="menu_add" msgid="3065046628354640854">"Agiuntar"</string>
+    <!-- no translation found for menu_manage_apps (2308685199463588895) -->
+    <skip />
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Fund davos"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Tschertgar"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Avis"</string>
+    <!-- no translation found for menu_settings (3946232973327980394) -->
+    <skip />
+    <!-- no translation found for menu_help (4901160661634590633) -->
+    <skip />
+    <!-- no translation found for cab_menu_delete_app (4089398025537640349) -->
+    <skip />
+    <!-- no translation found for cab_menu_app_info (914548323652698884) -->
+    <skip />
+    <!-- no translation found for cab_app_selection_text (6378522164293415735) -->
+    <skip />
+    <!-- no translation found for cab_widget_selection_text (962527270506951955) -->
+    <skip />
+    <!-- no translation found for cab_folder_selection_text (8916111874189565067) -->
+    <skip />
+    <!-- no translation found for cab_shortcut_selection_text (8115847384500412878) -->
+    <skip />
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"Installar scursanidas"</string>
+    <!-- no translation found for permdesc_install_shortcut (8634424803272077038) -->
+    <skip />
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"deinstallar scursanidas"</string>
+    <!-- no translation found for permdesc_uninstall_shortcut (274355570620220977) -->
+    <skip />
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Leger ils parameters e las scursanidas da la pagina da partenza"</string>
+    <!-- no translation found for permdesc_read_settings (5788109303585403679) -->
+    <skip />
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Definir ils parameters e las scursanidas per la pagina da partenza"</string>
+    <!-- no translation found for permdesc_write_settings (8530105489115785531) -->
+    <skip />
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problems cun chargiar il widget"</string>
+    <!-- no translation found for uninstall_system_app_text (6429814133777046491) -->
+    <skip />
+    <!-- no translation found for dream_name (2847171357608437154) -->
+    <skip />
+    <!-- no translation found for folder_hint_text (8633351560105748141) -->
+    <skip />
+    <!-- no translation found for workspace_description_format (2968608205939373034) -->
+    <skip />
+    <!-- no translation found for default_scroll_format (4057140866420001240) -->
+    <skip />
+    <!-- no translation found for workspace_scroll_format (1704767047951143301) -->
+    <skip />
+    <!-- no translation found for apps_customize_apps_scroll_format (5494241912377704885) -->
+    <skip />
+    <!-- no translation found for apps_customize_widgets_scroll_format (5383009742241717437) -->
+    <skip />
+    <!-- no translation found for workspace_cling_title (738396473989890567) -->
+    <skip />
+    <!-- no translation found for workspace_cling_move_item (791013895761065070) -->
+    <skip />
+    <!-- no translation found for workspace_cling_open_all_apps (2459977609848572588) -->
+    <skip />
+    <!-- no translation found for all_apps_cling_title (2559734712581447107) -->
+    <skip />
+    <!-- no translation found for all_apps_cling_add_item (5665035103260318891) -->
+    <skip />
+    <!-- no translation found for folder_cling_title (4308949882377840953) -->
+    <skip />
+    <!-- no translation found for folder_cling_move_item (270598675060435169) -->
+    <skip />
+    <!-- no translation found for folder_cling_create_folder (8352867485656129478) -->
+    <skip />
+    <!-- no translation found for cling_dismiss (2780907108735868381) -->
+    <skip />
+    <!-- no translation found for folder_opened (1262064100943801533) -->
+    <skip />
+    <!-- no translation found for folder_tap_to_close (1335478160661137579) -->
+    <skip />
+    <!-- no translation found for folder_tap_to_rename (5201612989905472442) -->
+    <skip />
+    <!-- no translation found for folder_closed (3130534551370511932) -->
+    <skip />
+    <!-- no translation found for folder_renamed (7951233572858053642) -->
+    <skip />
+    <!-- no translation found for folder_name_format (3051680259794759037) -->
+    <skip />
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ro/strings.xml b/FairphoneHome/res/values-ro/strings.xml
new file mode 100644
index 0000000..1ed96ac
--- /dev/null
+++ b/FairphoneHome/res/values-ro/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Lansator"</string>
+    <string name="home" msgid="5921706419368316758">"Ecran de pornire"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Alegeţi imaginea de fundal din"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Setaţi imaginea de fundal"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Imagini de fundal"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Aplicaţia nu este instalată."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Obiecte widget"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Atingeţi/menţineţi apăsat un widget pt. a-l alege."</string>
+    <string name="market" msgid="2652226429823445833">"Cumpăraţi"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Nu am putut plasa articolul pe ecranul de pornire."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Alegeţi widgetul de creare"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Nume dosar"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Redenumiţi dosarul"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Anulaţi"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Adăugaţi la Ecranul de pornire"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplicaţii"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Comenzi rapide"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Obiecte widget"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Imagini de fundal"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Nu mai este loc pe ecranele de pornire."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Niciun spaţiu rămas pe acest Ecran de pornire."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Nu mai există loc în bara de lansare rapidă."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Acest widget este prea mare pentru hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>”·a fost creată."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>” a fost eliminată."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Comanda rapidă „<xliff:g id="NAME">%s</xliff:g>” deja există."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Alegeţi o comandă rapidă"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Alegeţi aplicaţia"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplicaţii"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Domiciliu"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminaţi"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Dezinstalaţi"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Eliminaţi"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Dezinstalaţi"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informaţii aplicaţie"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Căutaţi"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Căutare vocală"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplicaţii"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminaţi"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Dezinstalaţi actualizarea"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Adăugaţi"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Gestionaţi aplicaţii"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Imagine de fundal"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Căutaţi"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Notificări"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Setări de sistem"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Ajutor"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Dezinstalaţi aplicaţia"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Detalii aplicaţie"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 aplicaţie selectată"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 obiect widget selectat"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 dosar selectat"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 comandă rapidă selectată"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalaţi comenzi rapide"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Permite unei aplicaţii să adauge comenzi rapide, fără intervenţia utilizatorului."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"dezinstalaţi comenzile rapide"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Permite aplicaţiei să elimine comenzile rapide, fără intervenţia utilizatorului."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"citiţi setările Paginii de pornire şi comenzile rapide"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Permite aplicaţiei să citească setările şi comenzile rapide din ecranul de pornire."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"scrieţi setări şi comenzi rapide pentru Ecranul de pornire"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Permite aplicaţiei să modifice setările şi comenzile rapide din ecranul de pornire."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Probleme la încărcarea obiectului widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Aceasta este o aplicaţie de sistem şi nu poate fi dezinstalată."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Dosar fără nume"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Ecran de pornire %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Pagina %1$d din %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Ecranul de pornire %1$d din %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Pagina de aplicaţii %1$d din %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Pagina de widgeturi %1$d din %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Simţiţi-vă ca acasă"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Puteţi plasa aici aplicaţiile preferate."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Pentru a vedea toate aplicaţiile, atingeţi cercul."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Alegeţi unele aplicaţii"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Atingeţi o aplicaţie şi menţineţi-o apăsată pentru a o adăuga pe ecranul de pornire."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organizaţi aplicaţiile în dosare"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Pentru a muta o aplicaţie, atingeţi şi ţineţi apăsat."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Pentru a crea un dosar nou pe ecranul de pornire, plasaţi o aplicaţie deasupra alteia."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Dosar deschis, <xliff:g id="WIDTH">%1$d</xliff:g> pe <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Atingeţi pentru a închide dosarul"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Atingeţi pentru a salva redenumirea"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Dosar închis"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Dosar redenumit <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-ru/strings.xml b/FairphoneHome/res/values-ru/strings.xml
new file mode 100644
index 0000000..c2b88d5
--- /dev/null
+++ b/FairphoneHome/res/values-ru/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Главный экран"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Основные приложения"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Установка обоев"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Установить обои"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Обои"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Приложение удалено."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Виджеты"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Чтобы выбрать виджет, нажмите на значок и удерживайте его."</string>
+    <string name="market" msgid="2652226429823445833">"Маркет"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Не удалось добавить элемент на главный экран."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Выберите виджет"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Название папки"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Переименовать папку"</string>
+    <string name="rename_action" msgid="6016003384693240896">"ОК"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Отмена"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Добавить на главный экран"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Приложения"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Ярлыки"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Виджеты"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Обои"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"На главных экранах всё занято."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"На этом экране всё занято."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Нет свободного места в слоте."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Виджет слишком велик для слота."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" создан"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" удален."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" уже существует."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Выбор ярлыка"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Выберите приложение"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Приложения"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Главная"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Удалить"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Удалить"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Удалить"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Удалить"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Сведения о приложении"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Поиск"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Голосовой поиск"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Приложения"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Удалить"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Удалить обновление"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Добавить"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Приложения"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Обои"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Поиск"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Уведомления"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Настройки"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Справка"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Удалить"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"О приложении"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Выбрано 1 приложение"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Выбран 1 виджет"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Выбрана 1 папка"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Выбран 1 ярлык"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"Установка ярлыков"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Приложение сможет самостоятельно добавлять ярлыки."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"удалять ярлыки"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Приложение сможет самостоятельно удалять ярлыки."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Просмотр настроек и ярлыков главного экрана"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Приложение получит доступ к данным о настройках и ярлыках на главном экране."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Изменение настроек и ярлыков главного экрана"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Приложение сможет изменять настройки и ярлыки на главном экране."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Не удалось загрузить виджет"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Это системное приложение, его нельзя удалить."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Фейерверк"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Без названия"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Главный экран %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Стр. %1$d из %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Главные экран %1$d из %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Приложения: стр. %1$d из %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Виджеты: стр. %1$d из %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Будьте как дома"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Добавляйте сюда любимые приложения."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Чтобы открыть список приложений, нажмите на круг."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Выберите приложения"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Чтобы добавить приложение на главный экран, нажмите на значок и удерживайте его."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Разложите все по папкам"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Чтобы переместить значок приложения, нажмите на него и удерживайте."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Чтобы создать папку на главном экране, перенесите одно приложение на другое."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"ОК"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Папка открыта, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Нажмите, чтобы закрыть папку"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Нажмите, чтобы подтвердить переименование"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Папка закрыта"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Папка переименована в \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-sk/strings.xml b/FairphoneHome/res/values-sk/strings.xml
new file mode 100644
index 0000000..43c4c16
--- /dev/null
+++ b/FairphoneHome/res/values-sk/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Spúšťač"</string>
+    <string name="home" msgid="5921706419368316758">"Plocha"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Vybrať tapetu z"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Nastaviť tapetu"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Tapety"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Aplikácia nie je nainštalovaná."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Miniaplikácie"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Miniaplikáciu pridáte stlačením a podržaním."</string>
+    <string name="market" msgid="2652226429823445833">"Obchod"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Položku sa nepodarilo presunúť na túto plochu."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Zvoľte miniaplikáciu na vytvorenie"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Názov priečinka"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Premenovať priečinok"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Zrušiť"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Pridať na plochu"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Aplikácie"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Odkazy"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Miniaplikácie"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Tapety"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Na plochách už nie je miesto."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Na tejto ploche už nie je miesto"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"V časti hotseat už nie je miesto."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Táto miniaplikácia je pre hotseat príliš veľká."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Odkaz <xliff:g id="NAME">%s</xliff:g> bol vytvorený."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Odkaz <xliff:g id="NAME">%s</xliff:g> bol odstránený."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Odkaz <xliff:g id="NAME">%s</xliff:g> už existuje."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Vyberte odkaz"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Vyberte aplikáciu"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Aplikácie"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Domovská stránka"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrániť"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinštalovať"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Odstrániť"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Odinštalovať"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Informácie o aplikácii"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Hľadať"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hlasové vyhľadávanie"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Aplikácie"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Odstrániť"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinštalovať aktualizáciu"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Pridať"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Spravovať aplikácie"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Hľadať"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Upozornenia"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Nastavenia systému"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Pomocník"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Odinštalovať aplikáciu"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Podrobnosti o aplikácii"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Vybratá 1 aplikácia"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Vybratá 1 miniaplikácia"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Vybratý 1 priečinok"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Vybratý 1 odkaz"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"inštalovať odkazy"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Povoľuje aplikácii pridať odkazy bez zásahu používateľa."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"odinštalovať odkazy"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Povoľuje aplikácii odstrániť odkazy bez zásahu používateľa."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"čítanie nastavení a odkazov plochy"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Povoľuje aplikácii čítať nastavenia a odkazy na ploche."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"zápis nastavení a odkazov plochy"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Povoľuje aplikácii zmeniť nastavenia a odkazy na ploche."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problém s načítaním miniaplikácií"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Toto je systémová aplikácia a nedá sa odinštalovať."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Raketomet"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Nepomenovaný priečinok"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Plocha %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Stránka %1$d z %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Plocha %1$d z %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Stránka aplikácií %1$d z %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Stránka miniaplikácií %1$d z %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Cíťte sa ako doma"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Tu môžete umiestniť svoje obľúbené aplikácie."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Ak chcete zobraziť všetky aplikácie, dotknite sa kruhu."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Vyberte niektoré aplikácie"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Ak chcete pridať aplikáciu na plochu, dotknite sa jej a podržte ju."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Usporiadajte aplikácie v priečinkoch"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Ak chcete presunúť aplikáciu, dotknite sa jej a podržte ju."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Ak chcete vytvoriť nový priečinok na ploche, presuňte jednu aplikáciu na inú."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Otvorený priečinok, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Dotykom zavriete priečinok"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Dotykom premenovanie uložíte"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Priečinok je uzavretý"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Priečinok bol premenovaný na <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-sl/strings.xml b/FairphoneHome/res/values-sl/strings.xml
new file mode 100644
index 0000000..3217c0a
--- /dev/null
+++ b/FairphoneHome/res/values-sl/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Zaganjalnik"</string>
+    <string name="home" msgid="5921706419368316758">"Začetna stran"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Izberite sliko za ozadje"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Nastavi sliko za ozadje"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Slike za ozadje"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Program ni nameščen."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Pripomočki"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Za izbiro pripomočka se ga dotaknite in pridržite."</string>
+    <string name="market" msgid="2652226429823445833">"Nakup"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Elemen. ni bilo mogoče spustiti na začetni zaslon."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Izberite pripomoček za ustvarjanje"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Ime mape"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Preimenuj mapo"</string>
+    <string name="rename_action" msgid="6016003384693240896">"V redu"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Prekliči"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Dodaj na začetni zaslon"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Programi"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Bližnjice"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Pripomočki"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Slike za ozadje"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Na začetnih zaslonih ni več prostora."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Na tem začetnem zaslonu ni več prostora."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"V vrstici z ikonami ni več prostora."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Ta pripomoček je prevelik za podnožje."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« je bila ustvarjena."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« je bila odstranjena."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Bližnjica »<xliff:g id="NAME">%s</xliff:g>« že obstaja."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Izbira bližnjice"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Izberite program"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Programi"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Začetni zaslon"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrani"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odstrani"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Izbriši"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Odstrani"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Podatki o programu"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Išči"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Glasovno iskanje"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Programi"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Odstrani"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odstrani posodobitev"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj programe"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Slika za ozadje"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Iskanje"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Obvestila"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Sistemske nastavitve"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Pomoč"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Odstrani program"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Podrobnosti programa"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Izbran je 1 program"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Izbran je 1 pripomoček"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Izbrana je 1 mapa"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Izbrana je 1 bližnjica"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"namesti bližnjice"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Programu omogoča dodajanje bližnjic brez posredovanja uporabnika."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"odstrani bližnjice"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Programu omogoča odstranjevanje bližnjic brez posredovanja uporabnika."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"branje nastavitev in bližnjic začetnega zaslona"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Dovoli programu branje nastavitev in bližnjic na začetnem zaslonu."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"zapis nastavitev in bližnjic začetnega zaslona"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Dovoli programu spreminjanje nastavitev in bližnjic na začetnem zaslonu."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Težave pri nalaganju pripomočka"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"To je sistemski program in ga ni mogoče odstraniti."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Raketno izstrelišče"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Neimenovana mapa"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Začetni zaslon %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Stran %1$d od %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Začetni zaslon %1$d od %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Stran programov %1$d od %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Stran pripomočkov %1$d od %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Počutite se kot doma"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Sem lahko daste priljubljene programe."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Če si želite ogledati vse programe, se dotaknite kroga."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Izberite nekaj programov"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Če želite dodati program na začetni zaslon, se ga dotaknite in ga pridržite."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Organizirajte svoje programe z mapami"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Če želite premakniti program, se ga dotaknite in ga pridržite."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Če želite na začetnem zaslonu ustvariti novo mapo, postavite en program na drugega."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"V redu"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Mapa je odprta, <xliff:g id="WIDTH">%1$d</xliff:g> krat <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Dotaknite se, da zaprete mapo"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Dotaknite se, da shranite preimenovanje"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mapa je zaprta"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mapa je preimenovana v <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-sr/strings.xml b/FairphoneHome/res/values-sr/strings.xml
new file mode 100644
index 0000000..7e49aef
--- /dev/null
+++ b/FairphoneHome/res/values-sr/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Покретач"</string>
+    <string name="home" msgid="5921706419368316758">"Почетна"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Основне Android апликације"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Избор позадине из"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Подеси позадину"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Позадине"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Апликација није инсталирана."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Виџети"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Додирните и задржите да бисте узели виџет."</string>
+    <string name="market" msgid="2652226429823445833">"Куповина"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Није могуће отпустити ставку на почетни екран."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Избор виџета за прављење"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Име директоријума"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Преименовање директоријума"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Потврди"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Откажи"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Додавање на почетни екран"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Апликације"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Пречице"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Виџети"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Позадине"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Нема више простора на Почетним екранима."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Нема више простора на овом почетном екрану."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Нема више простора на траци актуелности."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Овај виџет је превелики за траку актуелности."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ је направљена."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ је уклоњена."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Пречица „<xliff:g id="NAME">%s</xliff:g>“ већ постоји."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Избор пречице"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Избор апликације"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Почетна"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Уклони"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталирај"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Уклони"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Деинсталирај"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Информације о апликацији"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Претражи"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Гласовна претрага"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Апликације"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Уклони"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинсталирај ажурирања"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Додај"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Управљање апликацијама"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Позадина"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Претражи"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Обавештења"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Системска подешавања"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Помоћ"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Деинсталирај апликацију"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Детаљи о апликацији"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Изабрана је 1 апликација"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Изабран је 1 виџет"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Изабран је 1 директоријум"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Изабрана је 1 пречица"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"инсталирај пречице"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Дозвољава апликацији да додаје пречице без интервенције корисника."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"деинсталирај пречице"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Дозвољава апликацији да уклања пречице без интервенције корисника."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"читај подешавања и пречице на почетном екрану"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Дозвољава апликацији да чита подешавања и пречице на почетном екрану."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"уписивање подешавања и пречица на почетном екрану"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Дозвољава апликацији да мења подешавања и пречице на почетном екрану."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Проблем приликом учитавања виџета"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Ово је системска апликација и не може да се деинсталира."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Неименовани директоријум"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Почетни екран %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Страница %1$d. од %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Почетни екран %1$d од %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Страница апликације %1$d. од %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Страница видџета %1$d. од %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Осећајте се као код куће"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Овде можете да ставите омиљене апликације."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Да бисте видели све апликације, додирните круг."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Избор апликација"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Да бисте додали апликацију на почетни екран, додирните је и задржите."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Организација апликација помоћу директоријума"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Да бисте преместили апликацију, додирните је и задржите."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Да бисте направили нови директоријум на почетном екрану, поређајте апликације једну на другу."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Потврди"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Директоријум је отворен, <xliff:g id="WIDTH">%1$d</xliff:g> пута <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Додирните да бисте затворили директоријум"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Додирните да бисте сачували промену имена"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Директоријум је затворен"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Директоријум је преименован у <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Директоријум: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-sv/strings.xml b/FairphoneHome/res/values-sv/strings.xml
new file mode 100644
index 0000000..067b5f1
--- /dev/null
+++ b/FairphoneHome/res/values-sv/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Startbild"</string>
+    <string name="home" msgid="5921706419368316758">"Startsida"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Välj bakgrund från"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Ange bakgrund"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Bakgrundsbilder"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Appen är inte installerad."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widgetar"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Tryck länge om du vill flytta en widget."</string>
+    <string name="market" msgid="2652226429823445833">"Butik"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Objektet kunde inte släppas på den här startsidan."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Ange vilken widget du vill använda"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Mappnamn"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Byt namn på mapp"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Avbryt"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Lägg till på startsidan"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Appar"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Genvägar"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widgetar"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Bakgrundsbilder"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Det finns inte plats för mer på dina startskärmar."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Det finns inte plats för mer på den här startsidan."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Utrymmet på Hotseat är fullt."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Denna widget är för stor för Hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" har skapats."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" har tagits bort."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" finns redan."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Välj genväg"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Välj app"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Appar"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsida"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ta bort"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstallera"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Ta bort"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Avinstallera"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Info om appen"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Sök"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Röstsökning"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Appar"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Ta bort"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstallera uppdatering"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Lägg till"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Hantera appar"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Bakgrund"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Sök"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Aviseringar"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Systeminställningar"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Hjälp"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Avinstallera appen"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Information om appen"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 app har valts"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget vald"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mapp vald"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 genväg har valts"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"installera genvägar"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Tillåter att en app lägger till genvägar utan åtgärd från användaren."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"avinstallera genvägar"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Tillåter att appen tar bort genvägar utan åtgärd från användaren."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"läsa inställningar och genvägar för startsidan"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Tillåter att appen läser inställningar och genvägar på startsidan."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"skriva inställningar och genvägar för startsidan"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Tillåter att appen ändrar inställningar och genvägar på startsidan."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Det gick inte att läsa in widgeten"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Det här är en systemapp som inte kan  avinstalleras."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Raketavfyringsramp"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Namnlös mapp"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Startskärmen %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Sidan %1$d av %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Startskärmen %1$d av %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Appsida %1$d av %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widget-sida %1$d av %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Känn dig som hemma"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Du kan placera dina favoritappar här."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Om du vill visa alla dina appar trycker du på cirkeln."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Välj några appar"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Om du vill lägga till en app på startskärmen trycker du länge på den."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Ordna dina appar i mappar"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Om du vill flytta en app trycker du på den länge."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Om du vill skapa en ny mapp på startskärmen placerar du en app på en annan."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Mappen är öppen, <xliff:g id="WIDTH">%1$d</xliff:g> gånger <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Tryck om du vill stänga mappen"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Tryck om du vill spara det nya namnet"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Mappen är stängd"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Mappen har bytt namn till <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-sw/strings.xml b/FairphoneHome/res/values-sw/strings.xml
new file mode 100644
index 0000000..c09d328
--- /dev/null
+++ b/FairphoneHome/res/values-sw/strings.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Kizinduzi"</string>
+    <string name="home" msgid="5921706419368316758">"Nyumbani"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Programu Kuu za Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Chagua mandhari kutoka"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Weka mandhari"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Mandhari"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Programu haijasakinishwa."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Wijeti"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Gusa &amp; ushikilie ili kuteua wijeti."</string>
+    <string name="market" msgid="2652226429823445833">"Duka"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Haikuweza kudondosha kipengee kwenye skrini hii ya Nyumbani."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Chagua wijeti ili uunde"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Jina la folda"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Ipe jina jipya folda"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Sawa"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Ghairi"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Ongeza kwa skrini ya Nyumbani"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Programu"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Njia za mkato"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Wijeti"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Mandhari"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Hakuna nafasi zaidi kwenye skrini zako za Nyumbani."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Hakuna nafasi katika skrini hii ya nyumbani."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Hakuna nafasi zaidi kwenye eneo kali."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Wijeti hii ni kubwa zaidi kwa hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" imeundwa."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" iliondolewa."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" tayari ipo."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Chagua njia ya mkato"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Chagua programu"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Programu"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Nyumbani"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ondoa"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Ondoa"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Ondoa"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Ondoa"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Maelezo ya programu"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Tafuta"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Utafutaji wa Sauti"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Programu"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Ondoa"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Sanidua sasisho"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Ongeza"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Dhibiti programu"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Mandhari"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Tafuta"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Arifa"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Mipangilio ya mfumo"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Usaidizi"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Sanidua programu"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Maelezo ya programu"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Programu 1 imechaguliwa"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Wijeti 1 imechaguliwa"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Folda 1 limechaguliwa"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">" Njia 1 ya mkato imechaguliwa"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"njia mikato za moja kwa moja"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Huruhusu programu kuongeza njia za mkato bila mtumiaji kuhusika."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"Sakunua mikato"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Inaruhusu programu kuondoa njia za mikato bila juhudi za mtumiaji."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"soma mipangilio ya Nyumbani na njia za mkato"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Inaruhusu programu kusoma mipangilio na njia za mikato katika Nyumbani."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"andika mipangilio ya Nyumbani na njia za mkato"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Huruhusu programu kubadilisha mipangilio na njia za mkato katika Nyumbani."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Tatizo la kupakia wijeti"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Hii ni programu ya mfumo na haiwezi kusaniduliwa."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Kizinduzi cha Roketi"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Folda isiyo na jina"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Skrini ya nyumbani %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Ukurasa%1$d wa %2$d"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for workspace_scroll_format (1704767047951143301) -->
+    <skip />
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Ukurasa wa programu %1$d ya %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Ukurasa wa wijeti %1$d ya %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Jisikie huru"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Unaweza kuweka programu zako uzipendazo hapa."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Kutazama programu zako zote, gusa duara."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Chagua programu kadhaa"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Ili kuongeza programu kwa skrini yako ya Nyumbani, iguse na uishikilie."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Panga programu zako na folda"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Kuhamisha programu, gusa na; uishikilie."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Kuunda folda mpya katika skrini yako ya nyumbani, rundika programu moja juu ya nyingine."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Sawa"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Folda imefunguliwa, <xliff:g id="WIDTH">%1$d</xliff:g> kwa <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Gusa ili ufunge folda"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Gusa kuhifadhi upaji jina jipya"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Folda imefungwa"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Folda imebadilishwa jina hadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Folda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-sw340dp-port/config.xml b/FairphoneHome/res/values-sw340dp-port/config.xml
new file mode 100644
index 0000000..d31ee59
--- /dev/null
+++ b/FairphoneHome/res/values-sw340dp-port/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<resources>
+<!-- Workspace -->
+    <!-- Whether or not to fade the side pages -->
+    <bool name="config_workspaceFadeAdjacentScreens">false</bool>
+</resources>
diff --git a/FairphoneHome/res/values-sw340dp-port/dimens.xml b/FairphoneHome/res/values-sw340dp-port/dimens.xml
new file mode 100644
index 0000000..fac8e0e
--- /dev/null
+++ b/FairphoneHome/res/values-sw340dp-port/dimens.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<resources>
+<!-- Clings -->
+    <dimen name="folderClingMarginTop">70dp</dimen>
+
+<!-- Workspace -->
+    <dimen name="workspace_divider_padding_left">6dp</dimen>
+    <dimen name="workspace_divider_padding_right">6dp</dimen>
+
+    <!-- qsb_bar_height_inset represents qsb_bar_height minus the padding
+         that we put on each page for allowing folders to draw out of bounds -->
+    <!-- FPNOTE : This is changed for  -->
+    <dimen name="qsb_bar_height_inset">48dp</dimen>
+    <dimen name="qsb_bar_height">54dp</dimen>
+    <dimen name="qsb_padding_left">6dp</dimen>
+    <dimen name="qsb_padding_right">6dp</dimen>
+    <dimen name="search_bar_height">48dp</dimen>
+
+<!-- AppsCustomize -->
+    <dimen name="apps_customize_pageLayoutPaddingTop">16dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingBottom">20dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingLeft">8dp</dimen>
+    <dimen name="apps_customize_pageLayoutPaddingRight">8dp</dimen>
+    <dimen name="apps_customize_cell_height">92dp</dimen>
+    <dimen name="apps_customize_widget_cell_height_gap">16dp</dimen>
+</resources>
diff --git a/FairphoneHome/res/values-sw340dp-port/styles.xml b/FairphoneHome/res/values-sw340dp-port/styles.xml
new file mode 100644
index 0000000..b309d85
--- /dev/null
+++ b/FairphoneHome/res/values-sw340dp-port/styles.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 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.
+*/
+-->
+
+<resources>
+<!-- Workspace -->
+    <style name="SearchButton">
+        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+    </style>
+
+<!-- AppsCustomize -->
+    <style name="TabIndicator.AppsCustomize">
+        <item name="android:maxWidth">150dp</item>
+    </style>
+    <style name="WorkspaceIcon.Portrait.AppsCustomize">
+        <item name="android:singleLine">false</item>
+        <item name="android:maxLines">2</item>
+        <item name="android:background">@null</item>
+        <item name="android:paddingTop">4dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:paddingLeft">0dp</item>
+        <item name="android:paddingRight">0dp</item>
+        <item name="android:drawablePadding">6dp</item>
+    </style>
+</resources>
diff --git a/FairphoneHome/res/values-sw340dp/dimens.xml b/FairphoneHome/res/values-sw340dp/dimens.xml
new file mode 100644
index 0000000..93de009
--- /dev/null
+++ b/FairphoneHome/res/values-sw340dp/dimens.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<resources>
+    <!-- Drag padding to add to the bottom of drop targets -->
+    <dimen name="drop_target_drag_padding">20dp</dimen>
+
+<!-- Hotseat -->
+    <dimen name="hotseat_width_gap">0dp</dimen>
+    <dimen name="hotseat_height_gap">0dp</dimen>
+    <!-- height of the bottom row of controls -->
+    <dimen name="button_bar_height">80dip</dimen>
+    <!-- Because portal animations go beyond the bounds of an icon, we need
+         to make the dock layout slightly larger than the button_bar_height -->
+    <dimen name="button_bar_height_bottom_padding">8dp</dimen>
+    <dimen name="button_bar_width_left_padding">8dp</dimen>
+    <dimen name="button_bar_width_right_padding">8dp</dimen>
+    <dimen name="button_bar_height_plus_padding">80dp</dimen>
+
+<!-- CellLayout padding land / port-->
+    <dimen name="cell_layout_left_padding_port">8dp</dimen>
+    <dimen name="cell_layout_left_padding_land">8dp</dimen>
+    <dimen name="cell_layout_right_padding_port">8dp</dimen>
+    <dimen name="cell_layout_right_padding_land">8dp</dimen>
+    <dimen name="cell_layout_top_padding_port">8dp</dimen>
+    <dimen name="cell_layout_top_padding_land">8dp</dimen>
+    <dimen name="cell_layout_bottom_padding_port">8dp</dimen>
+    <dimen name="cell_layout_bottom_padding_land">8dp</dimen>
+</resources>
diff --git a/FairphoneHome/res/values-sw380dp-port/dimens.xml b/FairphoneHome/res/values-sw380dp-port/dimens.xml
new file mode 100644
index 0000000..eef6eb2
--- /dev/null
+++ b/FairphoneHome/res/values-sw380dp-port/dimens.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<resources>
+<!-- Workspace -->
+    <!-- qsb_bar_height_inset represents qsb_bar_height minus the padding
+         that we put on each page for allowing folders to draw out of bounds -->
+    <dimen name="qsb_bar_height_inset">48dp</dimen>
+    <dimen name="qsb_bar_height">56dp</dimen>
+    <dimen name="qsb_padding_left">8dp</dimen>
+    <dimen name="qsb_padding_right">8dp</dimen>
+    <dimen name="search_bar_height">48dp</dimen>
+
+    <dimen name="workspace_divider_padding_left">8dp</dimen>
+    <dimen name="workspace_divider_padding_right">8dp</dimen>
+    <dimen name="workspace_width_gap_land">0dp</dimen>
+    <dimen name="workspace_width_gap_port">8dp</dimen>
+    <dimen name="workspace_height_gap_land">0dp</dimen>
+    <dimen name="workspace_height_gap_port">0dp</dimen>
+
+    <dimen name="hotseat_width_gap">2dp</dimen>
+</resources>
diff --git a/FairphoneHome/res/values-th/strings.xml b/FairphoneHome/res/values-th/strings.xml
new file mode 100644
index 0000000..91070ad
--- /dev/null
+++ b/FairphoneHome/res/values-th/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"ตัวเรียกใช้งาน"</string>
+    <string name="home" msgid="5921706419368316758">"หน้าแรก"</string>
+    <string name="uid_name" msgid="3371120195364560632">"แอปหลัก Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"เลือกวอลเปเปอร์จาก"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"ตั้งค่าวอลเปเปอร์"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"วอลเปเปอร์"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"ไม่ได้ติดตั้งแอปพลิเคชัน"</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"วิดเจ็ต"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"แตะค้างเพื่อรับวิดเจ็ต"</string>
+    <string name="market" msgid="2652226429823445833">"ร้าน"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"ไม่สามารถวางรายการลงในหน้าจอหลักนี้"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"เลือกวิดเจ็ตที่จะสร้าง"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"ชื่อโฟลเดอร์"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"เปลี่ยนชื่อโฟลเดอร์"</string>
+    <string name="rename_action" msgid="6016003384693240896">"ตกลง"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"ยกเลิก"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"เพิ่มลงในหน้าแรก"</string>
+    <string name="group_applications" msgid="2103752818818161976">"แอปพลิเคชัน"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"ทางลัด"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"วิดเจ็ต"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"วอลเปเปอร์"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"ไม่มีที่ว่างในหน้าจอหลักของคุณ"</string>
+    <string name="out_of_space" msgid="8365249326091984698">"ไม่มีที่ว่างในหน้าจอหลักนี้"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"ไม่มีที่ว่างใน hotseat"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"วิดเจ็ตนี้มีขนาดใหญ่เกินไปสำหรับ hotseat"</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"สร้างทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" แล้ว"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"ทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" ถูกนำออกแล้ว"</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"ทางลัด \"<xliff:g id="NAME">%s</xliff:g>\" มีอยู่แล้ว"</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"เลือกทางลัด"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"เลือกแอปพลิเคชัน"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"แอปพลิเคชัน"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"บ้าน"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"นำออก"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"ถอนการติดตั้ง"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"นำออก"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"ถอนการติดตั้ง"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"ข้อมูลแอปพลิเคชัน"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"ค้นหา"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Voice Search"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"แอปพลิเคชัน"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"ลบ"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"ถอนการติดตั้งการอัปเดต"</string>
+    <string name="menu_add" msgid="3065046628354640854">"เพิ่ม"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"จัดการแอปพลิเคชัน"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"วอลเปเปอร์"</string>
+    <string name="menu_search" msgid="4826514464423239041">"ค้นหา"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"การแจ้งเตือน"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"การตั้งค่าระบบ"</string>
+    <string name="menu_help" msgid="4901160661634590633">"ความช่วยเหลือ"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"ถอนการติดตั้งแอปพลิเคชัน"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"รายละเอียดแอปพลิเคชัน"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"เลือกไว้ 1 แอปพลิเคชัน"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"เลือก 1 วิดเจ็ต"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"เลือก 1 โฟลเดอร์"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"เลือก 1 ทางลัด"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"ติดตั้งทางลัด"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"อนุญาตให้แอปพลิเคชันเพิ่มทางลัดโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"ถอนการติดตั้งทางลัด"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"อนุญาตให้แอปพลิเคชันนำทางลัดออกโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"อ่านการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"อนุญาตให้แอปพลิเคชันอ่านการตั้งค่าและทางลัดในหน้าหลัก"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"เขียนการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"อนุญาตให้แอปพลิเคชันเปลี่ยนการตั้งค่าและทางลัดในหน้าหลัก"</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"มีปัญหาขณะโหลดวิดเจ็ต"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"นี่เป็นแอปพลิเคชันระบบและไม่สามารถถอนการติดตั้งได้"</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"โฟลเดอร์ที่ไม่มีชื่อ"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"หน้าจอหลัก %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"หน้า %1$d จาก %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"หน้าจอหลัก %1$d จาก %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"แอปพลิเคชันหน้า %1$d จาก %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"วิดเจ็ตหน้า %1$d จาก %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"เชิญตามสบาย"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"คุณสามารถวางแอปพลิเคชันโปรดของคุณไว้ที่นี่"</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"หากต้องการดูแอปพลิเคชันทั้งหมด โปรดแตะที่วงกลม"</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"เลือกบางแอปพลิเคชัน"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"หากต้องการเพิ่มแอปพลิเคชันลงในหน้าจอหลัก ให้แตะแอปพลิเคชันค้างไว้"</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"จัดระเบียบแอปพลิเคชันของคุณด้วยโฟลเดอร์"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"หากต้องการย้ายแอปพลิเคชัน ให้แตะแอปพลิเคชันนั้นค้างไว้"</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"หากต้องการสร้างโฟลเดอร์ใหม่บนหน้าจอหลัก ให้วางแอปพลิเคชันหนึ่งซ้อนบนแอปพลิเคชันอื่น"</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"ตกลง"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"เปิดโฟลเดอร์ <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"แตะเพื่อปิดโฟลเดอร์"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"แตะเพื่อบัน​​ทึกการเปลี่ยนชื่อ"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"โฟลเดอร์ปิดอยู่"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"เปลี่ยนชื่อโฟลเดอร์เป็น <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"โฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-tl/strings.xml b/FairphoneHome/res/values-tl/strings.xml
new file mode 100644
index 0000000..dfa5357
--- /dev/null
+++ b/FairphoneHome/res/values-tl/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Home"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Pumili ng wallpaper mula sa"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Itakda ang wallpaper"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Mga Wallpaper"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Hindi naka-install ang app."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Mga Widget"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Pindutin nang matagal upang kumuha ng widget."</string>
+    <string name="market" msgid="2652226429823445833">"Mamili"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Hindi ma-drop ang item sa Home screen na ito."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Pumili ng widget na lilikhain"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Pangalan ng folder"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Palitan ng pangalan ang folder"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Kanselahin"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Idagdag sa Home screen"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Apps"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Mga Shortcut"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Mga Widget"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Mga Wallpaper"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Wala nang puwang sa iyong mga Home screen."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Wala nang lugar sa Home screen na ito."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Wala nang lugar sa hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Masyadong malaki ang widget na ito para sa hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Nalikha ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Inalis ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Umiiral na ang shortcut na \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Pumili ng shortcut"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Pumili ng app"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Alisin"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"I-uninstall"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Alisin"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"I-uninstall"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Impormasyon ng app"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Maghanap"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Paghahanap gamit ang Boses"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Apps"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Alisin"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"I-uninstall ang update"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Idagdag"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Pamahalaan ang apps"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Wallpaper"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Paghahanap"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Mga Notification"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Mga setting ng system"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Tulong"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"I-uninstall ang app"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Mga detalye ng app"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 app ang napili"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget ang napili"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 folder ang napili"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 shortcut ang napili"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"i-install ang mga shortcut"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Binibigyang-daan ang isang app na magdagdag ng mga shortcut nang walang panghihimasok ng user."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"huwag i-install ang mga shortcut"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Binibigyang-daan ang app na mag-alis ng mga shortcut nang walang panghihimasok ng user."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"basahin ang mga setting ng Home at shortcut"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Binibigyang-daan ang app na basahin ang mga setting at shortcut sa Home."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"magsulat ng mga setting ng Home at mga shortcut"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Binibigyang-daan ang app na baguhin ang mga setting at shortcut sa Home."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Problema sa pag-load ng widget"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Isa itong app ng system at hindi maaaring i-uninstall."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Walang Pangalang Folder"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Home screen %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Pahina %1$d ng %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Home screen %1$d ng %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Pahina ng apps %1$d ng %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Pahina ng widget %1$d ng %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Gawing komportable ang iyong sarili"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Maaari mong ilagay ang iyong mga paboritong app dito."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Upang tingnan ang lahat ng iyong apps, pindutin ang bilog."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Pumili ng ilang apps"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Upang magdagdag ng app sa iyong Home screen, pindutin ito nang matagal."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Isaayos ang iyong apps gamit ang mga folder"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Upang ilipat ang isang app, pindutin ito nang matagal."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Upang gumawa ng bagong folder sa iyong home screen, magpatong ng isang app sa ibabaw ng isa pa."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Binuksan ang folder, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Pindutin upang isara ang folder"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Pindutin upang i-save ang pagpapalit ng pangalan"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Nakasara ang folder"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Binago ang pangalan ng folder patungong <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Folder: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-tr/strings.xml b/FairphoneHome/res/values-tr/strings.xml
new file mode 100644
index 0000000..58fd9d0
--- /dev/null
+++ b/FairphoneHome/res/values-tr/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Launcher"</string>
+    <string name="home" msgid="5921706419368316758">"Ana Ekran"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Duvar kağıdı seçin:"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Duvar kağıdını ayarla"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Duvar Kağıtları"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Uygulama yüklü değil."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Widget\'lar"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Widget seçmek için dokunun ve basılı tutun."</string>
+    <string name="market" msgid="2652226429823445833">"Alışveriş"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Öğe bu Ana Ekrana bırakılamadı."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Oluşturmak için widget seçin"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Klasör adı"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Klasörü yeniden adlandır"</string>
+    <string name="rename_action" msgid="6016003384693240896">"Tamam"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"İptal"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Ana Sayfaya ekle"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Uygulamalar"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Kısayollar"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Widget\'lar"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Duvar Kağıtları"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Ana ekranlarınızda yer kalmadı."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Bu Ana Sayfada yer yok."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Favori kısayollarda yer yok"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Bu widget, hotseat için çok büyük."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu oluşturuldu."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu kaldırıldı."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu zaten var."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Kısayolu seçin"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Uygulama seçin"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Uygulamalar"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Ana Sayfa"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Kaldır"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Yüklemeyi Kaldır"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Kaldır"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Yüklemeyi kaldır"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Uygulama bilgileri"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Ara"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Sesli Arama"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Uygulamalar"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Kaldır"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Güncelleme kaldırılsın mı?"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Ekle"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Uygulamaları yönet"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Duvar Kağıdı"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Ara"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Bildirimler"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Sistem ayarları"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Yardım"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Uygulamayı kaldır"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Uygulama ayrıntıları"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"1 uygulama seçildi"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget seçildi"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 klasör seçildi"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 kısayol seçildi"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"kısayolları yükle"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Uygulamaya, kullanıcı müdahalesi olmadan kısayol ekleme izni verir."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"kısayolları kaldır"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Uygulamaya kullanıcı müdahalesi olmadan kısayolları kaldırma izni verir."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Ana Sayfa ayarlarını ve kısayollarını oku"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Uygulamaya Ana Ekrandaki ayarları ve kısayolları okuma izni verir."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Ana Sayfa ayarlarını ve kısayollarını yaz"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Uygulamaya Ana Ekrandaki ayarları ve kısayolları değiştirme izni verir."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Widget yüklenirken sorun oluştu"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Bu bir sistem uygulamasıdır ve kaldırılamaz."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Roket Fırlatıcı"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Adsız Klasör"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Ana ekran %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Sayfa %1$d / %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Ana ekran %1$d / %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Uygulama sayfası %1$d / %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Widget sayfası %1$d / %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Kendinizi evinizde hissedin"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Favori uygulamalarınızı buraya koyabilirsiniz."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Tüm uygulamalarınızı görmek için çembere dokunun."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"İstediğiniz uygulamaları seçin"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Ana Ekranınıza bir uygulama eklemek için, ilgili uygulamaya dokunup basılı tutun."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Uygulamalarınızı klasörlerle düzenleyin"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Bir uygulamayı taşımak için, uygulamaya dokunun ve basılı tutun."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Ana Ekranınızda yeni bir klasör oluşturmak için, bir uygulamayı diğerinin üzerine getirin."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"Tamam"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Klasör açıldı, <xliff:g id="WIDTH">%1$d</xliff:g> genişlik, <xliff:g id="HEIGHT">%2$d</xliff:g> yükseklik"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Klasörü kapatmak için dokunun"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Yeni adı kaydetmek için dokunun"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Klasör kapatıldı"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Klasörün adı <xliff:g id="NAME">%1$s</xliff:g> olarak değiştirildi"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Klasör: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-uk/strings.xml b/FairphoneHome/res/values-uk/strings.xml
new file mode 100644
index 0000000..2355b0d
--- /dev/null
+++ b/FairphoneHome/res/values-uk/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Пан. запуску"</string>
+    <string name="home" msgid="5921706419368316758">"Домашня сторінка"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Служби Android Core"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Вибрати фоновий малюнок з"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Устан. фон. мал."</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Фонові мал."</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Програму не встановлено."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Віджети"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Торкніться й утримуйте, щоб вибрати віджет."</string>
+    <string name="market" msgid="2652226429823445833">"Магазин"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Не вдалося помістити елемент на цей головний екран"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Вибрати віджет для створення"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Назва папки"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Переймен. папку"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Скасувати"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Додати до Головної"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Програми"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Ярлики"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Віджети"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Фонові мал."</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"На головних екранах більше немає місця."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"На цьому екрані немає місця."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"На гарячій панелі більше немає місця."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Цей віджет завеликий для Hotseat."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" створено."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" видалено."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Ярлик \"<xliff:g id="NAME">%s</xliff:g>\" уже існує."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Вибрати ярлик"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Вибрати програму"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Прогр."</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Головна"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Видалити"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Видалити"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Вилучити"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Видалити"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Інформація про програму"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Пошук"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Голосовий пошук"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Програми"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Видалити"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Видалити оновлення"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Додати"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Керув. прогр."</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Фоновий мал."</string>
+    <string name="menu_search" msgid="4826514464423239041">"Пошук"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Сповіщення"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Налаштування системи"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Довідка"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Видалити програму"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Деталі програми"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Вибрано 1 програму"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Вибрано 1 віджет"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Вибрано 1 папку"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Вибрано 1 ярлик"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"установити ярлики"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Дозволяє програмі додавати ярлики без втручання користувача."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"видалити ярлики"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Дозволяє програмі видаляти ярлики без втручання користувача."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"читати налашт-ня Головної та ярлики"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Дозволяє програмі читати налаштування та ярлики на головному екрані."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"писати налашт-ня Головної та ярлики"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Дозволяє програмі змінювати налаштування та ярлики на головному екрані."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Пробл із завантаж. віджета"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Це системна програма, її неможливо видалити."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Папка без назви"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Головний екран %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Сторінка %1$d з %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Головний екран %1$d з %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Сторінка програм %1$d з %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Сторінка віджетів %1$d з %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Влаштовуйтеся зручніше"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Тут можна розмістити вибрані програми."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Щоб побачити всі свої програми, торкніться кола."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Виберіть програми"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Щоб додати програму на головний екран, торкніться й утримуйте її."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Організовуйте програми за допомогою папок"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Щоб перемістити програму, торкніться й утримуйте її."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Щоб створити нову папку на головному екрані, помістіть одну програму на іншу."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"ОК"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Папку відкрито: <xliff:g id="WIDTH">%1$d</xliff:g> х <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Торкніться, щоб закрити папку"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Торкніться, щоб зберегти перейменування"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Папку закрито"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Папку перейменовано на <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Папка: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-vi/strings.xml b/FairphoneHome/res/values-vi/strings.xml
new file mode 100644
index 0000000..232aa0a
--- /dev/null
+++ b/FairphoneHome/res/values-vi/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Trình khởi chạy"</string>
+    <string name="home" msgid="5921706419368316758">"Trang chủ"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Ứng dụng Lõi Android"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Chọn hình nền từ"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Đặt hình nền"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Hình nền"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"Ứng dụng chưa được cài đặt."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Tiện ích"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Chạm &amp; giữ để chọn tiện ích con."</string>
+    <string name="market" msgid="2652226429823445833">"Mua hàng"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Không thể thả mục vào Màn hình chính này."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Chọn tiện ích con để tạo"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Tên thư mục"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Đổi tên thư mục"</string>
+    <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Hủy"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Thêm vào Màn hình chính"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Ứng dụng"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Lối tắt"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Tiện ích"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Hình nền"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Không còn chỗ trên Màn hình chính của bạn."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Không còn khoảng trống trên Màn hình chính này."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Không còn chỗ trên vùng gắn."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Tiện ích này quá lớn cho điểm giới hạn."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã được tạo."</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã bị xóa."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Lối tắt \"<xliff:g id="NAME">%s</xliff:g>\" đã tồn tại."</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Chọn lối tắt"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Chọn ứng dụng"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Ứng dụng"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Màn hình trang chủ"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Xóa"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Gỡ cài đặt"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Xóa"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Gỡ cài đặt"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Thông tin ứng dụng"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Tìm kiếm"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Tìm kiếm bằng giọng nói"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Ứng dụng"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Xóa"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Gỡ cài đặt cập nhật"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Thêm"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Quản lý ứng dụng"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Hình nền"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Tìm kiếm"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Thông báo"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Cài đặt hệ thống"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Trợ giúp"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Gỡ cài đặt ứng dụng"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Chi tiết ứng dụng"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Đã chọn 1 ứng dụng"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"Đã chọn 1 tiện ích"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"Đã chọn 1 thư mục"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Đã chọn 1 lối tắt"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"cài đặt lối tắt"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Cho phép ứng dụng thêm lối tắt mà không cần sự can thiệp của người dùng."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"gỡ cài đặt lối tắt"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Cho phép ứng dụng xóa lối tắt mà không cần sự can thiệp của người dùng."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"đọc cài đặt Màn hình trang chủ và lối tắt"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Cho phép ứng dụng đọc cài đặt và lối tắt trên Màn hình chính."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"ghi cài đặt Màn hình trang chủ và lối tắt"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Cho phép ứng dụng thay đổi cài đặt và lối tắt trên Màn hình chính."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Sự cố khi tải tiện ích"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Đây là ứng dụng hệ thống và không thể gỡ cài đặt."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Thư mục chưa đặt tên"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Màn hình chính %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Trang %1$d trong tổng số %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Màn hình chính %1$d trong tổng số %2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Trang ứng dụng %1$d trong tổng số %2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Trang tiện ích con %1$d trong tổng số %2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Tự nhiên như ở nhà"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Bạn có thể đặt ứng dụng yêu thích của mình tại đây."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Để xem tất cả ứng dụng của bạn, chạm vào vòng kết nối."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Chọn một số ứng dụng"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Để thêm ứng dụng vào Màn hình chính của bạn, chạm &amp; giữ ứng dụng đó."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Tổ chức ứng dụng của bạn bằng các thư mục"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Để di chuyển ứng dụng, chạm &amp; giữ ứng dụng đó."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Để tạo thư mục mới trên Màn hình chính của bạn, xếp ứng dụng này lên trên ứng dụng khác."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"OK"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Đã mở thư mục, <xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Chạm để đóng thư mục"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Chạm để lưu tên mới"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Đã đóng thư mục"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Đã đổi tên thư mục thành <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-zh-rCN/strings.xml b/FairphoneHome/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..fe30775
--- /dev/null
+++ b/FairphoneHome/res/values-zh-rCN/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"启动器"</string>
+    <string name="home" msgid="5921706419368316758">"主屏幕"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android 核心应用"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"选择壁纸来源"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"设置壁纸"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"壁纸"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"未安装该应用。"</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"小部件"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"触摸并按住可选取小部件。"</string>
+    <string name="market" msgid="2652226429823445833">"购买"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"无法将项拖放到此主屏幕上。"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"选择要创建的小部件"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"文件夹名称"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"重命名文件夹"</string>
+    <string name="rename_action" msgid="6016003384693240896">"确定"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"取消"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"添加到主屏幕"</string>
+    <string name="group_applications" msgid="2103752818818161976">"应用"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"快捷方式"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"小部件"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"壁纸"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"您的主屏幕上没有空间了。"</string>
+    <string name="out_of_space" msgid="8365249326091984698">"此主屏幕上已没有空间。"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"底部区域已无空间。"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"该小部件太大,超出基座区域可用空间。"</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"已创建“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"已删除“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"“<xliff:g id="NAME">%s</xliff:g>”快捷方式已存在。"</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"选择快捷方式"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"选择应用"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"应用"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"主屏幕"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"删除"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"卸载"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"删除"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"卸载"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"应用信息"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"搜索"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"语音搜索"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"应用"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"删除"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"卸载更新"</string>
+    <string name="menu_add" msgid="3065046628354640854">"添加"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"管理应用"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"壁纸"</string>
+    <string name="menu_search" msgid="4826514464423239041">"搜索"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"系统设置"</string>
+    <string name="menu_help" msgid="4901160661634590633">"帮助"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"卸载该应用"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"应用详情"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"选中了 1 个应用"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"已选中 1 个小部件"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"已选中 1 个文件夹"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"已选中 1 个快捷方式"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"安装快捷方式"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"允许应用自行添加快捷方式。"</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"卸载快捷方式"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"允许应用自行删除快捷方式,而无需用户干预。"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"读取主屏幕的设置和快捷方式"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"允许应用读取主屏幕中的设置和快捷方式。"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"写入主屏幕的设置和快捷方式"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"允许应用更改主屏幕中的设置和快捷方式。"</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"载入小部件时出现问题"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"这是系统应用,无法卸载。"</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"未命名文件夹"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"主屏幕 %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"第 %1$d 页,共 %2$d 页"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"主屏幕 %1$d(共 %2$d 个)"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"应用:第 %1$d 页,共 %2$d 页"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"小部件:第 %1$d 页,共 %2$d 页"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"您的主屏幕您做主"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"您可以在此处放置自己喜爱的应用。"</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"要查看您的所有应用,请触摸该圆圈。"</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"选择一些应用"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"要将某个应用添加到主屏幕,请触摸并按住该应用。"</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"使用文件夹整理应用"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"要移动应用,请触摸并按住该应用。"</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"要在主屏幕上创建新文件夹,请将一个应用叠放到另一个上。"</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"确定"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"文件夹已打开,尺寸为 <xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"触摸可关闭文件夹"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"触摸可保存重命名"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"文件夹已关闭"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"已将文件夹重命名为“<xliff:g id="NAME">%1$s</xliff:g>”"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"文件夹:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-zh-rTW/strings.xml b/FairphoneHome/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..f261ddf
--- /dev/null
+++ b/FairphoneHome/res/values-zh-rTW/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"啟動器"</string>
+    <string name="home" msgid="5921706419368316758">"住家"</string>
+    <string name="uid_name" msgid="3371120195364560632">"Android 核心應用程式"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"選擇桌布來源"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"設定桌布"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"桌布"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"應用程式未安裝。"</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"小工具"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"輕觸並按住小工具即可選取。"</string>
+    <string name="market" msgid="2652226429823445833">"商店"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"無法將項目拖放至這個主螢幕上。"</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"選擇要建立的小工具"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"資料夾名稱"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"重新命名資料夾"</string>
+    <string name="rename_action" msgid="6016003384693240896">"確定"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"取消"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"新增至主螢幕"</string>
+    <string name="group_applications" msgid="2103752818818161976">"應用程式"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"捷徑"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"小工具"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"桌布"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"主螢幕已無空間。"</string>
+    <string name="out_of_space" msgid="8365249326091984698">"主螢幕已無空間"</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"停駐區已無可用空間。"</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"這個小工具過大,超出可用的空間。"</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"已建立「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"已移除「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"「<xliff:g id="NAME">%s</xliff:g>」捷徑已經存在。"</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"選擇捷徑"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"選擇應用程式"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"應用程式"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"主螢幕"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"移除"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"解除安裝"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"移除"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"解除安裝"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"應用程式資訊"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"搜尋"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"語音搜尋"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"應用程式"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"移除"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"解除安裝更新"</string>
+    <string name="menu_add" msgid="3065046628354640854">"新增"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"管理應用程式"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"桌布"</string>
+    <string name="menu_search" msgid="4826514464423239041">"搜尋"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"系統設定"</string>
+    <string name="menu_help" msgid="4901160661634590633">"說明"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"解除安裝應用程式"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"應用程式詳細資料"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"已選取 1 個應用程式"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"已選取 1 個小工具"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"已選取 1 個資料夾"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"已選取 1 個捷徑"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"安裝捷徑"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"允許應用程式自動新增捷徑。"</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"解除安裝捷徑"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"允許應用程式自動移除捷徑。"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"讀取主螢幕設定和捷徑"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"允許應用程式讀取主螢幕中的設定與捷徑。"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"寫入主螢幕設定和捷徑"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"允許應用程式變更主螢幕中的設定與捷徑。"</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"載入小工具時發生問題"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"這是系統應用程式,不可解除安裝。"</string>
+    <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"未命名的資料夾"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"主螢幕 %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"第 %1$d 頁,共 %2$d 頁"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"主螢幕 %1$d,共 %2$d 個"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"應用程式:第 %1$d 頁,共 %2$d 頁"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"小工具:第 %1$d 頁,共 %2$d 頁"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"當作自己家"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"您可以將最愛的應用程式放在這裡。"</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"如要查看您所有的應用程式,請輕觸圓圈。"</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"選擇一些應用程式"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"如要將應用程式新增至主螢幕,請輕觸並按住目標項目。"</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"使用資料夾整理應用程式"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"如要移動應用程式,請輕觸並按住目標。"</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"如要在主螢幕建立新資料夾,請將應用程式一個個堆疊起來。"</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"確定"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"資料夾已開啟 (<xliff:g id="WIDTH">%1$d</xliff:g> x <xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"輕觸即可關閉資料夾"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"輕觸即可儲存重新命名後的名稱"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"已關閉資料夾"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"已將資料夾重新命名為 <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values-zu/strings.xml b/FairphoneHome/res/values-zu/strings.xml
new file mode 100644
index 0000000..6faa63d
--- /dev/null
+++ b/FairphoneHome/res/values-zu/strings.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+* 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="application_name" msgid="8424725141379931883">"Isiqalisi"</string>
+    <string name="home" msgid="5921706419368316758">"Ikhaya"</string>
+    <string name="uid_name" msgid="3371120195364560632">"I-Android Core Apps"</string>
+    <string name="folder_name" msgid="8551881338202938211"></string>
+    <string name="chooser_wallpaper" msgid="6063168087625352235">"Khetha iphephalodonga kwi"</string>
+    <string name="wallpaper_instructions" msgid="4215640646180727542">"Hlela iphephadonga"</string>
+    <string name="pick_wallpaper" msgid="5630222540525626723">"Amaphephadonga"</string>
+    <string name="activity_not_found" msgid="217823393239365967">"I-App ayifakiwe."</string>
+    <string name="widgets_tab_label" msgid="9145860100000983599">"Amawijethi"</string>
+    <string name="long_press_widget_to_add" msgid="7395697462851217506">"Thinta &amp; bamba ukuthatha iwijethi"</string>
+    <string name="market" msgid="2652226429823445833">"Thenga"</string>
+    <string name="external_drop_widget_error" msgid="2285187188524172774">"Ayikwazanga ukubeka into kulesi sikrini sasekhaya."</string>
+    <string name="external_drop_widget_pick_title" msgid="7040647073452295370">"Khetha i-wijethi ongayidala"</string>
+    <string name="rename_folder_label" msgid="5646236631298452787">"Igama lefolda"</string>
+    <string name="rename_folder_title" msgid="4544573104191526550">"Qamba kabusha ifolda"</string>
+    <string name="rename_action" msgid="6016003384693240896">"KULUNGILE"</string>
+    <string name="cancel_action" msgid="3811860427489435048">"Khansela"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Faka kwisikrini saseKhaya"</string>
+    <string name="group_applications" msgid="2103752818818161976">"Izinsiza"</string>
+    <string name="group_shortcuts" msgid="9133529424900391877">"Izinqamuleli"</string>
+    <string name="group_widgets" msgid="6704978494073105844">"Izinqunjwana"</string>
+    <string name="group_wallpapers" msgid="1568191644272224858">"Amaphephadonga"</string>
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Akusenagumbi ezikrinini zakho zekhaya."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Asisekho isikhala kulesi sikrini Sasekhaya."</string>
+    <string name="hotseat_out_of_space" msgid="6304886797358479361">"Akusenagumbi ku-hotseat."</string>
+    <string name="invalid_hotseat_item" msgid="6545340627805449250">"Le wijethi inkulu kakhulu ukuba ibe esihlalweni esishisayo"</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Isinqamuleli \"<xliff:g id="NAME">%s</xliff:g>\" senziwe"</string>
+    <string name="shortcut_uninstalled" msgid="2129499669449749995">"Isinqamuleli \"<xliff:g id="NAME">%s</xliff:g>\" sikhishiwe."</string>
+    <string name="shortcut_duplicate" msgid="4757756326465060694">"Isinqamuleli \"<xliff:g id="NAME">%s</xliff:g>\" sivele sikhona"</string>
+    <string name="title_select_shortcut" msgid="1873670208166882222">"Khetha isinqamulelo"</string>
+    <string name="title_select_application" msgid="1793455815754848652">"Khetha i-app"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Izinhlelo zokusebenza"</string>
+    <string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekhaya"</string>
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Khipha"</string>
+    <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Khipha"</string>
+    <string name="delete_target_label" msgid="665300185123139530">"Susa"</string>
+    <string name="delete_target_uninstall_label" msgid="748894921183769150">"Khipha"</string>
+    <string name="info_target_label" msgid="4019495079517426980">"Ulwazi lohlelo lokusebenza"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Sesha"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Ukusesha Ngezwi"</string>
+    <string name="accessibility_all_apps_button" msgid="8803738611398979849">"Izinsiza"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Susa"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Khipha isibuyekezo"</string>
+    <string name="menu_add" msgid="3065046628354640854">"Engeza"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Phatha izinhlelo zokusebenza"</string>
+    <string name="menu_wallpaper" msgid="5837429080911269832">"Phephadonga"</string>
+    <string name="menu_search" msgid="4826514464423239041">"Sesha"</string>
+    <string name="menu_notifications" msgid="6424587053194766192">"Izaziso"</string>
+    <string name="menu_settings" msgid="3946232973327980394">"Izilungiselelo Zendlela Yokusebenza"</string>
+    <string name="menu_help" msgid="4901160661634590633">"Usizo"</string>
+    <string name="cab_menu_delete_app" msgid="4089398025537640349">"Khipha i-app"</string>
+    <string name="cab_menu_app_info" msgid="914548323652698884">"Imininingwane ye-App"</string>
+    <string name="cab_app_selection_text" msgid="6378522164293415735">"Kukhethwe i-app engu-1"</string>
+    <string name="cab_widget_selection_text" msgid="962527270506951955">"kukhethwe iwijethi engu-1"</string>
+    <string name="cab_folder_selection_text" msgid="8916111874189565067">"kukhethwe ifolda engu-1"</string>
+    <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"kukhethwe isinqamuleli esingu-1"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"engeza izinqamuleli"</string>
+    <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Ivumela uhlelo lokusebenza ukufaka izinqamuleli ngaphandle kokungenela komsebenzisi."</string>
+    <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"khipha izinqamuleli"</string>
+    <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Vumela i-app ukususa izinqamuleli ngaphandle kukubandakanyeka komsebenzisi."</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"funda izilungiselelo zaseKhaya nezinqamuleli"</string>
+    <string name="permdesc_read_settings" msgid="5788109303585403679">"Vumela ama-app ukufunda izilungiselelo nezinqamulelo eKhaya."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"bhala izilungiselelo zaseKhaya nezinqamuleli"</string>
+    <string name="permdesc_write_settings" msgid="8530105489115785531">"Vumela ama-app ukushintsha izilungiselelo nezinqamulelo eKhaya."</string>
+    <string name="gadget_error_text" msgid="8359351016167075858">"Inkinga yokulayisha iwijethi"</string>
+    <string name="uninstall_system_app_text" msgid="6429814133777046491">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
+    <string name="dream_name" msgid="2847171357608437154">"Isiqalisi se-Rocket"</string>
+    <string name="folder_hint_text" msgid="8633351560105748141">"Ifolda Engenagama"</string>
+    <string name="workspace_description_format" msgid="2968608205939373034">"Isikrini sasekhaya %1$d"</string>
+    <string name="default_scroll_format" msgid="4057140866420001240">"Ikhasi %1$d lika %2$d"</string>
+    <string name="workspace_scroll_format" msgid="1704767047951143301">"Isikrini sasekhaya %1$d se-%2$d"</string>
+    <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"Ukhasi lama-Apps %1$d le-%2$d"</string>
+    <string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"Ikhasi le-Widgets %1$d le-%2$d"</string>
+    <string name="workspace_cling_title" msgid="738396473989890567">"Zizwe usekhaya"</string>
+    <string name="workspace_cling_move_item" msgid="791013895761065070">"Ungafaka izinsiza zakho ozithandayo lapha."</string>
+    <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"Ukubona zonke izinsiza zakho, thinta indingiliza."</string>
+    <string name="all_apps_cling_title" msgid="2559734712581447107">"Khetha ezinye izinsiza"</string>
+    <string name="all_apps_cling_add_item" msgid="5665035103260318891">"Ukwengeza insiza eskrinini sakho sasekhaya, thinta &amp;uyibambe."</string>
+    <string name="folder_cling_title" msgid="4308949882377840953">"Hlela izinsiza zakho ngamafolda"</string>
+    <string name="folder_cling_move_item" msgid="270598675060435169">"Ukususa insiza, thinta &amp; uyibambe."</string>
+    <string name="folder_cling_create_folder" msgid="8352867485656129478">"Ukwenza ifolda entsha eskrinini sakho sasekhaya, beka insiza eyodwa phezulu kwenye."</string>
+    <string name="cling_dismiss" msgid="2780907108735868381">"KULUNGILE"</string>
+    <string name="folder_opened" msgid="1262064100943801533">"Ifolda ivulwe, <xliff:g id="WIDTH">%1$d</xliff:g> by <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
+    <string name="folder_tap_to_close" msgid="1335478160661137579">"Thinta ukuze uvale ifolda"</string>
+    <string name="folder_tap_to_rename" msgid="5201612989905472442">"Thinta ukuze ulondoloze ukuqamba kabusha"</string>
+    <string name="folder_closed" msgid="3130534551370511932">"Ifolda ivaliwe"</string>
+    <string name="folder_renamed" msgid="7951233572858053642">"Ifolda iqanjwe kabusha ngo-<xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="folder_name_format" msgid="3051680259794759037">"Ifolda: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="custom_workspace_cling_title_1" msgid="1433009175359948587"></string>
+    <string name="custom_workspace_cling_description_1" msgid="6875529190849858047"></string>
+    <string name="custom_workspace_cling_title_2" msgid="5516006164661020362"></string>
+    <string name="custom_workspace_cling_description_2" msgid="2758258454975288377"></string>
+</resources>
diff --git a/FairphoneHome/res/values/array.xml b/FairphoneHome/res/values/array.xml
new file mode 100644
index 0000000..88b9fef
--- /dev/null
+++ b/FairphoneHome/res/values/array.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+        <string-array name="prefMoodChangerType">
+            <item name="no_mood">No mood</item>
+            <item name="mood_background">Mood over background</item>
+            <item name="mood_only">Only mood</item>
+        </string-array>
+        <string-array name="prefMoodChangerTypeValues">
+            <item name="no_mood">0</item>
+            <item name="mood_background">1</item>
+            <item name="mood_only">2</item>
+        </string-array>
+
+<!--     <string-array name="prefMoodChangerAlpha"> -->
+<!--         <item name="25">See almost only background</item> -->
+<!--         <item name="50">See background and mood</item> -->
+<!--         <item name="75">See almost only mood</item> -->
+<!--         <item name="100">Solid, no background</item> -->
+<!--     </string-array> -->
+<!--     <string-array name="prefMoodChangerAlphaValues"> -->
+<!--         <item name="25">0.25</item> -->
+<!--         <item name="50">0.5</item> -->
+<!--         <item name="75">0.75</item> -->
+<!--         <item name="100">1.0</item> -->
+<!--     </string-array> -->
+    
+<!--     <string-array name="prefMoodChangerPlacement"> -->
+<!--         <item name="none">Mood nowhere</item> -->
+<!--         <item name="lockscreen">Mood on lock screen only</item> -->
+<!--         <item name="homescreen">Mood on home screen only</item> -->
+<!--         <item name="both">Mood everywhere</item> -->
+        
+<!--     </string-array> -->
+<!--     <string-array name="prefMoodChangerPlacementValues"> -->
+<!--         <item name="none">0</item> -->
+<!--         <item name="lockscreen">1</item> -->
+<!--         <item name="homescreen">2</item> -->
+<!--         <item name="both">3</item> -->
+<!--     </string-array> -->
+     
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values/attrs.xml b/FairphoneHome/res/values/attrs.xml
new file mode 100644
index 0000000..c76a6a5
--- /dev/null
+++ b/FairphoneHome/res/values/attrs.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 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.
+*/
+-->
+
+<resources>
+    <!-- Orientation of a widget. -->
+    <attr name="direction">
+        <!-- Vertical widget. -->
+        <enum name="vertical" value="0" />
+        <!-- Horizontal widget. -->
+        <enum name="horizontal" value="1" />
+    </attr>
+
+    <skip />
+
+    <!-- DrawableStateProxyView specific attributes. These attributes are used to customize
+         a DrawableStateProxyView view in XML files. -->
+    <declare-styleable name="DrawableStateProxyView">
+        <!-- The source view to delegate touch presses events to. -->
+        <attr name="sourceViewId" format="integer" />
+    </declare-styleable>
+
+    <!-- Cling specific attributes. These attributes are used to customize
+         the cling in XML files. -->
+    <declare-styleable name="Cling">
+        <!-- Used to identify how to draw the cling bg -->
+        <attr name="drawIdentifier" format="string"  />
+    </declare-styleable>
+
+    <!-- Workspace specific attributes. These attributes are used to customize
+         the workspace in XML files. -->
+    <declare-styleable name="Workspace">
+        <!-- The first screen the workspace should display. -->
+        <attr name="defaultScreen" format="integer"  />
+        <!-- The number of horizontal cells in the CellLayout -->
+        <attr name="cellCountX" format="integer"  />
+        <!-- The number of vertical cells in the CellLayout -->
+        <attr name="cellCountY" format="integer"  />
+    </declare-styleable>
+    
+    <!-- Hotseat specific attributes. These attributes are used to customize
+         the hotseat in XML files. -->
+    <declare-styleable name="Hotseat">
+        <!-- The number of horizontal cells in the CellLayout -->
+        <attr name="cellCountX" />
+        <!-- The number of vertical cells in the CellLayout -->
+        <attr name="cellCountY" />
+    </declare-styleable>
+
+    <!-- CellLayout specific attributes. These attributes are used to customize
+         a CellLayout view in XML files. -->
+    <declare-styleable name="CellLayout">
+        <!-- The width of a single cell -->
+        <attr name="cellWidth" format="dimension"  />
+        <!-- The height of a single cell -->
+        <attr name="cellHeight" format="dimension"  />
+        <!-- An override for the width and height gap to allow users to specify
+             a specific size for the page using spacing instead of resolving the
+             spacing from the width of the page -->
+        <attr name="widthGap" format="dimension" />
+        <attr name="heightGap" format="dimension" />
+        <!-- The max gap size for each dimension -->
+        <attr name="maxGap" format="dimension" />
+    </declare-styleable>
+
+    <!-- StrokedTextView specific attributes. -->
+    <declare-styleable name="StrokedTextView">
+        <!-- The color of the stroke outline -->
+        <attr name="strokeColor" format="color" />
+        <!-- The color of the text -->
+        <attr name="strokeTextColor" format="color" />
+        <!-- The width of the stroke -->
+        <attr name="strokeWidth" format="float" />
+    </declare-styleable>
+
+    <!-- HolographicLinearLayout specific attributes. -->
+    <declare-styleable name="HolographicLinearLayout">
+        <!-- The source view to generate and apply the drawable states to/from -->
+        <attr name="sourceImageViewId" format="integer" />
+    </declare-styleable>
+
+    <!-- PagedView specific attributes. These attributes are used to customize
+         a PagedView view in XML files. -->
+    <declare-styleable name="PagedView">
+        <!-- A spacing override for the icons within a page -->
+        <attr name="pageLayoutWidthGap" format="dimension" />
+        <attr name="pageLayoutHeightGap" format="dimension" />
+        <!-- The padding of the pages that are dynamically created per page -->
+        <attr name="pageLayoutPaddingTop" format="dimension" />
+        <attr name="pageLayoutPaddingBottom" format="dimension" />
+        <attr name="pageLayoutPaddingLeft" format="dimension" />
+        <attr name="pageLayoutPaddingRight" format="dimension" />
+        <!-- The space between adjacent pages of the PagedView. -->
+        <attr name="pageSpacing" format="dimension" />
+        <!-- The padding for the scroll indicator area -->
+        <attr name="scrollIndicatorPaddingLeft" format="dimension" />
+        <attr name="scrollIndicatorPaddingRight" format="dimension" />
+    </declare-styleable>
+
+    <!-- AppsCustomizePagedView specific attributes.  These attributes are used to
+         customize an AppsCustomizePagedView in xml files. -->
+    <declare-styleable name="AppsCustomizePagedView">
+        <!-- Max number of cells of applications horizontally -->
+        <attr name="maxAppCellCountX" format="integer" />
+        <!-- Max number of cells of applications vertically -->
+        <attr name="maxAppCellCountY" format="integer" />
+        <!-- Horizontal spacing between widgets and wallpapers -->
+        <attr name="widgetCellWidthGap" format="dimension" />
+        <!-- Vertical spacing between widgets -->
+        <attr name="widgetCellHeightGap" format="dimension" />
+        <!-- Number of widgets horizontally -->
+        <attr name="widgetCountX" format="integer" />
+        <!-- Number of widgets vertically -->
+        <attr name="widgetCountY" format="integer" />
+        <!-- The x index of the item to be focused in the cling -->
+        <attr name="clingFocusedX" format="integer" />
+        <!-- The y index of the item to be focused in the cling -->
+        <attr name="clingFocusedY" format="integer" />
+    </declare-styleable>
+
+    <!-- HandleView specific attributes. These attributes are used to customize
+         a HandleView view in XML files. -->
+    <declare-styleable name="HandleView">
+        <!-- Orientation of the handle. -->
+        <attr name="direction" />
+    </declare-styleable>
+
+    <!-- XML attributes used by default_workspace.xml -->
+    <declare-styleable name="Favorite">
+        <attr name="className" format="string" />
+        <attr name="packageName" format="string" />
+        <attr name="container" format="string" />
+        <attr name="screen" format="string" />
+        <attr name="x" format="string" />
+        <attr name="y" format="string" />
+        <attr name="spanX" format="string" />
+        <attr name="spanY" format="string" />
+        <attr name="icon" format="reference" />  
+        <attr name="title" format="reference" />
+        <attr name="uri" format="string" />
+    </declare-styleable>
+    <declare-styleable name="Extra">
+        <attr name="key" format="string" />
+        <attr name="value" format="string" />
+    </declare-styleable>
+
+    <!-- Only used in the device overlays -->
+    <declare-styleable name="CustomClingTitleText">
+    </declare-styleable>
+    <declare-styleable name="CustomClingText">
+    </declare-styleable>
+</resources>
diff --git a/FairphoneHome/res/values/colors.xml b/FairphoneHome/res/values/colors.xml
new file mode 100644
index 0000000..4b33c72
--- /dev/null
+++ b/FairphoneHome/res/values/colors.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 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.
+*/
+-->
+<resources>
+
+    <!--
+         The color tints to apply to the text and drag view when hovering
+         over the delete target or the info target
+    -->
+    <color name="delete_target_hover_tint">#DAFF0000</color>
+    <color name="info_target_hover_tint">#DA0099CC</color>
+    <color name="bubble_dark_background">#20000000</color>
+    <color name="appwidget_error_color">#FCCC</color>
+    <color name="workspace_all_apps_and_delete_zone_text_color">#CCFFFFFF</color>
+    <color name="workspace_all_apps_and_delete_zone_text_shadow_color">#A0000000</color>
+    <color name="workspace_icon_text_color">#FFF</color>
+    <color name="text_color_white">#FFF</color>
+    <color name="text_shadow_color">#000</color>
+    <color name="white">#FFFFFF</color>
+    <color name="transparent">#00000000</color>
+    <color name="google_blue">#33b5e5</color>
+    <color name="google_progressbar_grey">#4a4d51</color>
+    
+    
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values/config.xml b/FairphoneHome/res/values/config.xml
new file mode 100644
index 0000000..7cdfa3e
--- /dev/null
+++ b/FairphoneHome/res/values/config.xml
@@ -0,0 +1,104 @@
+<resources>
+    <bool name="config_largeHeap">false</bool>
+    <bool name="is_large_screen">false</bool>
+    <bool name="allow_rotation">false</bool>
+
+<!-- DragController -->
+    <integer name="config_flingToDeleteMinVelocity">-1500</integer>
+
+<!-- AllApps/Customize/AppsCustomize -->
+    <!-- The alpha of the AppsCustomize bg in spring loaded mode -->
+    <integer name="config_appsCustomizeSpringLoadedBgAlpha">45</integer>
+    <integer name="config_workspaceUnshrinkTime">300</integer>
+    <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
+    <integer name="config_workspaceSpringLoadShrinkPercentage">80</integer>
+
+    <!-- Fade/zoom in/out duration & scale in the AllApps transition.
+         Note: This should be less than the workspaceShrinkTime as they happen together. -->
+    <integer name="config_appsCustomizeZoomInTime">350</integer>
+    <integer name="config_appsCustomizeZoomOutTime">600</integer>
+    <integer name="config_appsCustomizeZoomScaleFactor">7</integer>
+    <integer name="config_appsCustomizeFadeInTime">250</integer>
+    <integer name="config_appsCustomizeFadeOutTime">200</integer>
+    <integer name="config_appsCustomizeWorkspaceShrinkTime">300</integer>
+    <integer name="config_appsCustomizeWorkspaceAnimationStagger">40</integer>
+    <integer name="config_workspaceAppsCustomizeAnimationStagger">100</integer>
+
+    <!-- Tab transition animation duration -->
+    <integer name="config_tabTransitionDuration">250</integer>
+
+    <!-- The slope, in percent, of the drag movement needed to drag an item out of
+         AppsCustomize (y / x * 100%)  -->
+    <integer name="config_appsCustomizeDragSlopeThreshold">150</integer>
+
+    <!-- Batch loading for loading in LauncherModel -->
+    <integer name="config_allAppsBatchLoadDelay">0</integer>
+    <integer name="config_allAppsBatchSize">0</integer>
+
+<!-- Workspace -->
+    <!-- Whether or not the drop targets drop down as opposed to fade in -->
+    <bool name="config_useDropTargetDownTransition">true</bool>
+    <!-- Whether or not to fade the side pages -->
+    <bool name="config_workspaceFadeAdjacentScreens">false</bool>
+
+    <!-- The transition duration for the background of the drop targets -->
+    <integer name="config_dropTargetBgTransitionDuration">0</integer>
+
+    <!-- The duration (in ms) of the fade animation on the object outlines, used when
+         we are dragging objects around on the home screen. -->
+    <integer name="config_dragOutlineFadeTime">900</integer>
+
+    <!-- The alpha value at which to show the most recent drop visualization outline. -->
+    <integer name="config_dragOutlineMaxAlpha">128</integer>
+
+    <!-- Parameters controlling the animation for when an item is dropped on the home screen,
+         and it animates from its old position to the new one. -->
+    <integer name="config_dropAnimMinDuration">100</integer>
+    <integer name="config_dropAnimMaxDuration">500</integer>
+
+    <!-- The duration of the UserFolder opening and closing animation -->
+    <integer name="config_folderAnimDuration">120</integer>
+
+    <!-- The distance at which the animation should take the max duration -->
+    <integer name="config_dropAnimMaxDist">800</integer>
+
+    <!-- Properties controlling the workspace fade-out during dragging -->
+    <integer name="config_dragFadeOutAlpha">80</integer>
+    <integer name="config_dragFadeOutDuration">250</integer>
+
+    <!-- Camera distance for the overscroll effect -->
+    <integer name="config_cameraDistance">6500</integer>
+
+    <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y
+         >= folder_max_num_items. When these are set to -1, they are automatically determined. -->
+    <integer name="folder_max_count_x">4</integer>
+    <integer name="folder_max_count_y">4</integer>
+    <integer name="folder_max_num_items">16</integer>
+
+    <integer name="cell_count_x">4</integer>
+    <integer name="cell_count_y">4</integer>
+
+    <!-- Whether or not to use custom clings if a custom workspace layout is passed in -->
+    <bool name="config_useCustomClings">false</bool>
+
+<!-- Hotseat -->
+    <bool name="hotseat_transpose_layout_with_orientation">true</bool>
+    <integer name="hotseat_cell_count">5</integer>
+    <integer name="hotseat_all_apps_index">2</integer>
+    <!-- must be between 0 and 100 -->
+    <integer name="hotseat_item_scale_percentage">100</integer>
+    
+<!-- Edge menu -->
+	<string name="edge_swipe_default_apps">com.android.contacts,com.android.contacts.activities.DialtactsActivity;com.android.mms,com.android.mms.ui.BootActivity;com.android.gallery3d,com.android.camera.CameraLauncher;com.android.browser,com.android.browser.BrowserActivity</string>
+	<integer name="config_edgeMenuQuickTime">130</integer>
+	<integer name="config_edgeMenuEditButtonTime">1000</integer>
+	
+<!-- Google Apps Instaler -->
+	<string name="gapps_installer_download_url">http://www.fairphone.com/externalcontent/fp_ga.zip</string>
+	<!--<string name="gapps_installer_download_url">http://www.kwamecorp.com/dev/fairphonegapps.zip</string>-->
+	<string name="gapps_installer_config_file">fairphonegapps</string>
+	<string name="gapps_installer_zip">.zip</string>
+	<string name="gapps_installer_cfg">.cfg</string>
+	<string name="gapps_installer_sig">.sig</string>
+	<string name="gapps_installer_filename">googleapps.zip</string>
+</resources>
diff --git a/FairphoneHome/res/values/dimens.xml b/FairphoneHome/res/values/dimens.xml
new file mode 100644
index 0000000..bffbaac
--- /dev/null
+++ b/FairphoneHome/res/values/dimens.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<resources>
+<!-- Cling -->
+    <dimen name="clingPunchThroughGraphicCenterRadius">94dp</dimen>
+    <dimen name="folderClingMarginTop">20dp</dimen>
+    <!-- The offset for the text in the cling -->
+    <dimen name="cling_text_block_offset_x">0dp</dimen>
+    <dimen name="cling_text_block_offset_y">0dp</dimen>
+    <dimen name="reveal_radius">48dp</dimen>
+    <!-- entries for custom clings, will be set in overlays -->
+    <add-resource type="dimen" name="custom_cling_margin_top" />
+    <add-resource type="dimen" name="custom_cling_margin_right" />
+    <add-resource type="dimen" name="custom_cling_margin_left" />
+
+<!-- Workspace -->
+    <!-- qsb_bar_height_inset represents qsb_bar_height minus the padding
+         that we put on each page for allowing folders to draw out of bounds -->
+    <dimen name="qsb_bar_height_inset">34dp</dimen>
+    <dimen name="qsb_bar_height">40dp</dimen>
+    <dimen name="qsb_padding_left">0dp</dimen>
+    <dimen name="qsb_padding_right">0dp</dimen>
+    <dimen name="search_bar_height">40dp</dimen>
+    <dimen name="workspace_max_gap">16dp</dimen>
+    <dimen name="folder_cell_width">74dp</dimen>
+    <dimen name="folder_cell_height">82dp</dimen>
+    <dimen name="folder_icon_padding_top">2dp</dimen>
+    <dimen name="workspace_divider_padding_left">3dp</dimen>
+    <dimen name="workspace_divider_padding_right">3dp</dimen>
+    <dimen name="workspace_divider_padding_top">0dp</dimen>
+    <dimen name="workspace_divider_padding_bottom">0dp</dimen>
+    <dimen name="hotseat_cell_width">64dp</dimen>
+    <dimen name="hotseat_cell_height">64dp</dimen>
+    <dimen name="hotseat_width_gap">-1dp</dimen>
+    <dimen name="hotseat_height_gap">-1dp</dimen>
+    <dimen name="workspace_overscroll_drawable_padding">0dp</dimen>
+    <dimen name="workspace_icon_text_size">12sp</dimen>
+    <dimen name="workspace_spring_loaded_page_spacing">15dp</dimen>
+
+    <dimen name="app_icon_drawable_padding">6dp</dimen>
+    <dimen name="app_icon_drawable_padding_land">2dp</dimen>
+    <dimen name="app_icon_padding_top">8dp</dimen>
+
+<!-- QSB -->
+    <dimen name="toolbar_button_vertical_padding">0dip</dimen>
+    <dimen name="toolbar_button_horizontal_padding">12dip</dimen>
+    <!-- External toolbar icon size (for bounds) -->
+    <dimen name="toolbar_external_icon_width">36dp</dimen>
+    <dimen name="toolbar_external_icon_height">36dp</dimen>
+
+<!-- AllApps/Customize/AppsCustomize -->
+    <integer name="apps_customize_maxCellCountX">-1</integer>
+    <integer name="apps_customize_maxCellCountY">-1</integer>
+    <!-- The height of the tab bar - if this changes, we should update the
+         external icon width/height above to compensate -->
+    <dimen name="apps_customize_tab_bar_height">52dp</dimen>
+    <dimen name="apps_customize_tab_bar_margin_top">0dp</dimen>
+    <dimen name="app_icon_size">48dp</dimen>
+    <!-- The width can be 72dp because we don't have L/R padding -->
+    <dimen name="apps_customize_cell_width">74dp</dimen>
+    <dimen name="apps_customize_cell_height">82dp</dimen>
+    <dimen name="apps_customize_max_gap">18dp</dimen>
+    <dimen name="apps_customize_widget_cell_width_gap">10dp</dimen>
+    <dimen name="apps_customize_widget_cell_height_gap">8dp</dimen>
+
+    <!-- height of the bottom row of controls -->
+    <dimen name="button_bar_height">62dip</dimen>
+    <!-- Because portal animations go beyond the bounds of an icon, we need
+         to make the dock layout slightly larger than the button_bar_height -->
+    <dimen name="button_bar_height_top_padding">8dp</dimen>
+    <dimen name="button_bar_height_bottom_padding">0dp</dimen>
+    <dimen name="button_bar_width_left_padding">0dp</dimen>
+    <dimen name="button_bar_width_right_padding">0dp</dimen>
+    <dimen name="button_bar_height_plus_padding">70dp</dimen>
+
+    <!-- Drag padding to add to the bottom of drop targets -->
+    <dimen name="drop_target_drag_padding">14dp</dimen>
+
+<!-- Dragging -->
+    <!-- the area at the edge of the screen that makes the workspace go left
+         or right while you're dragging. -->
+    <dimen name="scroll_zone">20dp</dimen>
+
+    <!-- When dragging items on the workspace, the number of dps by which the position of
+     the drag view should be offset from the position of the original view. -->
+    <dimen name="dragViewOffsetX">0dp</dimen>
+    <dimen name="dragViewOffsetY">0dp</dimen>
+    <!--  When dragging an item, how much bigger (fixed dps) the dragged view
+          should be. If 0, it will not be scaled at all. -->
+    <dimen name="dragViewScale">12dp</dimen>
+
+    <!-- Padding applied to AppWidget previews -->
+    <dimen name="app_widget_preview_padding_left">16dp</dimen>
+    <dimen name="app_widget_preview_padding_right">16dp</dimen>
+    <dimen name="app_widget_preview_padding_top">32dp</dimen>
+    <dimen name="app_widget_preview_label_margin_top">4dp</dimen>
+    <dimen name="app_widget_preview_label_margin_left">2dp</dimen>
+    <dimen name="app_widget_preview_label_margin_right">2dp</dimen>
+
+    <!-- Padding applied to shortcut previews -->
+    <dimen name="shortcut_preview_padding_left">0dp</dimen>
+    <dimen name="shortcut_preview_padding_right">0dp</dimen>
+    <dimen name="shortcut_preview_padding_top">0dp</dimen>
+
+<!-- Folders -->
+    <!-- The size of the image which sits behind the preview of the folder contents -->
+    <dimen name="folder_preview_size">62dp</dimen>
+    <!-- The amount that the preview contents are inset from the preview background -->
+    <dimen name="folder_preview_padding">4dp</dimen>
+    <dimen name="folder_name_padding">10dp</dimen>
+    <dimen name="folder_width_gap">0dp</dimen>
+    <dimen name="folder_height_gap">0dp</dimen>
+    <dimen name="folder_padding">0dp</dimen>
+
+<!-- CellLayout padding -->
+    <dimen name="cell_layout_left_padding_port">0dp</dimen>
+    <dimen name="cell_layout_left_padding_land">0dp</dimen>
+    <dimen name="cell_layout_right_padding_port">0dp</dimen>
+    <dimen name="cell_layout_right_padding_land">0dp</dimen>
+    <dimen name="cell_layout_top_padding_port">0dp</dimen>
+    <dimen name="cell_layout_top_padding_land">0dp</dimen>
+    <dimen name="cell_layout_bottom_padding_port">0dp</dimen>
+    <dimen name="cell_layout_bottom_padding_land">0dp</dimen>
+
+<!-- Workspace padding -->
+    <dimen name="workspace_left_padding_port">0dp</dimen>
+    <dimen name="workspace_left_padding_land">0dp</dimen>
+    <dimen name="workspace_right_padding_port">0dp</dimen>
+    <dimen name="workspace_right_padding_land">0dp</dimen>
+    <dimen name="workspace_top_padding_port">0dp</dimen>
+    <dimen name="workspace_top_padding_land">0dp</dimen>
+    <dimen name="workspace_bottom_padding_port">0dp</dimen>
+    <dimen name="workspace_bottom_padding_land">0dp</dimen>
+
+<!-- Workspace cell size -->
+    <dimen name="workspace_cell_width_land">106dp</dimen>
+    <dimen name="workspace_cell_width_port">90dp</dimen>
+    <dimen name="workspace_cell_height_land">74dp</dimen>
+    <dimen name="workspace_cell_height_port">102dp</dimen>
+    <dimen name="workspace_width_gap_land">0dp</dimen>
+    <dimen name="workspace_width_gap_port">0dp</dimen>
+    <dimen name="workspace_height_gap_land">0dp</dimen>
+    <dimen name="workspace_height_gap_port">0dp</dimen>
+    
+<!-- EdgeSwipe -->
+	<dimen name="edge_swipe_show_limit">15dp</dimen>
+<!-- 	<dimen name="edge_swipe_up_limit">250dp</dimen> -->
+<!-- 	<dimen name="edge_swipe_down_limit">210dp</dimen> -->
+
+<!-- Edge swipe Radius Menu -->
+	<dimen name="edge_swipe_menu_radius">180dp</dimen>
+
+<!-- EdgeSwipe deadzones-->
+	<dimen name="edge_swipe_inner_deadzone">75dp</dimen>
+	<dimen name="edge_swipe_outer_deadzone">145dp</dimen>
+	
+</resources>
diff --git a/FairphoneHome/res/values/extra_wallpapers.xml b/FairphoneHome/res/values/extra_wallpapers.xml
new file mode 100644
index 0000000..9e0951c
--- /dev/null
+++ b/FairphoneHome/res/values/extra_wallpapers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ -->
+
+<resources>
+    <string-array name="extra_wallpapers">
+    </string-array>
+</resources>
diff --git a/FairphoneHome/res/values/strings.xml b/FairphoneHome/res/values/strings.xml
new file mode 100644
index 0000000..7cb728f
--- /dev/null
+++ b/FairphoneHome/res/values/strings.xml
@@ -0,0 +1,420 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- General -->
+    <skip />
+    <!-- Application name -->
+    <string name="application_name">Fairphone OS</string>
+    <!-- AppSwitcher Widget  name -->
+    <string name="app_switcher_name">Your apps</string>
+    <!-- AppSwitcher Widget  name -->
+    <string name="app_switcher_dialog_name">YourAppsDialog</string>  
+    <!-- Accessibility-facing application name -->
+    <string name="home">Home</string>
+    <!-- Name for all applications running as this uid. -->
+    <string name="uid_name">Android Core Apps</string>
+    <!-- Default folder name -->
+    <string name="folder_name"></string>
+    <!-- Title of dialog that appears after user selects Wallpaper from menu -->
+    <string name="chooser_wallpaper">Choose wallpaper from</string>
+    <!-- Button label on Wallpaper Gallery screen; user selects this button to set a specific wallpaper -->
+    <string name="wallpaper_instructions">Set wallpaper</string>
+    <!-- Option in "Select wallpaper from" dialog box -->
+    <string name="pick_wallpaper">Wallpapers</string>
+    <!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none] -->
+    <string name="activity_not_found">App isn\'t installed.</string>
+    <!-- Labels for the tabs in the customize drawer -->
+    <string name="widgets_tab_label">Widgets</string>
+
+    <!-- AppsCustomize pane -->
+    <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
+    <string name="long_press_widget_to_add">Touch &amp; hold to pick up a widget.</string>
+    <!--
+         Market button text.  The market button text is removed in Launcher.java 
+         in the Phone UI. [CHAR LIMIT=32]
+    -->
+    <string name="market">Shop</string>
+    <!-- The format string for the dimensions of a widget in the drawer -->
+    <string name="widget_dims_format" translatable="false">%1$d x %2$d</string>
+
+    <!-- External-drop widget pick label format string [CHAR_LIMIT=25] -->
+    <string name="external_drop_widget_pick_format" translatable="false">%1$s (%2$d x %3$d)</string>
+    <!--
+         External-drop widget error string.  This is the error that is shown
+         when you drag and item into the homescreen and it is unable to fit,
+         or an error is encountered. [CHAR_LIMIT=50]
+    -->
+    <string name="external_drop_widget_error">Couldn\'t drop item on this Home screen.</string>
+    <!--
+         External-drop widget pick title.  This is shown as the title of the
+         dialog which allows you to pick which widgets to handle a particular
+         drop if there are multiple choices. [CHAR_LIMIT=35]
+    -->
+    <string name="external_drop_widget_pick_title">Choose widget to create</string>
+
+    <!-- Folders -->
+    <skip />
+    <!-- Label of Folder name field in Rename folder dialog box -->
+    <string name="rename_folder_label">Folder name</string>
+    <!-- Title of dialog box -->
+    <string name="rename_folder_title">Rename folder</string>
+    <!-- Buttons in Rename folder dialog box -->
+    <string name="rename_action">OK</string>
+    <!-- Buttons in Rename folder dialog box -->
+    <string name="cancel_action">Cancel</string>
+
+    <!-- Shortcuts -->
+    <skip />
+    <!-- Title of dialog box -->
+    <string name="menu_item_add_item">Add to Home screen</string>
+    <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all apps -->
+    <string name="group_applications">Apps</string>
+    <!--
+Options in "Add to Home" dialog box; Title of the group containing the list of all shortcut
+s
+    -->
+    <string name="group_shortcuts">Shortcuts</string>
+    <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all widgets/gadgets -->
+    <string name="group_widgets">Widgets</string>
+    <!-- Options in "Add to Home" dialog box; Title of the group containing the list of apps that can set the wallpaper -->
+    <string name="group_wallpapers">Wallpapers</string>
+    <!-- TODO - FP edit favorites -->
+    <string name="menu_edit_favorites">Edit favorites</string>
+    <string name="menu_show_OOBE">Tutorial</string>
+    <string name="menu_change_edge_swipe">Change menu</string>
+    <string name="menu_home_settings">Home Settings</string>
+    
+    <!-- Error message when user has filled all their home screens -->
+    <string name="completely_out_of_space">No more room on your Home screens.</string>
+    <!-- Error message when user has filled a home screen -->
+    <string name="out_of_space">No more room on this Home screen.</string>
+    <!-- Error message when user has filled the hotseat -->
+    <string name="hotseat_out_of_space">No more room on the hotseat.</string>
+    <!-- Error message when user tries to drop an invalid item on the hotseat -->
+    <string name="invalid_hotseat_item">This widget is too large for the hotseat.</string>
+    <!-- Message displayed when a shortcut is created by an external application -->
+    <string name="shortcut_installed">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" created.</string>
+    <!-- Message displayed when a shortcut is uninstalled by an external application -->
+    <string name="shortcut_uninstalled">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" was removed.</string>
+    <!-- Message displayed when an external application attemps to create a shortcut that already exists -->
+    <string name="shortcut_duplicate">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" already exists.</string>
+
+    <!-- Title of dialog when user is selecting shortcut to add to homescreen -->
+    <string name="title_select_shortcut">Choose shortcut</string>
+    <!-- Title of dialog when user is selecting an application to add to homescreen -->
+    <string name="title_select_application">Choose app</string>
+
+    <!-- All applications label -->
+    <string name="all_apps_button_label">Apps</string>
+    <!--
+         Label for button in all applications label to go back home (to the workspace / desktop)
+         for accessibilty (spoken when the button gets focus).
+    -->
+    <string name="all_apps_home_button_label">Home</string>
+    <!--
+         Label for trash icon on workspace. Meant to communicate the idea of removing the
+         icon/widget from the home screen, but not permanently. [CHAR_LIMIT=30]
+    -->
+    <string name="delete_zone_label_workspace">Remove</string>
+    <!--
+         Label for trash icon in All Apps. The icon/widget will become completely unavailable on the
+         device. [CHAR_LIMIT=30]
+    -->
+    <string name="delete_zone_label_all_apps">Uninstall</string>
+
+    <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+    <string name="delete_target_label">Remove</string>
+    <!-- Label for uninstall drop target. [CHAR_LIMIT=30] -->
+    <string name="delete_target_uninstall_label">Uninstall</string>
+    <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+    <string name="info_target_label">App info</string>
+
+    <!-- Accessibility: Search button -->
+    <string name="accessibility_search_button">Search</string>
+    <!-- Accessibility: Voice Search button -->
+    <string name="accessibility_voice_search_button">Voice Search</string>
+    <!-- Accessibility: AllApps button -->
+    <string name="accessibility_all_apps_button">Apps</string>
+    <!-- Accessibility: Delete button -->
+    <string name="accessibility_delete_button">Remove</string>
+
+    <!--
+         Label for trash icon in All Apps, when an updated system app is selected. The update will
+         be uninstalled. [CHAR_LIMIT=30]
+    -->
+    <string name="delete_zone_label_all_apps_system_app">Uninstall update</string>
+
+    <!-- Menus items: -->
+    <skip />
+    <!-- Verb, menu item used to add an item on the desktop -->
+    <string name="menu_add">Add</string>
+    <!-- Menu item used to manage installed applications -->
+    <string name="menu_manage_apps">Manage apps</string>
+    <!-- Noun, menu item used to set the desktop's wallpaper -->
+    <string name="menu_wallpaper">Wallpaper</string>
+    <!-- Verb, menu item used to initiate global search -->
+    <string name="menu_search">Search</string>
+    <!-- Noun, menu item used to bring down the notifications shade -->
+    <string name="menu_notifications">Notifications</string>
+    <!-- Noun, menu item used to show the system settings -->
+    <string name="menu_settings">System settings</string>
+    <!-- Noun, menu item used to show help. [CHAR_LIMIT=none] -->
+    <string name="menu_help">Help</string>
+
+    <!-- URL pointing to help text. If empty, no link to help will be created [DO NOT TRANSLATE] -->
+    <string name="help_url" translatable="false"></string>
+
+    <!-- Strings for the contextual action bar (CAB) in All Apps -->
+    <skip />
+    <!--
+         Describes the button for uninstalling the currently selected application.
+         Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none]
+    -->
+    <string name="cab_menu_delete_app">Uninstall app</string>
+    <!--
+         Describes the button for getting details/info about currently selected application.
+         Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none]
+    -->
+    <string name="cab_menu_app_info">App details</string>
+    <!-- Appears in the CAB when an app is selected in All Apps or Customize mode. [CHAR_LIMIT=50] -->
+    <string name="cab_app_selection_text">1 app selected</string>
+    <!-- Appears in the CAB when a widget is selected in Customize mode. [CHAR_LIMIT=50] -->
+    <string name="cab_widget_selection_text">1 widget selected</string>
+    <!-- Appears in the CAB when a folder is selected in Customize mode. [CHAR_LIMIT=50] -->
+    <string name="cab_folder_selection_text">1 folder selected</string>
+    <!-- Appears in the CAB when a shortcut is selected in Customize mode. [CHAR_LIMIT=50] -->
+    <string name="cab_shortcut_selection_text">1 shortcut selected</string>
+
+    <!-- Permissions: -->
+    <skip />
+    <!-- Permission short label -->
+    <string name="permlab_install_shortcut">install shortcuts</string>
+    <!-- Permission description -->
+    <string name="permdesc_install_shortcut">Allows an app to add
+        shortcuts without user intervention.</string>
+    <!-- Permission short label -->
+    <string name="permlab_uninstall_shortcut">uninstall shortcuts</string>
+    <!-- Permission description -->
+    <string name="permdesc_uninstall_shortcut">Allows the app to remove
+        shortcuts without user intervention.</string>
+    <!-- Permission short label -->
+    <string name="permlab_read_settings">read Home settings and shortcuts</string>
+    <!-- Permission description -->
+    <string name="permdesc_read_settings">Allows the app to read the settings and
+        shortcuts in Home.</string>
+    <!-- Permission short label -->
+    <string name="permlab_write_settings">write Home settings and shortcuts</string>
+    <!-- Permission description -->
+    <string name="permdesc_write_settings">Allows the app to change the settings and
+        shortcuts in Home.</string>
+
+    <!-- Widgets: -->
+    <skip />
+
+    <!-- Text to show user in place of a gadget when we can't display it properly -->
+    <string name="gadget_error_text">Problem loading widget</string>
+
+    <!-- Text to inform the user that they can't uninstall a system application -->
+    <string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
+
+    <!-- Title of the Android Dreams (screensaver) module -->
+    <string name="dream_name">Rocket Launcher</string>
+
+    <!-- Default folder title -->
+    <string name="folder_hint_text">Unnamed Folder</string>
+
+    <!-- Accessibility -->
+    <skip />
+
+    <!-- The format string for Workspace descriptions [CHAR_LIMIT=none] -->
+    <string name="workspace_description_format">Home screen %1$d</string>
+
+    <!-- The format string for default page scroll text [CHAR_LIMIT=none] -->
+    <string name="default_scroll_format">Page %1$d of %2$d</string>
+    <!-- The format string for Workspace page scroll text [CHAR_LIMIT=none] -->
+    <string name="workspace_scroll_format">Home screen %1$d of %2$d</string>
+    <!-- The format string for AppsCustomize Apps page scroll text [CHAR_LIMIT=none] -->
+    <string name="apps_customize_apps_scroll_format">Apps page %1$d of %2$d</string>
+    <!-- The format string for AppsCustomize Apps page scroll text [CHAR_LIMIT=none] -->
+    <string name="apps_customize_widgets_scroll_format">Widgets page %1$d of %2$d</string>
+
+    <!-- Clings -->
+    <!-- The title text for the workspace cling [CHAR_LIMIT=none] -->
+    <string name="workspace_cling_title">Make yourself at home</string>
+    <!-- The description of how to use the workspace [CHAR_LIMIT=none] -->
+    <string name="workspace_cling_move_item">You can put your favorite apps here.</string>
+    <!-- The description of how to open all apps from the workspace [CHAR_LIMIT=none] -->
+    <string name="workspace_cling_open_all_apps">To see all your apps, touch the circle.</string>
+    <!-- The title text for the All Apps cling [CHAR_LIMIT=none] -->
+    <string name="all_apps_cling_title">Choose some apps</string>
+    <!-- The description of how to pick up and add an item to the workspace [CHAR_LIMIT=none] -->
+    <string name="all_apps_cling_add_item">To add an app to your Home screen, touch &amp; hold it.</string>
+    <!-- The title text for the Folder cling [CHAR_LIMIT=none] -->
+    <string name="folder_cling_title">Organize your apps with folders</string>
+    <!-- The description of how to move an app [CHAR_LIMIT=none] -->
+    <string name="folder_cling_move_item">To move an app, touch &amp; hold it.</string>
+    <!-- The description of how to create a folder [CHAR_LIMIT=none] -->
+    <string name="folder_cling_create_folder">To make a new folder on your Home screen, stack one app on top of another.</string>
+    <!-- The text on the button to dismiss a cling [CHAR_LIMIT=none] -->
+    <string name="cling_dismiss">OK</string>
+    <!-- Error message on dummy custom cling layout [DO NOT TRANSLATE] -->
+    <string name="dummy_custom_cling_error_message">Error: custom workspace layout passed in but custom cling was not overwritten</string>
+
+    <add-resource name="default_folder_name" type="string" />
+
+    <!-- Folder accessibility -->
+    <!-- The format string for when a folder is opened, speaks the dimensions -->
+    <string name="folder_opened">Folder opened, <xliff:g id="width" example="5">%1$d</xliff:g> by <xliff:g id="height" example="3">%2$d</xliff:g></string>
+    <!-- Instruction that clicking outside will close folder -->
+    <string name="folder_tap_to_close">Touch to close folder</string>
+    <!-- Instruction that clicking outside will commit folder rename -->
+    <string name="folder_tap_to_rename">Touch to save rename</string>
+    <!-- Indication that folder closed -->
+    <string name="folder_closed">Folder closed</string>
+    <!-- Folder renamed format -->
+    <string name="folder_renamed">Folder renamed to <xliff:g id="name" example="Games">%1$s</xliff:g></string>
+    <!-- Folder name format -->
+    <string name="folder_name_format">Folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
+
+    <!-- Strings used in device overlays -->
+
+
+    <!-- Clings -->
+    <!-- Dummy string [CHAR_LIMIT=40] -->
+    <string name="custom_workspace_cling_title_1"></string>
+    <!-- Dummy string [CHAR_LIMIT=60] -->
+    <string name="custom_workspace_cling_description_1"></string>
+    <!-- Dummy string [CHAR_LIMIT=40] -->
+    <string name="custom_workspace_cling_title_2"></string>
+    <!-- Dummy string [CHAR_LIMIT=60] -->
+    <string name="custom_workspace_cling_description_2"></string>
+
+    <!-- Default image description -->
+    <string name="image_desc">Default image descrition</string>
+
+    <!-- Fairphone -->
+    
+    <!-- Your Apps -->
+    <string name="your_apps">Your Apps</string>
+    
+    <string name="last_used_apps">Last\nused\napps</string>
+    <string name="last_used">Last used</string>
+    <string name="most_used_apps">Most\nused\napps</string>
+    <string name="most_used">Most used</string>
+    <string name="no_apps_have_been_opened_yet">No apps opened yet? Just start using your phone and come back to this screen</string>
+    <string name="last_used_oobe">You can see the last apps you have used</string>
+    <string name="most_used_oobe">And your phone learns from you, it will remember your most used apps</string>
+    <string name="reset">Reset</string>
+    <string name="app_switcher_reset_message">Are you sure?</string>
+    
+    <!-- Quick Access -->
+    <string name="quick_access">Quick Access</string>
+    <string name="edit">Edit</string>
+    <string name="favourite_apps">Favourite apps</string>
+    <string name="drag_here_to_add">Drag\nhere\nto add</string>
+    <string name="drag_here_to_remove">Drag\nhere to\nremove</string>
+
+    <!-- Settings -->
+    <string name="energy_mood">Energy Mood on lock screen</string>
+    <string name="energy_mood_summary">Display battery level as background color on lock screen</string>
+    
+    <string name="menu_change_edge_swipe_change_to">Changed to</string>
+	<string name="menu_change_edge_swipe_normal">normal menu</string>
+	<string name="menu_change_edge_swipe_alternative">alternative menu</string>
+	<string name="oobeVideoSkipButtonText">skip</string>
+	
+	<!-- Preferences -->
+	<string name="pref_mood_changer_title">Mood Changer</string>
+	<string name="pref_edge_swipe_title">Edge Swipe</string>
+	<string name="pref_edge_swipe_safe_zone">Enable safe zone</string>
+	<string name="pref_edge_swipe_safe_zone_summ">Enabling makes Edge Swipe menu not go out of top or bottom</string>
+	<string name="pref_show_mood_changer_on_lockscreen_summary">Enable Mood Changer on lockscreen, this will display the battery level as a background colour on the lockscreen</string>
+	<string name="pref_show_mood_changer_on_lockscreen">Mood Changer on lockscreen</string>
+	
+	<string name="pref_show_mood_changer_on_homescreen_summary">Enable Mood Changer on homescreen, this will display the battery level as a background colour on the homescreen</string>
+	<string name="pref_show_mood_changer_on_homescreen">Mood Changer on homescreen</string>
+	
+	<string name="pref_is_mood_changer_solid_summary">Is Mood changer solid</string>
+	<string name="pref_is_mood_changer_solid">Solid Mood</string>
+	
+	<!-- OOBE Texts -->
+	<string name="oobe_quick_access">Quick Access</string>
+	
+	<string name="oobe_select_language">Select\nLanguage</string>
+	<string name="oobe_setup_wifi">Setup\nWi-Fi</string>
+	<string name="oobe_intro_top">Welcome!\nYou hold in your hands a phone built in a way that puts social values first. But yes, it makes phone calls, too.</string>
+	<string name="oobe_intro_bottom">Let\'s show you how to use it</string>
+	
+	<string name="oobe_edge_swipe_title">Swipe from left or right</string>
+	<string name="oobe_edge_swipe_text">Without releasing your finger</string>
+	
+	<string name="oobe_open_app_title">Release your finger</string>
+	<string name="oobe_open_app_text">On top of an app to open it</string>
+	
+	<string name="oobe_edit_drag_intro">Apps can be dragged and dropped making them easy to edit</string>
+	<string name="oobe_edit_drag_add_title">Drag and drop</string>
+	<string name="oobe_edit_drag_add_text">To right column to add to favorites</string>
+	
+	<string name="oobe_edit_drag_remove_title">Drag and drop</string>
+	<string name="oobe_edit_drag_remove_text">To left column to remove from favorites</string>
+	
+	<string name="oobe_edit_drag_trade_title">Drag favorites</string>
+	<string name="oobe_edit_drag_trade_text">To swap position</string>
+	
+	<string name="oobe_your_apps_intro">Your most used apps all in one place</string>
+	<string name="oobe_your_apps_learning">Your phone learns from you and will remember your most used apps</string>
+	<string name="oobe_your_apps_last_ones">You can also see the last ones you\'ve used</string>
+	<string name="oobe_your_apps_start_using">Start using your phone, the apps will be waiting here for you</string>
+	
+	<string name="oobe_start">Start</string>
+	<string name="oobe_back">Back</string>
+	<string name="oobe_skip">Skip</string>
+	<string name="oobe_next">Next</string>
+	<string name="oobe_done">Done</string>
+	
+	<!-- Google Apps Install Widget -->
+    <string name="google_apps_installer_name">Google Apps Installer</string>
+	<string name="google_apps_initial_title">Install\nGoogle Apps</string>
+	<string name="google_apps_disclaimer_title">Install Google Apps</string>
+	<string name="google_apps_disclaimer_description">For the full Android and Google mobile experience like the Google Play store, your phone needs extra content and software. Unfortunately, as Fairphone doesn\'t have a license yet, we cannot pre-install this content, nor can we provide it directly ourselves. We are working with the content owner to achieve this.\nPress "I Agree" below to download this content from an external secured source. Installing this content is your own responsibility.\nIf you do not agree, your phone will still work with basic Android apps, of course, but you will miss some services from Google.</string>
+	<string name="google_apps_disclaimer_agree">I Agree</string>
+	<string name="google_apps_denied_permissions_title">Denied permissions</string>
+	<string name="google_apps_denied_permissions_description">Fairphone OS could not obtain the necessary permissions to install Google Apps. If you chose DENY, please restart the installer and ALLOW permissions.</string>
+	<string name="google_apps_reboot_failed_title">Failed reboot</string>
+	<string name="google_apps_reboot_failed_description">Google Apps are installed. Could not reboot device, please reboot manually.</string>
+	<string name="google_apps_download_title">Downloading Google Apps</string>
+	<string name="google_apps_unzip_title">Extracting Google Apps</string>
+	<string name="google_apps_install_title">Installing Google Apps</string>
+	<string name="google_apps_reboot_title">Rebooting device</string>
+	<string name="google_apps_permissions_description">Fairphone OS will now ask you for Superuser access. We assure you it\’s perfectly safe. Please choose ALLOW when asked.</string>
+	<string name="google_apps_permissions_title">System permissions</string>
+	<string name="google_apps_reboot_description">The system needs to reboot to complete the installation.\n\nAfter the reboot, follow the steps to set up Google Apps.</string>
+	<string name="google_apps_uninstall_title">Google Apps installed</string>
+	<string name="google_apps_uninstall_description">Delete this\nInstaller</string>
+	<string name="google_apps_failed_download_title">Download failed</string>
+	<string name="google_apps_failed_download_description">Downloaded files are corrupted. Retry?</string>
+	<string name="google_apps_download_error">Error downloading files, please try again.</string>
+	<string name="google_apps_connection_title">Wi-Fi disabled</string>
+	<string name="google_apps_connection_description">The file you’re trying to download is too large for mobile connections (~100MB). Please enable Wi-Fi connection and try again.</string>
+	<string name="updatingSystem">Updating System #8230;</string>
+	
+	
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values/styles.xml b/FairphoneHome/res/values/styles.xml
new file mode 100644
index 0000000..5b92dbe
--- /dev/null
+++ b/FairphoneHome/res/values/styles.xml
@@ -0,0 +1,350 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="Theme.WallpaperPicker" parent="@android:style/Theme.Holo.NoActionBar"></style>
+
+    <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar"></style>
+
+    <style name="ClingButton">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:paddingTop">10dp</item>
+        <item name="android:paddingBottom">15dp</item>
+        <item name="android:paddingLeft">35dp</item>
+        <item name="android:paddingRight">35dp</item>
+        <item name="android:text">@string/cling_dismiss</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:background">@drawable/cling_button_bg</item>
+    </style>
+
+    <style name="ClingTitleText">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginBottom">5dp</item>
+        <item name="android:textSize">23sp</item>
+        <item name="android:textColor">#49C0EC</item>
+        <item name="android:shadowColor">#000000</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2.0</item>
+    </style>
+
+    <style name="ClingText">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:textSize">15sp</item>
+        <item name="android:textColor">#FFFFFF</item>
+        <item name="android:shadowColor">#000000</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2.0</item>
+        <item name="android:lineSpacingMultiplier">1.1</item>
+    </style>
+
+    <style name="WorkspaceIcon">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">marquee</item>
+        <item name="android:textSize">@dimen/workspace_icon_text_size</item>
+        <item name="android:textColor">@color/workspace_icon_text_color</item>
+        <item name="android:shadowRadius">2.0</item>
+        <item name="android:shadowColor">#B0000000</item>
+    </style>
+
+    <style name="WorkspaceIcon.Portrait">
+        <item name="android:drawablePadding">@dimen/app_icon_drawable_padding</item>
+        <item name="android:paddingLeft">4dp</item>
+        <item name="android:paddingRight">4dp</item>
+        <item name="android:paddingTop">@dimen/app_icon_padding_top</item>
+        <item name="android:paddingBottom">4dp</item>
+    </style>
+
+    <style name="WorkspaceIcon.Landscape">
+        <item name="android:drawablePadding">@dimen/app_icon_drawable_padding_land</item>
+        <item name="android:paddingLeft">4dp</item>
+        <item name="android:paddingRight">4dp</item>
+        <item name="android:paddingTop">@dimen/app_icon_padding_top</item>
+        <item name="android:paddingBottom">4dp</item>
+    </style>
+
+    <style name="WorkspaceIcon.Portrait.Folder">
+        <item name="android:drawablePadding">0dp</item>
+        <item name="android:paddingTop">@dimen/folder_icon_padding_top</item>
+    </style>
+
+    <style name="WorkspaceIcon.Landscape.Folder">
+        <item name="android:drawablePadding">0dp</item>
+        <item name="android:paddingTop">0dp</item>
+        <item name="android:layout_marginTop">-2dp</item>
+    </style>
+
+    <style name="WorkspaceIcon.Portrait.AppsCustomize">
+        <item name="android:singleLine">false</item>
+        <item name="android:maxLines">2</item>
+        <item name="android:background">@null</item>
+        <item name="android:paddingTop">0dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:paddingLeft">0dp</item>
+        <item name="android:paddingRight">0dp</item>
+        <item name="android:drawablePadding">2dp</item>
+    </style>
+
+    <style name="WorkspaceIcon.Landscape.AppsCustomize">
+        <item name="android:background">@null</item>
+        <item name="android:paddingTop">4dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:drawablePadding">6dp</item>
+    </style>
+
+    <style name="QSBBar">
+        <item name="android:orientation">horizontal</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">@dimen/qsb_bar_height</item>
+        <item name="android:layout_gravity">top|center_horizontal</item>
+        <item name="android:paddingLeft">@dimen/qsb_padding_left</item>
+        <item name="android:paddingRight">@dimen/qsb_padding_right</item>
+    </style>
+
+    <style name="SearchDropTargetBar">
+        <item name="android:orientation">horizontal</item>
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">bottom|center_horizontal</item>
+    </style>
+
+    <style name="SearchButton">
+        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+    </style>
+
+    <style name="DropTargetButtonContainer">
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_height">match_parent</item>
+    </style>
+
+    <style name="DropTargetButton">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:drawablePadding">7.5dp</item>
+        <item name="android:paddingLeft">25dp</item>
+        <item name="android:paddingRight">25dp</item>
+        <item name="android:textColor">#FFFFFFFF</item>
+        <item name="android:textSize">16sp</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">end</item>
+        <item name="android:shadowColor">#FF000000</item>
+        <item name="android:shadowDx">0.0</item>
+        <item name="android:shadowDy">1.0</item>
+        <item name="android:shadowRadius">4.0</item>
+    </style>
+
+    <style name="TabIndicator">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:gravity">center</item>
+        <item name="android:paddingLeft">20dp</item>
+        <item name="android:paddingRight">20dp</item>
+        <item name="android:background">@drawable/tab_widget_indicator_selector</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textSize">12sp</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">end</item>
+    </style>
+
+    <style name="TabIndicator.AppsCustomize">
+        <!-- Overridden in values-land -->
+    </style>
+
+    <style name="MarketButton">
+        <item name="android:paddingLeft">5dp</item>
+        <item name="android:paddingRight">5dp</item>
+        <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
+        <item name="android:shadowDx">0.0</item>
+        <item name="android:shadowDy">0.0</item>
+        <item name="android:shadowRadius">2.0</item>
+    </style>
+
+    <!-- Overridden in device overlays -->
+    <style name="CustomClingTitleText"></style>
+
+    <style name="CustomClingText"></style>
+
+    <!-- Button styles -->
+    <style name="AppSwitcherButtonReset">
+        <item name="android:textColor">@color/button_app_switcher_reset_text</item>
+        <item name="android:background">@drawable/button_app_switcher_reset</item>
+        <item name="android:textSize">13.5sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:paddingLeft">10dp</item>
+        <item name="android:paddingRight">10dp</item>
+        <item name="android:paddingTop">0dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:includeFontPadding">false</item>
+    </style>
+
+    <style name="OOBEButton">
+        <item name="android:textSize">22sp</item>
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowColor">@color/white</item>
+        <item name="android:padding">15dp</item>
+        <item name="android:shadowDx">0.5</item>
+        <item name="android:shadowDy">0.5</item>
+        <item name="android:shadowRadius">0.01</item>
+        <item name="android:background">@color/transparent</item>
+    </style>
+
+    <!-- Text styles -->
+    <style name="MainTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">40sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-10dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="SecondaryMainTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">21sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="SubTitle">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">16sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="MainText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">11sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+    </style>
+
+    <style name="IconText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">12sp</item>
+        <item name="android:textAllCaps">false</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lines">2</item>
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="BigIconText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">17sp</item>
+        <item name="android:textAllCaps">false</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:gravity">center_vertical|left</item>
+        <item name="android:maxLines">2</item>
+    </style>
+
+    <style name="SwipeMenuEditText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:gravity">left</item>
+        <item name="android:maxLines">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">30sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:lineSpacingExtra">-7dp</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="AppSwitcherOOBEDescriptionText">
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textSize">13sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:includeFontPadding">false</item>
+        <item name="android:shadowColor">#33000000</item>
+        <item name="android:shadowDx">1</item>
+        <item name="android:shadowDy">1</item>
+        <item name="android:shadowRadius">1</item>
+    </style>
+
+    <style name="OOBETheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowIsTranslucent">true</item>
+    </style>
+
+    <style name="OOBETitle">
+        <item name="android:textSize">32sp</item>
+        <item name="android:textColor">@color/white</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:lineSpacingExtra">10dp</item>
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:shadowColor">#FFF</item>
+        <item name="android:shadowDx">0.5</item>
+        <item name="android:shadowDy">0.5</item>
+        <item name="android:shadowRadius">0.01</item>
+    </style>
+
+    <style name="OOBEText" parent="@style/OOBETitle">
+        <item name="android:textColor">#dcdcdc</item>
+        <item name="android:shadowColor">#dcdcdc</item>
+    </style>
+
+    <style name="OOBETitleBig" parent="@style/OOBETitle">
+        <item name="android:textSize">45sp</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphoneHome/res/values/wallpapers.xml b/FairphoneHome/res/values/wallpapers.xml
new file mode 100644
index 0000000..4b8e7a3
--- /dev/null
+++ b/FairphoneHome/res/values/wallpapers.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ -->
+
+<resources>
+    <string-array name="wallpapers" translatable="false">
+        <item>fp_wallpaper_company</item>
+        <item>fp_wallpaper_crystal_1</item>
+        <item>fp_wallpaper_crystal_2</item>
+        <item>fp_wallpaper_crystal_3</item>
+        <item>fp_wallpaper_crystal_4</item>
+        <item>fp_wallpaper_crystal_5</item>
+        <item>fp_wallpaper_crystal_6</item>
+        <item>fp_wallpaper_default</item>
+        <item>fp_wallpaper_crystal_1_blue</item>
+        <item>fp_wallpaper_crystal_1_pink</item>
+        <item>fp_wallpaper_crystal_4_blue</item>
+        <item>fp_wallpaper_crystal_4_pink</item>
+        <item>fp_wallpaper_crystal_5_blue</item>
+        <item>fp_wallpaper_crystal_5_pink</item>
+        <item>fp_wallpaper_mine_5_blue</item>
+        <item>fp_wallpaper_sun_1_pink</item>
+        <item>fp_wallpaper_sun_4_pink</item>
+        <item>fp_wallpaper_sun_1</item>
+        <item>fp_wallpaper_sun_2</item>
+        <item>fp_wallpaper_sun_3</item>
+        <item>fp_wallpaper_sun_4</item>
+        <item>fp_wallpaper_sun_5</item>
+    </string-array>
+</resources>
diff --git a/FairphoneHome/res/xml/default_workspace.xml b/FairphoneHome/res/xml/default_workspace.xml
new file mode 100644
index 0000000..5ff0aba
--- /dev/null
+++ b/FairphoneHome/res/xml/default_workspace.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher">
+    <!-- Far-left screen [0] -->
+
+    <!-- Left screen [1] -->
+    <appwidget
+        launcher:packageName="com.android.deskclock"
+        launcher:className="com.android.alarmclock.DigitalAppWidgetProvider"
+        launcher:screen="1"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="4"
+        launcher:spanY="3" />
+    <!-- 
+     <favorite
+        launcher:packageName="com.android.settings"
+        launcher:className="com.android.settings.Settings"
+        launcher:screen="1"
+        launcher:x="2"
+        launcher:y="4" />
+     -->
+     <!-- Middle screen [2] -->
+   
+     <appwidget
+        launcher:packageName="org.fairphone.fairphonepeaceofmindapp"
+        launcher:className="org.fairphone.peaceofmind.widget.WidgetProvider"
+        launcher:screen="2"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="4"
+        launcher:spanY="3" />
+     
+     <appwidget
+        launcher:packageName="org.fairphone.launcher"
+        launcher:className="org.fairphone.widgets.gapps.GoogleAppsInstallerWidget"
+        launcher:screen="2"
+        launcher:x="0"
+        launcher:y="3"
+        launcher:spanX="4"
+        launcher:spanY="3" />
+
+    <!-- Right screen [3] -->
+    
+       <appwidget
+        launcher:packageName="org.fairphone.launcher"
+        launcher:className="org.fairphone.widgets.appswitcher.WidgetProvider"
+        launcher:screen="3"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:spanX="4"
+        launcher:spanY="6" />
+
+    <!-- Far-right screen [4] -->
+	
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    
+    <favorite
+        launcher:packageName="com.android.contacts"
+        launcher:className="com.android.contacts.activities.DialtactsActivity"
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.android.contacts"
+        launcher:className="com.android.contacts.activities.PeopleActivity"
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.android.mms"
+        launcher:className="com.android.mms.ui.ConversationList"
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.android.browser"
+        launcher:className="com.android.browser.BrowserActivity"
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" />
+</favorites>
diff --git a/FairphoneHome/res/xml/google_apps_widget.xml b/FairphoneHome/res/xml/google_apps_widget.xml
new file mode 100644
index 0000000..c67ec18
--- /dev/null
+++ b/FairphoneHome/res/xml/google_apps_widget.xml
@@ -0,0 +1,9 @@
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

+    android:autoAdvanceViewId="@+id/googleAppsInstaller"

+    android:initialLayout="@layout/fp_google_apps_installer_widget"

+    android:minHeight="200dp"

+    android:minWidth="300dp"

+    android:label="GAppsInstWidget"

+    android:previewImage="@drawable/fp_gapps_installer_icon"

+    android:resizeMode="horizontal|vertical"

+    android:updatePeriodMillis="0" />
\ No newline at end of file
diff --git a/FairphoneHome/res/xml/launcher_settings.xml b/FairphoneHome/res/xml/launcher_settings.xml
new file mode 100644
index 0000000..0d6a795
--- /dev/null
+++ b/FairphoneHome/res/xml/launcher_settings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <PreferenceCategory
+        android:key="pref_edge_swipe_settings"
+        android:title="@string/pref_edge_swipe_title" >
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="pref_edge_swipe_safe_zone"
+            android:summary="@string/pref_edge_swipe_safe_zone_summ"
+            android:title="@string/pref_edge_swipe_safe_zone" />
+    </PreferenceCategory>
+    <PreferenceCategory
+        android:key="pref_mood_changer_settings"
+        android:title="@string/pref_mood_changer_title" >
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="pref_show_mood_changer_on_lock_screen"
+            android:summary="@string/pref_show_mood_changer_on_lockscreen_summary"
+            android:title="@string/pref_show_mood_changer_on_lockscreen" />
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="pref_show_mood_changer_on_home_screen"
+            android:summary="@string/pref_show_mood_changer_on_homescreen_summary"
+            android:title="@string/pref_show_mood_changer_on_homescreen" />
+		<CheckBoxPreference
+            android:defaultValue="true"
+            android:key="pref_is_mood_changer_solid"
+            android:summary="@string/pref_is_mood_changer_solid_summary"
+            android:title="@string/pref_is_mood_changer_solid" />        
+        
+    </PreferenceCategory>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/FairphoneHome/res/xml/update_workspace.xml b/FairphoneHome/res/xml/update_workspace.xml
new file mode 100644
index 0000000..b9430d0
--- /dev/null
+++ b/FairphoneHome/res/xml/update_workspace.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/org.fairphone.launcher">
+    <!-- Update the db with new hotseat items.  Note that we reference the browser's original
+         package name. -->
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <favorite
+        launcher:packageName="com.android.contacts"
+        launcher:className="com.android.contacts.activities.DialtactsActivity"
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.android.contacts"
+        launcher:className="com.android.contacts.activities.PeopleActivity"
+        launcher:container="-101"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.android.mms"
+        launcher:className="com.android.mms.ui.ConversationList"
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.android.browser"
+        launcher:className="com.android.browser.BrowserActivity"
+        launcher:container="-101"
+        launcher:screen="4"
+        launcher:x="4"
+        launcher:y="0" />
+</favorites>
diff --git a/FairphoneHome/res/xml/wallpaper_picker_preview.xml b/FairphoneHome/res/xml/wallpaper_picker_preview.xml
new file mode 100644
index 0000000..3536a58
--- /dev/null
+++ b/FairphoneHome/res/xml/wallpaper_picker_preview.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<wallpaper-preview
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:staticWallpaperPreview="@drawable/wallpaper_gallery_background">    
+</wallpaper-preview>
+
+<!-- android:staticWallpaperPreview="@drawable/wallpaper_picker_preview" -->
\ No newline at end of file
diff --git a/FairphoneHome/res/xml/widget_provider.xml b/FairphoneHome/res/xml/widget_provider.xml
new file mode 100755
index 0000000..f22512e
--- /dev/null
+++ b/FairphoneHome/res/xml/widget_provider.xml
@@ -0,0 +1,9 @@
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoAdvanceViewId="@+id/appSwitcher"
+    android:initialLayout="@layout/fp_app_switcher"
+    android:minHeight="500dp"
+    android:minWidth="300dp"
+    android:label="AppWidget"
+    android:previewImage="@drawable/appswicther_widget_icon"
+    android:resizeMode="horizontal|vertical"
+    android:updatePeriodMillis="0" />
diff --git a/FairphoneHome/src/org/fairphone/launcher/AccessibleTabView.java b/FairphoneHome/src/org/fairphone/launcher/AccessibleTabView.java
new file mode 100644
index 0000000..7f8588e
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/AccessibleTabView.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.TextView;
+
+/**
+ * We use a custom tab view to process our own focus traversals.
+ */
+public class AccessibleTabView extends TextView {
+    public AccessibleTabView(Context context) {
+        super(context);
+    }
+
+    public AccessibleTabView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public AccessibleTabView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+                || super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+                || super.onKeyUp(keyCode, event);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/AddAdapter.java b/FairphoneHome/src/org/fairphone/launcher/AddAdapter.java
new file mode 100644
index 0000000..ef1fd7a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/AddAdapter.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.R;
+
+/**
+ * Adapter showing the types of items that can be added to a {@link Workspace}.
+ */
+public class AddAdapter extends BaseAdapter {
+
+    private final LayoutInflater mInflater;
+
+    private final ArrayList<ListItem> mItems = new ArrayList<ListItem>();
+
+    public static final int ITEM_SHORTCUT = 0;
+    public static final int ITEM_APPWIDGET = 1;
+    public static final int ITEM_APPLICATION = 2;
+    public static final int ITEM_WALLPAPER = 3;
+
+    /**
+     * Specific item in our list.
+     */
+    public class ListItem {
+        public final CharSequence text;
+        public final Drawable image;
+        public final int actionTag;
+
+        public ListItem(Resources res, int textResourceId, int imageResourceId, int actionTag) {
+            text = res.getString(textResourceId);
+            if (imageResourceId != -1) {
+                image = res.getDrawable(imageResourceId);
+            } else {
+                image = null;
+            }
+            this.actionTag = actionTag;
+        }
+    }
+    
+    public AddAdapter(Launcher launcher) {
+        super();
+
+        mInflater = (LayoutInflater) launcher.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        // Create default actions
+        Resources res = launcher.getResources();
+
+        mItems.add(new ListItem(res, R.string.group_wallpapers,
+                R.mipmap.ic_launcher_wallpaper, ITEM_WALLPAPER));
+    }
+
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ListItem item = (ListItem) getItem(position);
+
+        if (convertView == null) {
+            convertView = mInflater.inflate(R.layout.add_list_item, parent, false);
+        }
+
+        TextView textView = (TextView) convertView;
+        textView.setTag(item);
+        textView.setText(item.text);
+        textView.setCompoundDrawablesWithIntrinsicBounds(item.image, null, null, null);
+
+        return convertView;
+    }
+
+    public int getCount() {
+        return mItems.size();
+    }
+
+    public Object getItem(int position) {
+        return mItems.get(position);
+    }
+
+    public long getItemId(int position) {
+        return position;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Alarm.java b/FairphoneHome/src/org/fairphone/launcher/Alarm.java
new file mode 100644
index 0000000..757ead2
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Alarm.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.os.Handler;
+
+public class Alarm implements Runnable{
+    // if we reach this time and the alarm hasn't been cancelled, call the listener
+    private long mAlarmTriggerTime;
+
+    // if we've scheduled a call to run() (ie called mHandler.postDelayed), this variable is true.
+    // We use this to avoid having multiple pending callbacks
+    private boolean mWaitingForCallback;
+
+    private Handler mHandler;
+    private OnAlarmListener mAlarmListener;
+    private boolean mAlarmPending = false;
+
+    public Alarm() {
+        mHandler = new Handler();
+    }
+
+    public void setOnAlarmListener(OnAlarmListener alarmListener) {
+        mAlarmListener = alarmListener;
+    }
+
+    // Sets the alarm to go off in a certain number of milliseconds. If the alarm is already set,
+    // it's overwritten and only the new alarm setting is used
+    public void setAlarm(long millisecondsInFuture) {
+        long currentTime = System.currentTimeMillis();
+        mAlarmPending = true;
+        mAlarmTriggerTime = currentTime + millisecondsInFuture;
+        if (!mWaitingForCallback) {
+            mHandler.postDelayed(this, mAlarmTriggerTime - currentTime);
+            mWaitingForCallback = true;
+        }
+    }
+
+    public void cancelAlarm() {
+        mAlarmTriggerTime = 0;
+        mAlarmPending = false;
+    }
+
+    // this is called when our timer runs out
+    public void run() {
+        mWaitingForCallback = false;
+        if (mAlarmTriggerTime != 0) {
+            long currentTime = System.currentTimeMillis();
+            if (mAlarmTriggerTime > currentTime) {
+                // We still need to wait some time to trigger spring loaded mode--
+                // post a new callback
+                mHandler.postDelayed(this, Math.max(0, mAlarmTriggerTime - currentTime));
+                mWaitingForCallback = true;
+            } else {
+                mAlarmPending = false;
+                if (mAlarmListener != null) {
+                    mAlarmListener.onAlarm(this);
+                }
+            }
+        }
+    }
+
+    public boolean alarmPending() {
+        return mAlarmPending;
+    }
+}
+
+interface OnAlarmListener {
+    public void onAlarm(Alarm alarm);
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/AllAppsList.java b/FairphoneHome/src/org/fairphone/launcher/AllAppsList.java
new file mode 100644
index 0000000..90ed3f9
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/AllAppsList.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+
+/**
+ * Stores the list of all applications for the all apps view.
+ */
+class AllAppsList {
+    public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
+    
+    /** The list off all apps. */
+    public ArrayList<ApplicationInfo> data =
+            new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
+    /** The list of apps that have been added since the last notify() call. */
+    public ArrayList<ApplicationInfo> added =
+            new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
+    /** The list of apps that have been removed since the last notify() call. */
+    public ArrayList<ApplicationInfo> removed = new ArrayList<ApplicationInfo>();
+    /** The list of apps that have been modified since the last notify() call. */
+    public ArrayList<ApplicationInfo> modified = new ArrayList<ApplicationInfo>();
+
+    private IconCache mIconCache;
+
+    /**
+     * Boring constructor.
+     */
+    public AllAppsList(IconCache iconCache) {
+        mIconCache = iconCache;
+    }
+
+    /**
+     * Add the supplied ApplicationInfo objects to the list, and enqueue it into the
+     * list to broadcast when notify() is called.
+     *
+     * If the app is already in the list, doesn't add it.
+     */
+    public void add(ApplicationInfo info) {
+        if (findActivity(data, info.componentName)) {
+            return;
+        }
+        data.add(info);
+        added.add(info);
+    }
+    
+    public void clear() {
+        data.clear();
+        // TODO: do we clear these too?
+        added.clear();
+        removed.clear();
+        modified.clear();
+    }
+
+    public int size() {
+        return data.size();
+    }
+
+    public ApplicationInfo get(int index) {
+        return data.get(index);
+    }
+
+    /**
+     * Add the icons for the supplied apk called packageName.
+     */
+    public void addPackage(Context context, String packageName) {
+        final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
+
+        if (matches.size() > 0) {
+            for (ResolveInfo info : matches) {
+                add(new ApplicationInfo(context.getPackageManager(), info, mIconCache, null));
+            }
+        }
+    }
+
+    /**
+     * Remove the apps for the given apk identified by packageName.
+     */
+    public void removePackage(String packageName) {
+        final List<ApplicationInfo> data = this.data;
+        for (int i = data.size() - 1; i >= 0; i--) {
+            ApplicationInfo info = data.get(i);
+            final ComponentName component = info.intent.getComponent();
+            if (packageName.equals(component.getPackageName())) {
+                removed.add(info);
+                data.remove(i);
+            }
+        }
+        // This is more aggressive than it needs to be.
+        mIconCache.flush();
+    }
+
+    /**
+     * Add and remove icons for this package which has been updated.
+     */
+    public void updatePackage(Context context, String packageName) {
+        final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
+        if (matches.size() > 0) {
+            // Find disabled/removed activities and remove them from data and add them
+            // to the removed list.
+            for (int i = data.size() - 1; i >= 0; i--) {
+                final ApplicationInfo applicationInfo = data.get(i);
+                final ComponentName component = applicationInfo.intent.getComponent();
+                if (packageName.equals(component.getPackageName())) {
+                    if (!findActivity(matches, component)) {
+                        removed.add(applicationInfo);
+                        mIconCache.remove(component);
+                        data.remove(i);
+                    }
+                }
+            }
+
+            // Find enabled activities and add them to the adapter
+            // Also updates existing activities with new labels/icons
+            int count = matches.size();
+            for (int i = 0; i < count; i++) {
+                final ResolveInfo info = matches.get(i);
+                ApplicationInfo applicationInfo = findApplicationInfoLocked(
+                        info.activityInfo.applicationInfo.packageName,
+                        info.activityInfo.name);
+                if (applicationInfo == null) {
+                    add(new ApplicationInfo(context.getPackageManager(), info, mIconCache, null));
+                } else {
+                    mIconCache.remove(applicationInfo.componentName);
+                    mIconCache.getTitleAndIcon(applicationInfo, info, null);
+                    modified.add(applicationInfo);
+                }
+            }
+        } else {
+            // Remove all data for this package.
+            for (int i = data.size() - 1; i >= 0; i--) {
+                final ApplicationInfo applicationInfo = data.get(i);
+                final ComponentName component = applicationInfo.intent.getComponent();
+                if (packageName.equals(component.getPackageName())) {
+                    removed.add(applicationInfo);
+                    mIconCache.remove(component);
+                    data.remove(i);
+                }
+            }
+        }
+    }
+
+    /**
+     * Query the package manager for MAIN/LAUNCHER activities in the supplied package.
+     */
+    private static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
+        final PackageManager packageManager = context.getPackageManager();
+
+        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        mainIntent.setPackage(packageName);
+
+        final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
+        return apps != null ? apps : new ArrayList<ResolveInfo>();
+    }
+
+    /**
+     * Returns whether <em>apps</em> contains <em>component</em>.
+     */
+    private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
+        final String className = component.getClassName();
+        for (ResolveInfo info : apps) {
+            final ActivityInfo activityInfo = info.activityInfo;
+            if (activityInfo.name.equals(className)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether <em>apps</em> contains <em>component</em>.
+     */
+    private static boolean findActivity(ArrayList<ApplicationInfo> apps, ComponentName component) {
+        final int N = apps.size();
+        for (int i=0; i<N; i++) {
+            final ApplicationInfo info = apps.get(i);
+            if (info.componentName.equals(component)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Find an ApplicationInfo object for the given packageName and className.
+     */
+    private ApplicationInfo findApplicationInfoLocked(String packageName, String className) {
+        for (ApplicationInfo info: data) {
+            final ComponentName component = info.intent.getComponent();
+            if (packageName.equals(component.getPackageName())
+                    && className.equals(component.getClassName())) {
+                return info;
+            }
+        }
+        return null;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/AppWidgetResizeFrame.java b/FairphoneHome/src/org/fairphone/launcher/AppWidgetResizeFrame.java
new file mode 100644
index 0000000..590e1dc
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/AppWidgetResizeFrame.java
@@ -0,0 +1,485 @@
+/*
+ * 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 org.fairphone.launcher;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.Gravity;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import org.fairphone.launcher.R;
+
+public class AppWidgetResizeFrame extends FrameLayout {
+    private LauncherAppWidgetHostView mWidgetView;
+    private CellLayout mCellLayout;
+    private DragLayer mDragLayer;
+    private Workspace mWorkspace;
+    private ImageView mLeftHandle;
+    private ImageView mRightHandle;
+    private ImageView mTopHandle;
+    private ImageView mBottomHandle;
+
+    private boolean mLeftBorderActive;
+    private boolean mRightBorderActive;
+    private boolean mTopBorderActive;
+    private boolean mBottomBorderActive;
+
+    private int mWidgetPaddingLeft;
+    private int mWidgetPaddingRight;
+    private int mWidgetPaddingTop;
+    private int mWidgetPaddingBottom;
+
+    private int mBaselineWidth;
+    private int mBaselineHeight;
+    private int mBaselineX;
+    private int mBaselineY;
+    private int mResizeMode;
+
+    private int mRunningHInc;
+    private int mRunningVInc;
+    private int mMinHSpan;
+    private int mMinVSpan;
+    private int mDeltaX;
+    private int mDeltaY;
+    private int mDeltaXAddOn;
+    private int mDeltaYAddOn;
+
+    private int mBackgroundPadding;
+    private int mTouchTargetWidth;
+
+    private int mTopTouchRegionAdjustment = 0;
+    private int mBottomTouchRegionAdjustment = 0;
+
+    int[] mDirectionVector = new int[2];
+    int[] mLastDirectionVector = new int[2];
+
+    final int SNAP_DURATION = 150;
+    final int BACKGROUND_PADDING = 24;
+    final float DIMMED_HANDLE_ALPHA = 0f;
+    final float RESIZE_THRESHOLD = 0.66f;
+
+    private static Rect mTmpRect = new Rect();
+
+    public static final int LEFT = 0;
+    public static final int TOP = 1;
+    public static final int RIGHT = 2;
+    public static final int BOTTOM = 3;
+
+    private Launcher mLauncher;
+
+    public AppWidgetResizeFrame(Context context,
+            LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
+
+        super(context);
+        mLauncher = (Launcher) context;
+        mCellLayout = cellLayout;
+        mWidgetView = widgetView;
+        mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
+        mDragLayer = dragLayer;
+        mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
+
+        final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
+        int[] result = Launcher.getMinSpanForWidget(mLauncher, info);
+        mMinHSpan = result[0];
+        mMinVSpan = result[1];
+
+        setBackgroundResource(R.drawable.widget_resize_frame_holo);
+        setPadding(0, 0, 0, 0);
+
+        LayoutParams lp;
+        mLeftHandle = new ImageView(context);
+        mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        addView(mLeftHandle, lp);
+
+        mRightHandle = new ImageView(context);
+        mRightHandle.setImageResource(R.drawable.widget_resize_handle_right);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.RIGHT | Gravity.CENTER_VERTICAL);
+        addView(mRightHandle, lp);
+
+        mTopHandle = new ImageView(context);
+        mTopHandle.setImageResource(R.drawable.widget_resize_handle_top);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.CENTER_HORIZONTAL | Gravity.TOP);
+        addView(mTopHandle, lp);
+
+        mBottomHandle = new ImageView(context);
+        mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+        addView(mBottomHandle, lp);
+
+        Rect p = AppWidgetHostView.getDefaultPaddingForWidget(context,
+                widgetView.getAppWidgetInfo().provider, null);
+        mWidgetPaddingLeft = p.left;
+        mWidgetPaddingTop = p.top;
+        mWidgetPaddingRight = p.right;
+        mWidgetPaddingBottom = p.bottom;
+
+        if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
+            mTopHandle.setVisibility(GONE);
+            mBottomHandle.setVisibility(GONE);
+        } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
+            mLeftHandle.setVisibility(GONE);
+            mRightHandle.setVisibility(GONE);
+        }
+
+        final float density = mLauncher.getResources().getDisplayMetrics().density;
+        mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING);
+        mTouchTargetWidth = 2 * mBackgroundPadding;
+
+        // When we create the resize frame, we first mark all cells as unoccupied. The appropriate
+        // cells (same if not resized, or different) will be marked as occupied when the resize
+        // frame is dismissed.
+        mCellLayout.markCellsAsUnoccupiedForView(mWidgetView);
+    }
+
+    public boolean beginResizeIfPointInRegion(int x, int y) {
+        boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
+        boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
+
+        mLeftBorderActive = (x < mTouchTargetWidth) && horizontalActive;
+        mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && horizontalActive;
+        mTopBorderActive = (y < mTouchTargetWidth + mTopTouchRegionAdjustment) && verticalActive;
+        mBottomBorderActive = (y > getHeight() - mTouchTargetWidth + mBottomTouchRegionAdjustment)
+                && verticalActive;
+
+        boolean anyBordersActive = mLeftBorderActive || mRightBorderActive
+                || mTopBorderActive || mBottomBorderActive;
+
+        mBaselineWidth = getMeasuredWidth();
+        mBaselineHeight = getMeasuredHeight();
+        mBaselineX = getLeft();
+        mBaselineY = getTop();
+
+        if (anyBordersActive) {
+            mLeftHandle.setAlpha(mLeftBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
+            mRightHandle.setAlpha(mRightBorderActive ? 1.0f :DIMMED_HANDLE_ALPHA);
+            mTopHandle.setAlpha(mTopBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
+            mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
+        }
+        return anyBordersActive;
+    }
+
+    /**
+     *  Here we bound the deltas such that the frame cannot be stretched beyond the extents
+     *  of the CellLayout, and such that the frame's borders can't cross.
+     */
+    public void updateDeltas(int deltaX, int deltaY) {
+        if (mLeftBorderActive) {
+            mDeltaX = Math.max(-mBaselineX, deltaX); 
+            mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
+        } else if (mRightBorderActive) {
+            mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
+            mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
+        }
+
+        if (mTopBorderActive) {
+            mDeltaY = Math.max(-mBaselineY, deltaY);
+            mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
+        } else if (mBottomBorderActive) {
+            mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
+            mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
+        }
+    }
+
+    public void visualizeResizeForDelta(int deltaX, int deltaY) {
+        visualizeResizeForDelta(deltaX, deltaY, false);
+    }
+
+    /**
+     *  Based on the deltas, we resize the frame, and, if needed, we resize the widget.
+     */
+    private void visualizeResizeForDelta(int deltaX, int deltaY, boolean onDismiss) {
+        updateDeltas(deltaX, deltaY);
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+
+        if (mLeftBorderActive) {
+            lp.x = mBaselineX + mDeltaX;
+            lp.width = mBaselineWidth - mDeltaX;
+        } else if (mRightBorderActive) {
+            lp.width = mBaselineWidth + mDeltaX;
+        }
+
+        if (mTopBorderActive) {
+            lp.y = mBaselineY + mDeltaY;
+            lp.height = mBaselineHeight - mDeltaY;
+        } else if (mBottomBorderActive) {
+            lp.height = mBaselineHeight + mDeltaY;
+        }
+
+        resizeWidgetIfNeeded(onDismiss);
+        requestLayout();
+    }
+
+    /**
+     *  Based on the current deltas, we determine if and how to resize the widget.
+     */
+    private void resizeWidgetIfNeeded(boolean onDismiss) {
+        int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
+        int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
+
+        int deltaX = mDeltaX + mDeltaXAddOn;
+        int deltaY = mDeltaY + mDeltaYAddOn;
+
+        float hSpanIncF = 1.0f * deltaX / xThreshold - mRunningHInc;
+        float vSpanIncF = 1.0f * deltaY / yThreshold - mRunningVInc;
+
+        int hSpanInc = 0;
+        int vSpanInc = 0;
+        int cellXInc = 0;
+        int cellYInc = 0;
+
+        int countX = mCellLayout.getCountX();
+        int countY = mCellLayout.getCountY();
+
+        if (Math.abs(hSpanIncF) > RESIZE_THRESHOLD) {
+            hSpanInc = Math.round(hSpanIncF);
+        }
+        if (Math.abs(vSpanIncF) > RESIZE_THRESHOLD) {
+            vSpanInc = Math.round(vSpanIncF);
+        }
+
+        if (!onDismiss && (hSpanInc == 0 && vSpanInc == 0)) return;
+
+
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
+
+        int spanX = lp.cellHSpan;
+        int spanY = lp.cellVSpan;
+        int cellX = lp.useTmpCoords ? lp.tmpCellX : lp.cellX;
+        int cellY = lp.useTmpCoords ? lp.tmpCellY : lp.cellY;
+
+        int hSpanDelta = 0;
+        int vSpanDelta = 0;
+
+        // For each border, we bound the resizing based on the minimum width, and the maximum
+        // expandability.
+        if (mLeftBorderActive) {
+            cellXInc = Math.max(-cellX, hSpanInc);
+            cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc);
+            hSpanInc *= -1;
+            hSpanInc = Math.min(cellX, hSpanInc);
+            hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
+            hSpanDelta = -hSpanInc;
+
+        } else if (mRightBorderActive) {
+            hSpanInc = Math.min(countX - (cellX + spanX), hSpanInc);
+            hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
+            hSpanDelta = hSpanInc;
+        }
+
+        if (mTopBorderActive) {
+            cellYInc = Math.max(-cellY, vSpanInc);
+            cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc);
+            vSpanInc *= -1;
+            vSpanInc = Math.min(cellY, vSpanInc);
+            vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
+            vSpanDelta = -vSpanInc;
+        } else if (mBottomBorderActive) {
+            vSpanInc = Math.min(countY - (cellY + spanY), vSpanInc);
+            vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
+            vSpanDelta = vSpanInc;
+        }
+
+        mDirectionVector[0] = 0;
+        mDirectionVector[1] = 0;
+        // Update the widget's dimensions and position according to the deltas computed above
+        if (mLeftBorderActive || mRightBorderActive) {
+            spanX += hSpanInc;
+            cellX += cellXInc;
+            if (hSpanDelta != 0) {
+                mDirectionVector[0] = mLeftBorderActive ? -1 : 1;
+            }
+        }
+
+        if (mTopBorderActive || mBottomBorderActive) {
+            spanY += vSpanInc;
+            cellY += cellYInc;
+            if (vSpanDelta != 0) {
+                mDirectionVector[1] = mTopBorderActive ? -1 : 1;
+            }
+        }
+
+        if (!onDismiss && vSpanDelta == 0 && hSpanDelta == 0) return;
+
+        // We always want the final commit to match the feedback, so we make sure to use the
+        // last used direction vector when committing the resize / reorder.
+        if (onDismiss) {
+            mDirectionVector[0] = mLastDirectionVector[0];
+            mDirectionVector[1] = mLastDirectionVector[1];
+        } else {
+            mLastDirectionVector[0] = mDirectionVector[0];
+            mLastDirectionVector[1] = mDirectionVector[1];
+        }
+
+        if (mCellLayout.createAreaForResize(cellX, cellY, spanX, spanY, mWidgetView,
+                mDirectionVector, onDismiss)) {
+            lp.tmpCellX = cellX;
+            lp.tmpCellY = cellY;
+            lp.cellHSpan = spanX;
+            lp.cellVSpan = spanY;
+            mRunningVInc += vSpanDelta;
+            mRunningHInc += hSpanDelta;
+            if (!onDismiss) {
+                updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
+            }
+        }
+        mWidgetView.requestLayout();
+    }
+
+    static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
+            int spanX, int spanY) {
+
+        getWidgetSizeRanges(launcher, spanX, spanY, mTmpRect);
+        widgetView.updateAppWidgetSize(null, mTmpRect.left, mTmpRect.top,
+                mTmpRect.right, mTmpRect.bottom);
+    }
+
+    static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) {
+        if (rect == null) {
+            rect = new Rect();
+        }
+        Rect landMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.LANDSCAPE);
+        Rect portMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.PORTRAIT);
+        final float density = launcher.getResources().getDisplayMetrics().density;
+
+        // Compute landscape size
+        int cellWidth = landMetrics.left;
+        int cellHeight = landMetrics.top;
+        int widthGap = landMetrics.right;
+        int heightGap = landMetrics.bottom;
+        int landWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
+        int landHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
+
+        // Compute portrait size
+        cellWidth = portMetrics.left;
+        cellHeight = portMetrics.top;
+        widthGap = portMetrics.right;
+        heightGap = portMetrics.bottom;
+        int portWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
+        int portHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
+        rect.set(portWidth, landHeight, landWidth, portHeight);
+        return rect;
+    }
+
+    /**
+     * This is the final step of the resize. Here we save the new widget size and position
+     * to LauncherModel and animate the resize frame.
+     */
+    public void commitResize() {
+        resizeWidgetIfNeeded(true);
+        requestLayout();
+    }
+
+    public void onTouchUp() {
+        int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
+        int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
+
+        mDeltaXAddOn = mRunningHInc * xThreshold; 
+        mDeltaYAddOn = mRunningVInc * yThreshold; 
+        mDeltaX = 0;
+        mDeltaY = 0;
+
+        post(new Runnable() {
+            @Override
+            public void run() {
+                snapToWidget(true);
+            }
+        });
+    }
+
+    public void snapToWidget(boolean animate) {
+        final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+        int xOffset = mCellLayout.getLeft() + mCellLayout.getPaddingLeft()
+                + mDragLayer.getPaddingLeft() - mWorkspace.getScrollX();
+        int yOffset = mCellLayout.getTop() + mCellLayout.getPaddingTop()
+                + mDragLayer.getPaddingTop() - mWorkspace.getScrollY();
+
+        int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft -
+                mWidgetPaddingRight;
+        int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop -
+                mWidgetPaddingBottom;
+
+        int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset + mWidgetPaddingLeft;
+        int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset + mWidgetPaddingTop;
+
+        // We need to make sure the frame's touchable regions lie fully within the bounds of the 
+        // DragLayer. We allow the actual handles to be clipped, but we shift the touch regions
+        // down accordingly to provide a proper touch target.
+        if (newY < 0) {
+            // In this case we shift the touch region down to start at the top of the DragLayer
+            mTopTouchRegionAdjustment = -newY;
+        } else {
+            mTopTouchRegionAdjustment = 0;
+        }
+        if (newY + newHeight > mDragLayer.getHeight()) {
+            // In this case we shift the touch region up to end at the bottom of the DragLayer
+            mBottomTouchRegionAdjustment = -(newY + newHeight - mDragLayer.getHeight());
+        } else {
+            mBottomTouchRegionAdjustment = 0;
+        }
+
+        if (!animate) {
+            lp.width = newWidth;
+            lp.height = newHeight;
+            lp.x = newX;
+            lp.y = newY;
+            mLeftHandle.setAlpha(1.0f);
+            mRightHandle.setAlpha(1.0f);
+            mTopHandle.setAlpha(1.0f);
+            mBottomHandle.setAlpha(1.0f);
+            requestLayout();
+        } else {
+            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", lp.width, newWidth);
+            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", lp.height,
+                    newHeight);
+            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX);
+            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY);
+            ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(lp, width, height, x, y);
+            ObjectAnimator leftOa = LauncherAnimUtils.ofFloat(mLeftHandle, "alpha", 1.0f);
+            ObjectAnimator rightOa = LauncherAnimUtils.ofFloat(mRightHandle, "alpha", 1.0f);
+            ObjectAnimator topOa = LauncherAnimUtils.ofFloat(mTopHandle, "alpha", 1.0f);
+            ObjectAnimator bottomOa = LauncherAnimUtils.ofFloat(mBottomHandle, "alpha", 1.0f);
+            oa.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    requestLayout();
+                }
+            });
+            AnimatorSet set = LauncherAnimUtils.createAnimatorSet();
+            if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
+                set.playTogether(oa, topOa, bottomOa);
+            } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
+                set.playTogether(oa, leftOa, rightOa);
+            } else {
+                set.playTogether(oa, leftOa, rightOa, topOa, bottomOa);
+            }
+
+            set.setDuration(SNAP_DURATION);
+            set.start();
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/ApplicationInfo.java b/FairphoneHome/src/org/fairphone/launcher/ApplicationInfo.java
new file mode 100644
index 0000000..5d0ae61
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/ApplicationInfo.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Represents an app in AllAppsView.
+ */
+public class ApplicationInfo extends ItemInfo {
+    private static final String TAG = "fairphonelauncher.ApplicationInfo";
+
+    /**
+     * The intent used to start the application.
+     */
+    public Intent intent;
+
+    /**
+     * A bitmap version of the application icon.
+     */
+    public Bitmap iconBitmap;
+
+    /**
+     * The time at which the app was first installed.
+     */
+    public long firstInstallTime;
+
+    public ComponentName componentName;
+    public String appName;
+
+    static final int DOWNLOADED_FLAG = 1;
+    static final int UPDATED_SYSTEM_APP_FLAG = 2;
+
+    int flags = 0;
+
+    ApplicationInfo() {
+        itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
+    }
+
+    /**
+     * Must not hold the Context.
+     */
+    public ApplicationInfo(PackageManager pm, ResolveInfo info, IconCache iconCache,
+            HashMap<Object, CharSequence> labelCache) {
+        final String packageName = info.activityInfo.applicationInfo.packageName;
+
+        this.componentName = new ComponentName(packageName, info.activityInfo.name);
+        this.appName = info.activityInfo.applicationInfo.loadLabel(pm).toString();
+        
+        this.container = ItemInfo.NO_ID;
+        this.setActivity(componentName,
+                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+        try {
+            int appFlags = pm.getApplicationInfo(packageName, 0).flags;
+            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
+                flags |= DOWNLOADED_FLAG;
+
+                if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+                    flags |= UPDATED_SYSTEM_APP_FLAG;
+                }
+            }
+            firstInstallTime = pm.getPackageInfo(packageName, 0).firstInstallTime;
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, "PackageManager.getApplicationInfo failed for " + packageName);
+        }
+
+        iconCache.getTitleAndIcon(this, info, labelCache);
+    }
+
+    public ApplicationInfo(ApplicationInfo info) {
+        super(info);
+        componentName = info.componentName;
+        title = info.title.toString();
+        intent = new Intent(info.intent);
+        flags = info.flags;
+        firstInstallTime = info.firstInstallTime;
+    }
+
+    /** Returns the package name that the shortcut's intent will resolve to, or an empty string if
+     *  none exists. */
+    String getPackageName() {
+        return super.getPackageName(intent);
+    }
+
+    /**
+     * Creates the application intent based on a component name and various launch flags.
+     * Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
+     *
+     * @param className the class name of the component representing the intent
+     * @param launchFlags the launch flags
+     */
+    final void setActivity(ComponentName className, int launchFlags) {
+        intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setComponent(className);
+        intent.setFlags(launchFlags);
+        itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
+    }
+
+    @Override
+    public String toString() {
+        return "ApplicationInfo(title=" + title.toString() + ")";
+    }
+
+    public static void dumpApplicationInfoList(String tag, String label,
+            ArrayList<ApplicationInfo> list) {
+        Log.d(tag, label + " size=" + list.size());
+        for (ApplicationInfo info: list) {
+            Log.d(tag, "   title=\"" + info.title + "\" iconBitmap="
+                    + info.iconBitmap + " firstInstallTime="
+                    + info.firstInstallTime);
+        }
+    }
+
+    public ShortcutInfo makeShortcut() {
+        return new ShortcutInfo(this);
+    }
+    
+    /**
+     * Returns the application title
+     * @return application title
+     */
+    public String getApplicationTitle(){
+    	return title.toString();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/AppsCustomizePagedView.java b/FairphoneHome/src/org/fairphone/launcher/AppsCustomizePagedView.java
new file mode 100644
index 0000000..aca9b42
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/AppsCustomizePagedView.java
@@ -0,0 +1,1915 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.GridLayout;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import org.fairphone.launcher.R;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.fairphone.launcher.DropTarget.DragObject;
+
+/**
+ * A simple callback interface which also provides the results of the task.
+ */
+interface AsyncTaskCallback {
+    void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data);
+}
+
+/**
+ * The data needed to perform either of the custom AsyncTasks.
+ */
+class AsyncTaskPageData {
+    enum Type {
+        LoadWidgetPreviewData
+    }
+
+    AsyncTaskPageData(int p, ArrayList<Object> l, ArrayList<Bitmap> si, AsyncTaskCallback bgR,
+            AsyncTaskCallback postR) {
+        page = p;
+        items = l;
+        sourceImages = si;
+        generatedImages = new ArrayList<Bitmap>();
+        maxImageWidth = maxImageHeight = -1;
+        doInBackgroundCallback = bgR;
+        postExecuteCallback = postR;
+    }
+    AsyncTaskPageData(int p, ArrayList<Object> l, int cw, int ch, AsyncTaskCallback bgR,
+            AsyncTaskCallback postR) {
+        page = p;
+        items = l;
+        generatedImages = new ArrayList<Bitmap>();
+        maxImageWidth = cw;
+        maxImageHeight = ch;
+        doInBackgroundCallback = bgR;
+        postExecuteCallback = postR;
+    }
+    void cleanup(boolean cancelled) {
+        // Clean up any references to source/generated bitmaps
+        if (sourceImages != null) {
+            if (cancelled) {
+                for (Bitmap b : sourceImages) {
+                    b.recycle();
+                }
+            }
+            sourceImages.clear();
+        }
+        if (generatedImages != null) {
+            if (cancelled) {
+                for (Bitmap b : generatedImages) {
+                    b.recycle();
+                }
+            }
+            generatedImages.clear();
+        }
+    }
+    int page;
+    ArrayList<Object> items;
+    ArrayList<Bitmap> sourceImages;
+    ArrayList<Bitmap> generatedImages;
+    int maxImageWidth;
+    int maxImageHeight;
+    AsyncTaskCallback doInBackgroundCallback;
+    AsyncTaskCallback postExecuteCallback;
+}
+
+/**
+ * A generic template for an async task used in AppsCustomize.
+ */
+class AppsCustomizeAsyncTask extends AsyncTask<AsyncTaskPageData, Void, AsyncTaskPageData> {
+    AppsCustomizeAsyncTask(int p, AsyncTaskPageData.Type ty) {
+        page = p;
+        threadPriority = Process.THREAD_PRIORITY_DEFAULT;
+        dataType = ty;
+    }
+    @Override
+    protected AsyncTaskPageData doInBackground(AsyncTaskPageData... params) {
+        if (params.length != 1) return null;
+        // Load each of the widget previews in the background
+        params[0].doInBackgroundCallback.run(this, params[0]);
+        return params[0];
+    }
+    @Override
+    protected void onPostExecute(AsyncTaskPageData result) {
+        // All the widget previews are loaded, so we can just callback to inflate the page
+        result.postExecuteCallback.run(this, result);
+    }
+
+    void setThreadPriority(int p) {
+        threadPriority = p;
+    }
+    void syncThreadPriority() {
+        Process.setThreadPriority(threadPriority);
+    }
+
+    // The page that this async task is associated with
+    AsyncTaskPageData.Type dataType;
+    int page;
+    int threadPriority;
+}
+
+abstract class WeakReferenceThreadLocal<T> {
+    private ThreadLocal<WeakReference<T>> mThreadLocal;
+    public WeakReferenceThreadLocal() {
+        mThreadLocal = new ThreadLocal<WeakReference<T>>();
+    }
+
+    abstract T initialValue();
+
+    public void set(T t) {
+        mThreadLocal.set(new WeakReference<T>(t));
+    }
+
+    public T get() {
+        WeakReference<T> reference = mThreadLocal.get();
+        T obj;
+        if (reference == null) {
+            obj = initialValue();
+            mThreadLocal.set(new WeakReference<T>(obj));
+            return obj;
+        } else {
+            obj = reference.get();
+            if (obj == null) {
+                obj = initialValue();
+                mThreadLocal.set(new WeakReference<T>(obj));
+            }
+            return obj;
+        }
+    }
+}
+
+class CanvasCache extends WeakReferenceThreadLocal<Canvas> {
+    @Override
+    protected Canvas initialValue() {
+        return new Canvas();
+    }
+}
+
+class PaintCache extends WeakReferenceThreadLocal<Paint> {
+    @Override
+    protected Paint initialValue() {
+        return null;
+    }
+}
+
+class BitmapCache extends WeakReferenceThreadLocal<Bitmap> {
+    @Override
+    protected Bitmap initialValue() {
+        return null;
+    }
+}
+
+class RectCache extends WeakReferenceThreadLocal<Rect> {
+    @Override
+    protected Rect initialValue() {
+        return new Rect();
+    }
+}
+
+/**
+ * The Apps/Customize page that displays all the applications, widgets, and shortcuts.
+ */
+public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
+        View.OnClickListener, View.OnKeyListener, DragSource,
+        PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,
+        LauncherTransitionable {
+    static final String TAG = "AppsCustomizePagedView";
+
+    /**
+     * The different content types that this paged view can show.
+     */
+    public enum ContentType {
+        Applications,
+        Widgets
+    }
+
+    // Refs
+    private Launcher mLauncher;
+    private DragController mDragController;
+    private final LayoutInflater mLayoutInflater;
+    private final PackageManager mPackageManager;
+
+    // Save and Restore
+    private int mSaveInstanceStateItemIndex = -1;
+    private PagedViewIcon mPressedIcon;
+
+    // Content
+    private ArrayList<ApplicationInfo> mApps;
+    private ArrayList<Object> mWidgets;
+
+    // Cling
+    private boolean mHasShownAllAppsCling;
+    private int mClingFocusedX;
+    private int mClingFocusedY;
+
+    // Caching
+    private Canvas mCanvas;
+    private IconCache mIconCache;
+
+    // Dimens
+    private int mContentWidth;
+    private int mAppIconSize;
+    private int mMaxAppCellCountX, mMaxAppCellCountY;
+    private int mWidgetCountX, mWidgetCountY;
+    private int mWidgetWidthGap, mWidgetHeightGap;
+    private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
+    private PagedViewCellLayout mWidgetSpacingLayout;
+    private int mNumAppsPages;
+    private int mNumWidgetPages;
+
+    // Relating to the scroll and overscroll effects
+    Workspace.ZInterpolator mZInterpolator = new Workspace.ZInterpolator(0.5f);
+    private static float CAMERA_DISTANCE = 6500;
+    private static float TRANSITION_SCALE_FACTOR = 0.74f;
+    private static float TRANSITION_PIVOT = 0.65f;
+    private static float TRANSITION_MAX_ROTATION = 22;
+    private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
+    private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
+    private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
+
+    // Previews & outlines
+    ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
+    private static final int sPageSleepDelay = 200;
+
+    private Runnable mInflateWidgetRunnable = null;
+    private Runnable mBindWidgetRunnable = null;
+    static final int WIDGET_NO_CLEANUP_REQUIRED = -1;
+    static final int WIDGET_PRELOAD_PENDING = 0;
+    static final int WIDGET_BOUND = 1;
+    static final int WIDGET_INFLATED = 2;
+    int mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
+    int mWidgetLoadingId = -1;
+    PendingAddWidgetInfo mCreateWidgetInfo = null;
+    private boolean mDraggingWidget = false;
+
+    private Toast mWidgetInstructionToast;
+
+    // Deferral of loading widget previews during launcher transitions
+    private boolean mInTransition;
+    private ArrayList<AsyncTaskPageData> mDeferredSyncWidgetPageItems =
+        new ArrayList<AsyncTaskPageData>();
+    private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks =
+        new ArrayList<Runnable>();
+
+    private Rect mTmpRect = new Rect();
+
+    // Used for drawing shortcut previews
+    BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
+    PaintCache mCachedShortcutPreviewPaint = new PaintCache();
+    CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
+
+    // Used for drawing widget previews
+    CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
+    RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
+    RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
+    PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
+
+    public AppsCustomizePagedView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLayoutInflater = LayoutInflater.from(context);
+        mPackageManager = context.getPackageManager();
+        mApps = new ArrayList<ApplicationInfo>();
+        mWidgets = new ArrayList<Object>();
+        mIconCache = ((LauncherApplication) context.getApplicationContext()).getIconCache();
+        mCanvas = new Canvas();
+        mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>();
+
+        // Save the default widget preview background
+        Resources resources = context.getResources();
+        mAppIconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
+        mMaxAppCellCountX = a.getInt(R.styleable.AppsCustomizePagedView_maxAppCellCountX, -1);
+        mMaxAppCellCountY = a.getInt(R.styleable.AppsCustomizePagedView_maxAppCellCountY, -1);
+        mWidgetWidthGap =
+            a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellWidthGap, 0);
+        mWidgetHeightGap =
+            a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellHeightGap, 0);
+        mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
+        mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
+        mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0);
+        mClingFocusedY = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedY, 0);
+        a.recycle();
+        mWidgetSpacingLayout = new PagedViewCellLayout(getContext());
+
+        // The padding on the non-matched dimension for the default widget preview icons
+        // (top + bottom)
+        mFadeInAdjacentScreens = false;
+
+        // Unless otherwise specified this view is important for accessibility.
+        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+    }
+
+    @Override
+    protected void init() {
+        super.init();
+        mCenterPagesVertically = false;
+
+        Context context = getContext();
+        Resources r = context.getResources();
+        setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
+    }
+
+    /** Returns the item index of the center item on this page so that we can restore to this
+     *  item index when we rotate. */
+    private int getMiddleComponentIndexOnCurrentPage() {
+        int i = -1;
+        if (getPageCount() > 0) {
+            int currentPage = getCurrentPage();
+            if (currentPage < mNumAppsPages) {
+                PagedViewCellLayout layout = (PagedViewCellLayout) getPageAt(currentPage);
+                PagedViewCellLayoutChildren childrenLayout = layout.getChildrenLayout();
+                int numItemsPerPage = mCellCountX * mCellCountY;
+                int childCount = childrenLayout.getChildCount();
+                if (childCount > 0) {
+                    i = (currentPage * numItemsPerPage) + (childCount / 2);
+                }
+            } else {
+                int numApps = mApps.size();
+                PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(currentPage);
+                int numItemsPerPage = mWidgetCountX * mWidgetCountY;
+                int childCount = layout.getChildCount();
+                if (childCount > 0) {
+                    i = numApps +
+                        ((currentPage - mNumAppsPages) * numItemsPerPage) + (childCount / 2);
+                }
+            }
+        }
+        return i;
+    }
+
+    /** Get the index of the item to restore to if we need to restore the current page. */
+    int getSaveInstanceStateIndex() {
+        if (mSaveInstanceStateItemIndex == -1) {
+            mSaveInstanceStateItemIndex = getMiddleComponentIndexOnCurrentPage();
+        }
+        return mSaveInstanceStateItemIndex;
+    }
+
+    /** Returns the page in the current orientation which is expected to contain the specified
+     *  item index. */
+    int getPageForComponent(int index) {
+        if (index < 0) return 0;
+
+        if (index < mApps.size()) {
+            int numItemsPerPage = mCellCountX * mCellCountY;
+            return (index / numItemsPerPage);
+        } else {
+            int numItemsPerPage = mWidgetCountX * mWidgetCountY;
+            return mNumAppsPages + ((index - mApps.size()) / numItemsPerPage);
+        }
+    }
+
+    /** Restores the page for an item at the specified index */
+    void restorePageForIndex(int index) {
+        if (index < 0) return;
+        mSaveInstanceStateItemIndex = index;
+    }
+
+    private void updatePageCounts() {
+        mNumWidgetPages = (int) Math.ceil(mWidgets.size() /
+                (float) (mWidgetCountX * mWidgetCountY));
+        mNumAppsPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+    }
+
+    protected void onDataReady(int width, int height) {
+        // Note that we transpose the counts in portrait so that we get a similar layout
+        boolean isLandscape = getResources().getConfiguration().orientation ==
+            Configuration.ORIENTATION_LANDSCAPE;
+        int maxCellCountX = Integer.MAX_VALUE;
+        int maxCellCountY = Integer.MAX_VALUE;
+        if (LauncherApplication.isScreenLarge()) {
+            maxCellCountX = (isLandscape ? LauncherModel.getCellCountX() :
+                LauncherModel.getCellCountY());
+            maxCellCountY = (isLandscape ? LauncherModel.getCellCountY() :
+                LauncherModel.getCellCountX());
+        }
+        if (mMaxAppCellCountX > -1) {
+            maxCellCountX = Math.min(maxCellCountX, mMaxAppCellCountX);
+        }
+        // Temp hack for now: only use the max cell count Y for widget layout
+        int maxWidgetCellCountY = maxCellCountY;
+        if (mMaxAppCellCountY > -1) {
+            maxWidgetCellCountY = Math.min(maxWidgetCellCountY, mMaxAppCellCountY);
+        }
+
+        // Now that the data is ready, we can calculate the content width, the number of cells to
+        // use for each page
+        mWidgetSpacingLayout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+        mWidgetSpacingLayout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+        mWidgetSpacingLayout.calculateCellCount(width, height, maxCellCountX, maxCellCountY);
+        mCellCountX = mWidgetSpacingLayout.getCellCountX();
+        mCellCountY = mWidgetSpacingLayout.getCellCountY();
+        updatePageCounts();
+
+        // Force a measure to update recalculate the gaps
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+        mWidgetSpacingLayout.calculateCellCount(width, height, maxCellCountX, maxWidgetCellCountY);
+        mWidgetSpacingLayout.measure(widthSpec, heightSpec);
+        mContentWidth = mWidgetSpacingLayout.getContentWidth();
+
+        AppsCustomizeTabHost host = (AppsCustomizeTabHost) getTabHost();
+        final boolean hostIsTransitioning = host.isTransitioning();
+
+        // Restore the page
+        int page = getPageForComponent(mSaveInstanceStateItemIndex);
+        invalidatePageData(Math.max(0, page), hostIsTransitioning);
+
+        // Show All Apps cling if we are finished transitioning, otherwise, we will try again when
+        // the transition completes in AppsCustomizeTabHost (otherwise the wrong offsets will be
+        // returned while animating)
+        if (!hostIsTransitioning) {
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    showAllAppsCling();
+                }
+            });
+        }
+    }
+
+    void showAllAppsCling() {
+        if (!mHasShownAllAppsCling && isDataReady()) {
+            mHasShownAllAppsCling = true;
+            // Calculate the position for the cling punch through
+            int[] offset = new int[2];
+            int[] pos = mWidgetSpacingLayout.estimateCellPosition(mClingFocusedX, mClingFocusedY);
+            mLauncher.getDragLayer().getLocationInDragLayer(this, offset);
+            // PagedViews are centered horizontally but top aligned
+            // Note we have to shift the items up now that Launcher sits under the status bar
+            pos[0] += (getMeasuredWidth() - mWidgetSpacingLayout.getMeasuredWidth()) / 2 +
+                    offset[0];
+            pos[1] += offset[1] - mLauncher.getDragLayer().getPaddingTop();
+            mLauncher.showFirstRunAllAppsCling(pos);
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        int height = MeasureSpec.getSize(heightMeasureSpec);
+        if (!isDataReady()) {
+            if (!mApps.isEmpty() && !mWidgets.isEmpty()) {
+                setDataIsReady();
+                setMeasuredDimension(width, height);
+                onDataReady(width, height);
+            }
+        }
+
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    public void onPackagesUpdated() {
+        // Get the list of widgets and shortcuts
+        mWidgets.clear();
+        List<AppWidgetProviderInfo> widgets =
+            AppWidgetManager.getInstance(mLauncher).getInstalledProviders();
+        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
+        List<ResolveInfo> shortcuts = mPackageManager.queryIntentActivities(shortcutsIntent, 0);
+        for (AppWidgetProviderInfo widget : widgets) {
+            if (widget.minWidth > 0 && widget.minHeight > 0) {
+                // Ensure that all widgets we show can be added on a workspace of this size
+                int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget);
+                int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, widget);
+                int minSpanX = Math.min(spanXY[0], minSpanXY[0]);
+                int minSpanY = Math.min(spanXY[1], minSpanXY[1]);
+                if (minSpanX <= LauncherModel.getCellCountX() &&
+                        minSpanY <= LauncherModel.getCellCountY()) {
+                    mWidgets.add(widget);
+                } else {
+                    Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" +
+                            widget.minWidth + ", " + widget.minHeight + ")");
+                }
+            } else {
+                Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" +
+                        widget.minWidth + ", " + widget.minHeight + ")");
+            }
+        }
+        mWidgets.addAll(shortcuts);
+        Collections.sort(mWidgets,
+                new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
+        updatePageCounts();
+        invalidateOnDataChange();
+    }
+
+    @Override
+    public void onClick(View v) {
+        // When we have exited all apps or are in transition, disregard clicks
+        if (!mLauncher.isAllAppsVisible() ||
+                mLauncher.getWorkspace().isSwitchingState()) return;
+
+        if (v instanceof PagedViewIcon) {
+            // Animate some feedback to the click
+            final ApplicationInfo appInfo = (ApplicationInfo) v.getTag();
+
+            // Lock the drawable state to pressed until we return to Launcher
+            if (mPressedIcon != null) {
+                mPressedIcon.lockDrawableState();
+            }
+
+            // NOTE: We want all transitions from launcher to act as if the wallpaper were enabled
+            // to be consistent.  So re-enable the flag here, and we will re-disable it as necessary
+            // when Launcher resumes and we are still in AllApps.
+            mLauncher.updateWallpaperVisibility(true);
+            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
+
+        } else if (v instanceof PagedViewWidget) {
+            // Let the user know that they have to long press to add a widget
+            if (mWidgetInstructionToast != null) {
+                mWidgetInstructionToast.cancel();
+            }
+            mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add,
+                Toast.LENGTH_SHORT);
+            mWidgetInstructionToast.show();
+
+            // Create a little animation to show that the widget can move
+            float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+            final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
+            AnimatorSet bounce = LauncherAnimUtils.createAnimatorSet();
+            ValueAnimator tyuAnim = LauncherAnimUtils.ofFloat(p, "translationY", offsetY);
+            tyuAnim.setDuration(125);
+            ValueAnimator tydAnim = LauncherAnimUtils.ofFloat(p, "translationY", 0f);
+            tydAnim.setDuration(100);
+            bounce.play(tyuAnim).before(tydAnim);
+            bounce.setInterpolator(new AccelerateInterpolator());
+            bounce.start();
+        }
+    }
+
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleAppsCustomizeKeyEvent(v,  keyCode, event);
+    }
+
+    /*
+     * PagedViewWithDraggableItems implementation
+     */
+    @Override
+    protected void determineDraggingStart(android.view.MotionEvent ev) {
+        // Disable dragging by pulling an app down for now.
+    }
+
+    private void beginDraggingApplication(View v) {
+        mLauncher.getWorkspace().onDragStartedWithItem(v);
+        mLauncher.getWorkspace().beginDragShared(v, this);
+    }
+
+    Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) {
+        Bundle options = null;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, mTmpRect);
+            Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(mLauncher,
+                    info.componentName, null);
+
+            float density = getResources().getDisplayMetrics().density;
+            int xPaddingDips = (int) ((padding.left + padding.right) / density);
+            int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
+
+            options = new Bundle();
+            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH,
+                    mTmpRect.left - xPaddingDips);
+            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT,
+                    mTmpRect.top - yPaddingDips);
+            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH,
+                    mTmpRect.right - xPaddingDips);
+            options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT,
+                    mTmpRect.bottom - yPaddingDips);
+        }
+        return options;
+    }
+
+    private void preloadWidget(final PendingAddWidgetInfo info) {
+        final AppWidgetProviderInfo pInfo = info.info;
+        final Bundle options = getDefaultOptionsForWidget(mLauncher, info);
+
+        if (pInfo.configure != null) {
+            info.bindOptions = options;
+            return;
+        }
+
+        mWidgetCleanupState = WIDGET_PRELOAD_PENDING;
+        mBindWidgetRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
+                // Options will be null for platforms with JB or lower, so this serves as an
+                // SDK level check.
+                if (options == null) {
+                    if (AppWidgetManager.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
+                            mWidgetLoadingId, info.componentName)) {
+                        mWidgetCleanupState = WIDGET_BOUND;
+                    }
+                } else {
+                    if (AppWidgetManager.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
+                            mWidgetLoadingId, info.componentName, options)) {
+                        mWidgetCleanupState = WIDGET_BOUND;
+                    }
+                }
+            }
+        };
+        post(mBindWidgetRunnable);
+
+        mInflateWidgetRunnable = new Runnable() {
+            @Override
+            public void run() {
+                if (mWidgetCleanupState != WIDGET_BOUND) {
+                    return;
+                }
+                AppWidgetHostView hostView = mLauncher.
+                        getAppWidgetHost().createView(getContext(), mWidgetLoadingId, pInfo);
+                info.boundWidget = hostView;
+                mWidgetCleanupState = WIDGET_INFLATED;
+                hostView.setVisibility(INVISIBLE);
+                int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(info.spanX,
+                        info.spanY, info, false);
+
+                // We want the first widget layout to be the correct size. This will be important
+                // for width size reporting to the AppWidgetManager.
+                DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],
+                        unScaledSize[1]);
+                lp.x = lp.y = 0;
+                lp.customPosition = true;
+                hostView.setLayoutParams(lp);
+                mLauncher.getDragLayer().addView(hostView);
+            }
+        };
+        post(mInflateWidgetRunnable);
+    }
+
+    @Override
+    public void onShortPress(View v) {
+        // We are anticipating a long press, and we use this time to load bind and instantiate
+        // the widget. This will need to be cleaned up if it turns out no long press occurs.
+        if (mCreateWidgetInfo != null) {
+            // Just in case the cleanup process wasn't properly executed. This shouldn't happen.
+            cleanupWidgetPreloading(false);
+        }
+        mCreateWidgetInfo = new PendingAddWidgetInfo((PendingAddWidgetInfo) v.getTag());
+        preloadWidget(mCreateWidgetInfo);
+    }
+
+    private void cleanupWidgetPreloading(boolean widgetWasAdded) {
+        if (!widgetWasAdded) {
+            // If the widget was not added, we may need to do further cleanup.
+            PendingAddWidgetInfo info = mCreateWidgetInfo;
+            mCreateWidgetInfo = null;
+
+            if (mWidgetCleanupState == WIDGET_PRELOAD_PENDING) {
+                // We never did any preloading, so just remove pending callbacks to do so
+                removeCallbacks(mBindWidgetRunnable);
+                removeCallbacks(mInflateWidgetRunnable);
+            } else if (mWidgetCleanupState == WIDGET_BOUND) {
+                 // Delete the widget id which was allocated
+                if (mWidgetLoadingId != -1) {
+                    mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
+                }
+
+                // We never got around to inflating the widget, so remove the callback to do so.
+                removeCallbacks(mInflateWidgetRunnable);
+            } else if (mWidgetCleanupState == WIDGET_INFLATED) {
+                // Delete the widget id which was allocated
+                if (mWidgetLoadingId != -1) {
+                    mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId);
+                }
+
+                // The widget was inflated and added to the DragLayer -- remove it.
+                AppWidgetHostView widget = info.boundWidget;
+                mLauncher.getDragLayer().removeView(widget);
+            }
+        }
+        mWidgetCleanupState = WIDGET_NO_CLEANUP_REQUIRED;
+        mWidgetLoadingId = -1;
+        mCreateWidgetInfo = null;
+        PagedViewWidget.resetShortPressTarget();
+    }
+
+    @Override
+    public void cleanUpShortPress(View v) {
+        if (!mDraggingWidget) {
+            cleanupWidgetPreloading(false);
+        }
+    }
+
+    private boolean beginDraggingWidget(View v) {
+        mDraggingWidget = true;
+        // Get the widget preview as the drag representation
+        ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
+        PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
+
+        // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
+        // we abort the drag.
+        if (image.getDrawable() == null) {
+            mDraggingWidget = false;
+            return false;
+        }
+
+        // Compose the drag image
+        Bitmap preview;
+        Bitmap outline;
+        float scale = 1f;
+        if (createItemInfo instanceof PendingAddWidgetInfo) {
+            // This can happen in some weird cases involving multi-touch. We can't start dragging
+            // the widget if this is null, so we break out.
+            if (mCreateWidgetInfo == null) {
+                return false;
+            }
+
+            PendingAddWidgetInfo createWidgetInfo = mCreateWidgetInfo;
+            createItemInfo = createWidgetInfo;
+            int spanX = createItemInfo.spanX;
+            int spanY = createItemInfo.spanY;
+            int[] size = mLauncher.getWorkspace().estimateItemSize(spanX, spanY,
+                    createWidgetInfo, true);
+
+            FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
+            float minScale = 1.25f;
+            int maxWidth, maxHeight;
+            maxWidth = Math.min((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]);
+            maxHeight = Math.min((int) (previewDrawable.getIntrinsicHeight() * minScale), size[1]);
+            preview = getWidgetPreview(createWidgetInfo.componentName, createWidgetInfo.previewImage,
+                    createWidgetInfo.icon, spanX, spanY, maxWidth, maxHeight);
+
+            // Determine the image view drawable scale relative to the preview
+            float[] mv = new float[9];
+            Matrix m = new Matrix();
+            m.setRectToRect(
+                    new RectF(0f, 0f, (float) preview.getWidth(), (float) preview.getHeight()),
+                    new RectF(0f, 0f, (float) previewDrawable.getIntrinsicWidth(),
+                            (float) previewDrawable.getIntrinsicHeight()),
+                    Matrix.ScaleToFit.START);
+            m.getValues(mv);
+            scale = (float) mv[0];
+        } else {
+            PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
+            Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo);
+            preview = Bitmap.createBitmap(icon.getIntrinsicWidth(),
+                    icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
+            mCanvas.setBitmap(preview);
+            mCanvas.save();
+            renderDrawableToBitmap(icon, preview, 0, 0,
+                    icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+            mCanvas.restore();
+            mCanvas.setBitmap(null);
+            createItemInfo.spanX = createItemInfo.spanY = 1;
+        }
+
+        // Don't clip alpha values for the drag outline if we're using the default widget preview
+        boolean clipAlpha = !(createItemInfo instanceof PendingAddWidgetInfo &&
+                (((PendingAddWidgetInfo) createItemInfo).previewImage == 0));
+
+        // Save the preview for the outline generation, then dim the preview
+        outline = Bitmap.createScaledBitmap(preview, preview.getWidth(), preview.getHeight(),
+                false);
+
+        // Start the drag
+        mLauncher.lockScreenOrientation();
+        mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, outline, clipAlpha);
+        mDragController.startDrag(image, preview, this, createItemInfo,
+                DragController.DRAG_ACTION_COPY, null, scale);
+        outline.recycle();
+        preview.recycle();
+        return true;
+    }
+
+    @Override
+    protected boolean beginDragging(final View v) {
+        if (!super.beginDragging(v)) return false;
+
+        if (v instanceof PagedViewIcon) {
+            beginDraggingApplication(v);
+        } else if (v instanceof PagedViewWidget) {
+            if (!beginDraggingWidget(v)) {
+                return false;
+            }
+        }
+
+        // We delay entering spring-loaded mode slightly to make sure the UI
+        // thready is free of any work.
+        postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                // We don't enter spring-loaded mode if the drag has been cancelled
+                if (mLauncher.getDragController().isDragging()) {
+                    // Dismiss the cling
+                    mLauncher.dismissAllAppsCling(null);
+
+                    // Reset the alpha on the dragged icon before we drag
+                    resetDrawableState();
+
+                    // Go into spring loaded mode (must happen before we startDrag())
+                    mLauncher.enterSpringLoadedDragMode();
+                }
+            }
+        }, 150);
+
+        return true;
+    }
+
+    /**
+     * Clean up after dragging.
+     *
+     * @param target where the item was dragged to (can be null if the item was flung)
+     */
+    private void endDragging(View target, boolean isFlingToDelete, boolean success) {
+        if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
+                !(target instanceof DeleteDropTarget))) {
+            // Exit spring loaded mode if we have not successfully dropped or have not handled the
+            // drop in Workspace
+            mLauncher.exitSpringLoadedDragMode();
+        }
+        mLauncher.unlockScreenOrientation(false);
+    }
+
+    @Override
+    public View getContent() {
+        return null;
+    }
+
+    @Override
+    public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
+        mInTransition = true;
+        if (toWorkspace) {
+            cancelAllTasks();
+        }
+    }
+
+    @Override
+    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+    }
+
+    @Override
+    public void onLauncherTransitionStep(Launcher l, float t) {
+    }
+
+    @Override
+    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+        mInTransition = false;
+        for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) {
+            onSyncWidgetPageItems(d);
+        }
+        mDeferredSyncWidgetPageItems.clear();
+        for (Runnable r : mDeferredPrepareLoadWidgetPreviewsTasks) {
+            r.run();
+        }
+        mDeferredPrepareLoadWidgetPreviewsTasks.clear();
+        mForceDrawAllChildrenNextFrame = !toWorkspace;
+    }
+
+    @Override
+    public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
+            boolean success) {
+        // Return early and wait for onFlingToDeleteCompleted if this was the result of a fling
+        if (isFlingToDelete) return;
+
+        endDragging(target, false, success);
+
+        // Display an error message if the drag failed due to there not being enough space on the
+        // target layout we were dropping on.
+        if (!success) {
+            boolean showOutOfSpaceMessage = false;
+            if (target instanceof Workspace) {
+                int currentScreen = mLauncher.getCurrentWorkspaceScreen();
+                Workspace workspace = (Workspace) target;
+                CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
+                ItemInfo itemInfo = (ItemInfo) d.dragInfo;
+                if (layout != null) {
+                    layout.calculateSpans(itemInfo);
+                    showOutOfSpaceMessage =
+                            !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
+                }
+            }
+            if (showOutOfSpaceMessage) {
+                mLauncher.showOutOfSpaceMessage(false);
+            }
+
+            d.deferDragViewCleanupPostAnimation = false;
+        }
+        cleanupWidgetPreloading(success);
+        mDraggingWidget = false;
+    }
+
+    @Override
+    public void onFlingToDeleteCompleted() {
+        // We just dismiss the drag when we fling, so cleanup here
+        endDragging(null, true, true);
+        cleanupWidgetPreloading(false);
+        mDraggingWidget = false;
+    }
+
+    @Override
+    public boolean supportsFlingToDelete() {
+        return true;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        cancelAllTasks();
+    }
+
+    public void clearAllWidgetPages() {
+        cancelAllTasks();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View v = getPageAt(i);
+            if (v instanceof PagedViewGridLayout) {
+                ((PagedViewGridLayout) v).removeAllViewsOnPage();
+                mDirtyPageContent.set(i, true);
+            }
+        }
+    }
+
+    private void cancelAllTasks() {
+        // Clean up all the async tasks
+        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
+        while (iter.hasNext()) {
+            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+            task.cancel(false);
+            iter.remove();
+            mDirtyPageContent.set(task.page, true);
+
+            // We've already preallocated the views for the data to load into, so clear them as well
+            View v = getPageAt(task.page);
+            if (v instanceof PagedViewGridLayout) {
+                ((PagedViewGridLayout) v).removeAllViewsOnPage();
+            }
+        }
+        mDeferredSyncWidgetPageItems.clear();
+        mDeferredPrepareLoadWidgetPreviewsTasks.clear();
+    }
+
+    public void setContentType(ContentType type) {
+        if (type == ContentType.Widgets) {
+            invalidatePageData(mNumAppsPages, true);
+        } else if (type == ContentType.Applications) {
+            invalidatePageData(0, true);
+        }
+    }
+
+    protected void snapToPage(int whichPage, int delta, int duration) {
+        super.snapToPage(whichPage, delta, duration);
+        updateCurrentTab(whichPage);
+
+        // Update the thread priorities given the direction lookahead
+        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
+        while (iter.hasNext()) {
+            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+            int pageIndex = task.page;
+            if ((mNextPage > mCurrentPage && pageIndex >= mCurrentPage) ||
+                (mNextPage < mCurrentPage && pageIndex <= mCurrentPage)) {
+                task.setThreadPriority(getThreadPriorityForPage(pageIndex));
+            } else {
+                task.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
+            }
+        }
+    }
+
+    private void updateCurrentTab(int currentPage) {
+        AppsCustomizeTabHost tabHost = getTabHost();
+        if (tabHost != null) {
+            String tag = tabHost.getCurrentTabTag();
+            if (tag != null) {
+                if (currentPage >= mNumAppsPages &&
+                        !tag.equals(tabHost.getTabTagForContentType(ContentType.Widgets))) {
+                    tabHost.setCurrentTabFromContent(ContentType.Widgets);
+                } else if (currentPage < mNumAppsPages &&
+                        !tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
+                    tabHost.setCurrentTabFromContent(ContentType.Applications);
+                }
+            }
+        }
+    }
+
+    /*
+     * Apps PagedView implementation
+     */
+    private void setVisibilityOnChildren(ViewGroup layout, int visibility) {
+        int childCount = layout.getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            layout.getChildAt(i).setVisibility(visibility);
+        }
+    }
+    private void setupPage(PagedViewCellLayout layout) {
+        layout.setCellCount(mCellCountX, mCellCountY);
+        layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+        // Note: We force a measure here to get around the fact that when we do layout calculations
+        // immediately after syncing, we don't have a proper width.  That said, we already know the
+        // expected page width, so we can actually optimize by hiding all the TextView-based
+        // children that are expensive to measure, and let that happen naturally later.
+        setVisibilityOnChildren(layout, View.GONE);
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+        layout.setMinimumWidth(getPageContentWidth());
+        layout.measure(widthSpec, heightSpec);
+        setVisibilityOnChildren(layout, View.VISIBLE);
+    }
+
+    public void syncAppsPageItems(int page, boolean immediate) {
+        // ensure that we have the right number of items on the pages
+        int numCells = mCellCountX * mCellCountY;
+        int startIndex = page * numCells;
+        int endIndex = Math.min(startIndex + numCells, mApps.size());
+        PagedViewCellLayout layout = (PagedViewCellLayout) getPageAt(page);
+
+        layout.removeAllViewsOnPage();
+        ArrayList<Object> items = new ArrayList<Object>();
+        ArrayList<Bitmap> images = new ArrayList<Bitmap>();
+        for (int i = startIndex; i < endIndex; ++i) {
+            ApplicationInfo info = mApps.get(i);
+            PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
+                    R.layout.apps_customize_application, layout, false);
+            icon.applyFromApplicationInfo(info, true, this);
+            icon.setOnClickListener(this);
+            icon.setOnLongClickListener(this);
+            icon.setOnTouchListener(this);
+            icon.setOnKeyListener(this);
+
+            int index = i - startIndex;
+            int x = index % mCellCountX;
+            int y = index / mCellCountX;
+            layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
+
+            items.add(info);
+            images.add(info.iconBitmap);
+        }
+
+        layout.createHardwareLayers();
+    }
+
+    /**
+     * A helper to return the priority for loading of the specified widget page.
+     */
+    private int getWidgetPageLoadPriority(int page) {
+        // If we are snapping to another page, use that index as the target page index
+        int toPage = mCurrentPage;
+        if (mNextPage > -1) {
+            toPage = mNextPage;
+        }
+
+        // We use the distance from the target page as an initial guess of priority, but if there
+        // are no pages of higher priority than the page specified, then bump up the priority of
+        // the specified page.
+        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
+        int minPageDiff = Integer.MAX_VALUE;
+        while (iter.hasNext()) {
+            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+            minPageDiff = Math.abs(task.page - toPage);
+        }
+
+        int rawPageDiff = Math.abs(page - toPage);
+        return rawPageDiff - Math.min(rawPageDiff, minPageDiff);
+    }
+    /**
+     * Return the appropriate thread priority for loading for a given page (we give the current
+     * page much higher priority)
+     */
+    private int getThreadPriorityForPage(int page) {
+        // TODO-APPS_CUSTOMIZE: detect number of cores and set thread priorities accordingly below
+        int pageDiff = getWidgetPageLoadPriority(page);
+        if (pageDiff <= 0) {
+            return Process.THREAD_PRIORITY_LESS_FAVORABLE;
+        } else if (pageDiff <= 1) {
+            return Process.THREAD_PRIORITY_LOWEST;
+        } else {
+            return Process.THREAD_PRIORITY_LOWEST;
+        }
+    }
+    private int getSleepForPage(int page) {
+        int pageDiff = getWidgetPageLoadPriority(page);
+        return Math.max(0, pageDiff * sPageSleepDelay);
+    }
+    /**
+     * Creates and executes a new AsyncTask to load a page of widget previews.
+     */
+    private void prepareLoadWidgetPreviewsTask(int page, ArrayList<Object> widgets,
+            int cellWidth, int cellHeight, int cellCountX) {
+
+        // Prune all tasks that are no longer needed
+        Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
+        while (iter.hasNext()) {
+            AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+            int taskPage = task.page;
+            if (taskPage < getAssociatedLowerPageBound(mCurrentPage) ||
+                    taskPage > getAssociatedUpperPageBound(mCurrentPage)) {
+                task.cancel(false);
+                iter.remove();
+            } else {
+                task.setThreadPriority(getThreadPriorityForPage(taskPage));
+            }
+        }
+
+        // We introduce a slight delay to order the loading of side pages so that we don't thrash
+        final int sleepMs = getSleepForPage(page);
+        AsyncTaskPageData pageData = new AsyncTaskPageData(page, widgets, cellWidth, cellHeight,
+            new AsyncTaskCallback() {
+                @Override
+                public void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data) {
+                    try {
+                        try {
+                            Thread.sleep(sleepMs);
+                        } catch (Exception e) {}
+                        loadWidgetPreviewsInBackground(task, data);
+                    } finally {
+                        if (task.isCancelled()) {
+                            data.cleanup(true);
+                        }
+                    }
+                }
+            },
+            new AsyncTaskCallback() {
+                @Override
+                public void run(AppsCustomizeAsyncTask task, AsyncTaskPageData data) {
+                    mRunningTasks.remove(task);
+                    if (task.isCancelled()) return;
+                    // do cleanup inside onSyncWidgetPageItems
+                    onSyncWidgetPageItems(data);
+                }
+            });
+
+        // Ensure that the task is appropriately prioritized and runs in parallel
+        AppsCustomizeAsyncTask t = new AppsCustomizeAsyncTask(page,
+                AsyncTaskPageData.Type.LoadWidgetPreviewData);
+        t.setThreadPriority(getThreadPriorityForPage(page));
+        t.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, pageData);
+        mRunningTasks.add(t);
+    }
+
+    /*
+     * Widgets PagedView implementation
+     */
+    private void setupPage(PagedViewGridLayout layout) {
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+        // Note: We force a measure here to get around the fact that when we do layout calculations
+        // immediately after syncing, we don't have a proper width.
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+        layout.setMinimumWidth(getPageContentWidth());
+        layout.measure(widthSpec, heightSpec);
+    }
+
+    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
+        renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
+    }
+
+    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
+            float scale) {
+        if (bitmap != null) {
+            Canvas c = new Canvas(bitmap);
+            c.scale(scale, scale);
+            Rect oldBounds = d.copyBounds();
+            d.setBounds(x, y, x + w, y + h);
+            d.draw(c);
+            d.setBounds(oldBounds); // Restore the bounds
+            c.setBitmap(null);
+        }
+    }
+
+    private Bitmap getShortcutPreview(ResolveInfo info, int maxWidth, int maxHeight) {
+        Bitmap tempBitmap = mCachedShortcutPreviewBitmap.get();
+        final Canvas c = mCachedShortcutPreviewCanvas.get();
+        if (tempBitmap == null ||
+                tempBitmap.getWidth() != maxWidth ||
+                tempBitmap.getHeight() != maxHeight) {
+            tempBitmap = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
+            mCachedShortcutPreviewBitmap.set(tempBitmap);
+        } else {
+            c.setBitmap(tempBitmap);
+            c.drawColor(0, PorterDuff.Mode.CLEAR);
+            c.setBitmap(null);
+        }
+        // Render the icon
+        Drawable icon = mIconCache.getFullResIcon(info);
+
+        int paddingTop =
+                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
+        int paddingLeft =
+                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_left);
+        int paddingRight =
+                getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_right);
+
+        int scaledIconWidth = (maxWidth - paddingLeft - paddingRight);
+
+        renderDrawableToBitmap(
+                icon, tempBitmap, paddingLeft, paddingTop, scaledIconWidth, scaledIconWidth);
+
+        Bitmap preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
+        c.setBitmap(preview);
+        Paint p = mCachedShortcutPreviewPaint.get();
+        if (p == null) {
+            p = new Paint();
+            ColorMatrix colorMatrix = new ColorMatrix();
+            colorMatrix.setSaturation(0);
+            p.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
+            p.setAlpha((int) (255 * 0.06f));
+            //float density = 1f;
+            //p.setMaskFilter(new BlurMaskFilter(15*density, BlurMaskFilter.Blur.NORMAL));
+            mCachedShortcutPreviewPaint.set(p);
+        }
+        c.drawBitmap(tempBitmap, 0, 0, p);
+        c.setBitmap(null);
+
+        renderDrawableToBitmap(icon, preview, 0, 0, mAppIconSize, mAppIconSize);
+
+        return preview;
+    }
+
+    private Bitmap getWidgetPreview(ComponentName provider, int previewImage,
+            int iconId, int cellHSpan, int cellVSpan, int maxWidth,
+            int maxHeight) {
+        // Load the preview image if possible
+        String packageName = provider.getPackageName();
+        if (maxWidth < 0) maxWidth = Integer.MAX_VALUE;
+        if (maxHeight < 0) maxHeight = Integer.MAX_VALUE;
+
+        Drawable drawable = null;
+        if (previewImage != 0) {
+            drawable = mPackageManager.getDrawable(packageName, previewImage, null);
+            if (drawable == null) {
+                Log.w(TAG, "Can't load widget preview drawable 0x" +
+                        Integer.toHexString(previewImage) + " for provider: " + provider);
+            }
+        }
+
+        int bitmapWidth;
+        int bitmapHeight;
+        Bitmap defaultPreview = null;
+        boolean widgetPreviewExists = (drawable != null);
+        if (widgetPreviewExists) {
+            bitmapWidth = drawable.getIntrinsicWidth();
+            bitmapHeight = drawable.getIntrinsicHeight();
+        } else {
+            // Generate a preview image if we couldn't load one
+            if (cellHSpan < 1) cellHSpan = 1;
+            if (cellVSpan < 1) cellVSpan = 1;
+
+            BitmapDrawable previewDrawable = (BitmapDrawable) getResources()
+                    .getDrawable(R.drawable.widget_preview_tile);
+            final int previewDrawableWidth = previewDrawable
+                    .getIntrinsicWidth();
+            final int previewDrawableHeight = previewDrawable
+                    .getIntrinsicHeight();
+            bitmapWidth = previewDrawableWidth * cellHSpan; // subtract 2 dips
+            bitmapHeight = previewDrawableHeight * cellVSpan;
+
+            defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+                    Config.ARGB_8888);
+            final Canvas c = mCachedAppWidgetPreviewCanvas.get();
+            c.setBitmap(defaultPreview);
+            previewDrawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
+            previewDrawable.setTileModeXY(Shader.TileMode.REPEAT,
+                    Shader.TileMode.REPEAT);
+            previewDrawable.draw(c);
+            c.setBitmap(null);
+
+            // Draw the icon in the top left corner
+            int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage);
+            int smallestSide = Math.min(bitmapWidth, bitmapHeight);
+            float iconScale = Math.min((float) smallestSide
+                    / (mAppIconSize + 2 * minOffset), 1f);
+
+            try {
+                Drawable icon = null;
+                int hoffset =
+                        (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
+                int yoffset =
+                        (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
+                if (iconId > 0)
+                    icon = mIconCache.getFullResIcon(packageName, iconId);
+                if (icon != null) {
+                    renderDrawableToBitmap(icon, defaultPreview, hoffset,
+                            yoffset, (int) (mAppIconSize * iconScale),
+                            (int) (mAppIconSize * iconScale));
+                }
+            } catch (Resources.NotFoundException e) {
+            }
+        }
+
+        // Scale to fit width only - let the widget preview be clipped in the
+        // vertical dimension
+        float scale = 1f;
+        if (bitmapWidth > maxWidth) {
+            scale = maxWidth / (float) bitmapWidth;
+        }
+        if (scale != 1f) {
+            bitmapWidth = (int) (scale * bitmapWidth);
+            bitmapHeight = (int) (scale * bitmapHeight);
+        }
+
+        Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+                Config.ARGB_8888);
+
+        // Draw the scaled preview into the final bitmap
+        if (widgetPreviewExists) {
+            renderDrawableToBitmap(drawable, preview, 0, 0, bitmapWidth,
+                    bitmapHeight);
+        } else {
+            final Canvas c = mCachedAppWidgetPreviewCanvas.get();
+            final Rect src = mCachedAppWidgetPreviewSrcRect.get();
+            final Rect dest = mCachedAppWidgetPreviewDestRect.get();
+            c.setBitmap(preview);
+            src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
+            dest.set(0, 0, preview.getWidth(), preview.getHeight());
+
+            Paint p = mCachedAppWidgetPreviewPaint.get();
+            if (p == null) {
+                p = new Paint();
+                p.setFilterBitmap(true);
+                mCachedAppWidgetPreviewPaint.set(p);
+            }
+            c.drawBitmap(defaultPreview, src, dest, p);
+            c.setBitmap(null);
+        }
+        return preview;
+    }
+
+    public void syncWidgetPageItems(final int page, final boolean immediate) {
+        int numItemsPerPage = mWidgetCountX * mWidgetCountY;
+
+        // Calculate the dimensions of each cell we are giving to each widget
+        final ArrayList<Object> items = new ArrayList<Object>();
+        int contentWidth = mWidgetSpacingLayout.getContentWidth();
+        final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft - mPageLayoutPaddingRight
+                - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
+        int contentHeight = mWidgetSpacingLayout.getContentHeight();
+        final int cellHeight = ((contentHeight - mPageLayoutPaddingTop - mPageLayoutPaddingBottom
+                - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);
+
+        // Prepare the set of widgets to load previews for in the background
+        int offset = (page - mNumAppsPages) * numItemsPerPage;
+        for (int i = offset; i < Math.min(offset + numItemsPerPage, mWidgets.size()); ++i) {
+            items.add(mWidgets.get(i));
+        }
+
+        // Prepopulate the pages with the other widget info, and fill in the previews later
+        final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
+        layout.setColumnCount(layout.getCellCountX());
+        for (int i = 0; i < items.size(); ++i) {
+            Object rawInfo = items.get(i);
+            PendingAddItemInfo createItemInfo = null;
+            PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
+                    R.layout.apps_customize_widget, layout, false);
+            if (rawInfo instanceof AppWidgetProviderInfo) {
+                // Fill in the widget information
+                AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
+                createItemInfo = new PendingAddWidgetInfo(info, null, null);
+
+                // Determine the widget spans and min resize spans.
+                int[] spanXY = Launcher.getSpanForWidget(mLauncher, info);
+                createItemInfo.spanX = spanXY[0];
+                createItemInfo.spanY = spanXY[1];
+                int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, info);
+                createItemInfo.minSpanX = minSpanXY[0];
+                createItemInfo.minSpanY = minSpanXY[1];
+
+                widget.applyFromAppWidgetProviderInfo(info, -1, spanXY);
+                widget.setTag(createItemInfo);
+                widget.setShortPressListener(this);
+            } else if (rawInfo instanceof ResolveInfo) {
+                // Fill in the shortcuts information
+                ResolveInfo info = (ResolveInfo) rawInfo;
+                createItemInfo = new PendingAddShortcutInfo(info.activityInfo);
+                createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+                createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
+                        info.activityInfo.name);
+                widget.applyFromResolveInfo(mPackageManager, info);
+                widget.setTag(createItemInfo);
+            }
+            widget.setOnClickListener(this);
+            widget.setOnLongClickListener(this);
+            widget.setOnTouchListener(this);
+            widget.setOnKeyListener(this);
+
+            // Layout each widget
+            int ix = i % mWidgetCountX;
+            int iy = i / mWidgetCountX;
+            GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
+                    GridLayout.spec(iy, GridLayout.LEFT),
+                    GridLayout.spec(ix, GridLayout.TOP));
+            lp.width = cellWidth;
+            lp.height = cellHeight;
+            lp.setGravity(Gravity.TOP | Gravity.LEFT);
+            if (ix > 0) lp.leftMargin = mWidgetWidthGap;
+            if (iy > 0) lp.topMargin = mWidgetHeightGap;
+            layout.addView(widget, lp);
+        }
+
+        // wait until a call on onLayout to start loading, because
+        // PagedViewWidget.getPreviewSize() will return 0 if it hasn't been laid out
+        // TODO: can we do a measure/layout immediately?
+        layout.setOnLayoutListener(new Runnable() {
+            public void run() {
+                // Load the widget previews
+                int maxPreviewWidth = cellWidth;
+                int maxPreviewHeight = cellHeight;
+                if (layout.getChildCount() > 0) {
+                    PagedViewWidget w = (PagedViewWidget) layout.getChildAt(0);
+                    int[] maxSize = w.getPreviewSize();
+                    maxPreviewWidth = maxSize[0];
+                    maxPreviewHeight = maxSize[1];
+                }
+                if (immediate) {
+                    AsyncTaskPageData data = new AsyncTaskPageData(page, items,
+                            maxPreviewWidth, maxPreviewHeight, null, null);
+                    loadWidgetPreviewsInBackground(null, data);
+                    onSyncWidgetPageItems(data);
+                } else {
+                    if (mInTransition) {
+                        mDeferredPrepareLoadWidgetPreviewsTasks.add(this);
+                    } else {
+                        prepareLoadWidgetPreviewsTask(page, items,
+                                maxPreviewWidth, maxPreviewHeight, mWidgetCountX);
+                    }
+                }
+            }
+        });
+    }
+    private void loadWidgetPreviewsInBackground(AppsCustomizeAsyncTask task,
+            AsyncTaskPageData data) {
+        // loadWidgetPreviewsInBackground can be called without a task to load a set of widget
+        // previews synchronously
+        if (task != null) {
+            // Ensure that this task starts running at the correct priority
+            task.syncThreadPriority();
+        }
+
+        // Load each of the widget/shortcut previews
+        ArrayList<Object> items = data.items;
+        ArrayList<Bitmap> images = data.generatedImages;
+        int count = items.size();
+        for (int i = 0; i < count; ++i) {
+            if (task != null) {
+                // Ensure we haven't been cancelled yet
+                if (task.isCancelled()) break;
+                // Before work on each item, ensure that this task is running at the correct
+                // priority
+                task.syncThreadPriority();
+            }
+
+            Object rawInfo = items.get(i);
+            if (rawInfo instanceof AppWidgetProviderInfo) {
+                AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
+                int[] cellSpans = Launcher.getSpanForWidget(mLauncher, info);
+
+                int maxWidth = Math.min(data.maxImageWidth,
+                        mWidgetSpacingLayout.estimateCellWidth(cellSpans[0]));
+                int maxHeight = Math.min(data.maxImageHeight,
+                        mWidgetSpacingLayout.estimateCellHeight(cellSpans[1]));
+                Bitmap b = getWidgetPreview(info.provider, info.previewImage, info.icon,
+                        cellSpans[0], cellSpans[1], maxWidth, maxHeight);
+                images.add(b);
+            } else if (rawInfo instanceof ResolveInfo) {
+                // Fill in the shortcuts information
+                ResolveInfo info = (ResolveInfo) rawInfo;
+                images.add(getShortcutPreview(info, data.maxImageWidth, data.maxImageHeight));
+            }
+        }
+    }
+
+    private void onSyncWidgetPageItems(AsyncTaskPageData data) {
+        if (mInTransition) {
+            mDeferredSyncWidgetPageItems.add(data);
+            return;
+        }
+        try {
+            int page = data.page;
+            PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page);
+
+            ArrayList<Object> items = data.items;
+            int count = items.size();
+            for (int i = 0; i < count; ++i) {
+                PagedViewWidget widget = (PagedViewWidget) layout.getChildAt(i);
+                if (widget != null) {
+                    Bitmap preview = data.generatedImages.get(i);
+                    widget.applyPreview(new FastBitmapDrawable(preview), i);
+                }
+            }
+
+            layout.createHardwareLayer();
+            invalidate();
+
+            // Update all thread priorities
+            Iterator<AppsCustomizeAsyncTask> iter = mRunningTasks.iterator();
+            while (iter.hasNext()) {
+                AppsCustomizeAsyncTask task = (AppsCustomizeAsyncTask) iter.next();
+                int pageIndex = task.page;
+                task.setThreadPriority(getThreadPriorityForPage(pageIndex));
+            }
+        } finally {
+            data.cleanup(false);
+        }
+    }
+
+    @Override
+    public void syncPages() {
+        removeAllViews();
+        cancelAllTasks();
+
+        Context context = getContext();
+        for (int j = 0; j < mNumWidgetPages; ++j) {
+            PagedViewGridLayout layout = new PagedViewGridLayout(context, mWidgetCountX,
+                    mWidgetCountY);
+            setupPage(layout);
+            addView(layout, new PagedView.LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT));
+        }
+
+        for (int i = 0; i < mNumAppsPages; ++i) {
+            PagedViewCellLayout layout = new PagedViewCellLayout(context);
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+
+    @Override
+    public void syncPageItems(int page, boolean immediate) {
+        if (page < mNumAppsPages) {
+            syncAppsPageItems(page, immediate);
+        } else {
+            syncWidgetPageItems(page, immediate);
+        }
+    }
+
+    // We want our pages to be z-ordered such that the further a page is to the left, the higher
+    // it is in the z-order. This is important to insure touch events are handled correctly.
+    View getPageAt(int index) {
+        return getChildAt(indexToPage(index));
+    }
+
+    @Override
+    protected int indexToPage(int index) {
+        return getChildCount() - index - 1;
+    }
+
+    // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
+    @Override
+    protected void screenScrolled(int screenCenter) {
+        super.screenScrolled(screenCenter);
+
+        for (int i = 0; i < getChildCount(); i++) {
+            View v = getPageAt(i);
+            if (v != null) {
+                float scrollProgress = getScrollProgress(screenCenter, v, i);
+
+                float interpolatedProgress =
+                        mZInterpolator.getInterpolation(Math.abs(Math.min(scrollProgress, 0)));
+                float scale = (1 - interpolatedProgress) +
+                        interpolatedProgress * TRANSITION_SCALE_FACTOR;
+                float translationX = Math.min(0, scrollProgress) * v.getMeasuredWidth();
+
+                float alpha;
+
+                if (scrollProgress < 0) {
+                    alpha = scrollProgress < 0 ? mAlphaInterpolator.getInterpolation(
+                        1 - Math.abs(scrollProgress)) : 1.0f;
+                } else {
+                    // On large screens we need to fade the page as it nears its leftmost position
+                    alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
+                }
+
+                v.setCameraDistance(mDensity * CAMERA_DISTANCE);
+                int pageWidth = v.getMeasuredWidth();
+                int pageHeight = v.getMeasuredHeight();
+
+                if (PERFORM_OVERSCROLL_ROTATION) {
+                    if (i == 0 && scrollProgress < 0) {
+                        // Overscroll to the left
+                        v.setPivotX(TRANSITION_PIVOT * pageWidth);
+                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
+                        scale = 1.0f;
+                        alpha = 1.0f;
+                        // On the first page, we don't want the page to have any lateral motion
+                        translationX = 0;
+                    } else if (i == getChildCount() - 1 && scrollProgress > 0) {
+                        // Overscroll to the right
+                        v.setPivotX((1 - TRANSITION_PIVOT) * pageWidth);
+                        v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
+                        scale = 1.0f;
+                        alpha = 1.0f;
+                        // On the last page, we don't want the page to have any lateral motion.
+                        translationX = 0;
+                    } else {
+                        v.setPivotY(pageHeight / 2.0f);
+                        v.setPivotX(pageWidth / 2.0f);
+                        v.setRotationY(0f);
+                    }
+                }
+
+                v.setTranslationX(translationX);
+                v.setScaleX(scale);
+                v.setScaleY(scale);
+                v.setAlpha(alpha);
+
+                // If the view has 0 alpha, we set it to be invisible so as to prevent
+                // it from accepting touches
+                if (alpha == 0) {
+                    v.setVisibility(INVISIBLE);
+                } else if (v.getVisibility() != VISIBLE) {
+                    v.setVisibility(VISIBLE);
+                }
+            }
+        }
+    }
+
+    protected void overScroll(float amount) {
+        acceleratedOverScroll(amount);
+    }
+
+    /**
+     * Used by the parent to get the content width to set the tab bar to
+     * @return
+     */
+    public int getPageContentWidth() {
+        return mContentWidth;
+    }
+
+    @Override
+    protected void onPageEndMoving() {
+        super.onPageEndMoving();
+        mForceDrawAllChildrenNextFrame = true;
+        // We reset the save index when we change pages so that it will be recalculated on next
+        // rotation
+        mSaveInstanceStateItemIndex = -1;
+    }
+
+    /*
+     * AllAppsView implementation
+     */
+    public void setup(Launcher launcher, DragController dragController) {
+        mLauncher = launcher;
+        mDragController = dragController;
+    }
+
+    /**
+     * We should call thise method whenever the core data changes (mApps, mWidgets) so that we can
+     * appropriately determine when to invalidate the PagedView page data.  In cases where the data
+     * has yet to be set, we can requestLayout() and wait for onDataReady() to be called in the
+     * next onMeasure() pass, which will trigger an invalidatePageData() itself.
+     */
+    private void invalidateOnDataChange() {
+        if (!isDataReady()) {
+            // The next layout pass will trigger data-ready if both widgets and apps are set, so
+            // request a layout to trigger the page data when ready.
+            requestLayout();
+        } else {
+            cancelAllTasks();
+            invalidatePageData();
+        }
+    }
+
+    public void setApps(ArrayList<ApplicationInfo> list) {
+        mApps = list;
+        Collections.sort(mApps, LauncherModel.getAppNameComparator());
+        updatePageCounts();
+        invalidateOnDataChange();
+    }
+    private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // We add it in place, in alphabetical order
+        int count = list.size();
+        for (int i = 0; i < count; ++i) {
+            ApplicationInfo info = list.get(i);
+            int index = Collections.binarySearch(mApps, info, LauncherModel.getAppNameComparator());
+            if (index < 0) {
+                mApps.add(-(index + 1), info);
+            }
+        }
+    }
+    public void addApps(ArrayList<ApplicationInfo> list) {
+        addAppsWithoutInvalidate(list);
+        updatePageCounts();
+        invalidateOnDataChange();
+    }
+    private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
+        ComponentName removeComponent = item.intent.getComponent();
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            if (info.intent.getComponent().equals(removeComponent)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    private int findAppByPackage(List<ApplicationInfo> list, String packageName) {
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            if (ItemInfo.getPackageName(info.intent).equals(packageName)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // loop through all the apps and remove apps that have the same component
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            int removeIndex = findAppByComponent(mApps, info);
+            if (removeIndex > -1) {
+                mApps.remove(removeIndex);
+            }
+        }
+    }
+    private void removeAppsWithPackageNameWithoutInvalidate(ArrayList<String> packageNames) {
+        // loop through all the package names and remove apps that have the same package name
+        for (String pn : packageNames) {
+            int removeIndex = findAppByPackage(mApps, pn);
+            while (removeIndex > -1) {
+                mApps.remove(removeIndex);
+                removeIndex = findAppByPackage(mApps, pn);
+            }
+        }
+    }
+    public void removeApps(ArrayList<String> packageNames) {
+        removeAppsWithPackageNameWithoutInvalidate(packageNames);
+        updatePageCounts();
+        invalidateOnDataChange();
+    }
+    public void updateApps(ArrayList<ApplicationInfo> list) {
+        // We remove and re-add the updated applications list because it's properties may have
+        // changed (ie. the title), and this will ensure that the items will be in their proper
+        // place in the list.
+        removeAppsWithoutInvalidate(list);
+        addAppsWithoutInvalidate(list);
+        updatePageCounts();
+        invalidateOnDataChange();
+    }
+
+    public void reset() {
+        // If we have reset, then we should not continue to restore the previous state
+        mSaveInstanceStateItemIndex = -1;
+
+        AppsCustomizeTabHost tabHost = getTabHost();
+        String tag = tabHost.getCurrentTabTag();
+        if (tag != null) {
+            if (!tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
+                tabHost.setCurrentTabFromContent(ContentType.Applications);
+            }
+        }
+
+        if (mCurrentPage != 0) {
+            invalidatePageData(0);
+        }
+    }
+
+    private AppsCustomizeTabHost getTabHost() {
+        return (AppsCustomizeTabHost) mLauncher.findViewById(R.id.apps_customize_pane);
+    }
+
+    public void dumpState() {
+        // TODO: Dump information related to current list of Applications, Widgets, etc.
+        ApplicationInfo.dumpApplicationInfoList(TAG, "mApps", mApps);
+        dumpAppWidgetProviderInfoList(TAG, "mWidgets", mWidgets);
+    }
+
+    private void dumpAppWidgetProviderInfoList(String tag, String label,
+            ArrayList<Object> list) {
+        Log.d(tag, label + " size=" + list.size());
+        for (Object i: list) {
+            if (i instanceof AppWidgetProviderInfo) {
+                AppWidgetProviderInfo info = (AppWidgetProviderInfo) i;
+                Log.d(tag, "   label=\"" + info.label + "\" previewImage=" + info.previewImage
+                        + " resizeMode=" + info.resizeMode + " configure=" + info.configure
+                        + " initialLayout=" + info.initialLayout
+                        + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight);
+            } else if (i instanceof ResolveInfo) {
+                ResolveInfo info = (ResolveInfo) i;
+                Log.d(tag, "   label=\"" + info.loadLabel(mPackageManager) + "\" icon="
+                        + info.icon);
+            }
+        }
+    }
+
+    public void surrender() {
+        // TODO: If we are in the middle of any process (ie. for holographic outlines, etc) we
+        // should stop this now.
+
+        // Stop all background tasks
+        cancelAllTasks();
+    }
+
+    @Override
+    public void iconPressed(PagedViewIcon icon) {
+        // Reset the previously pressed icon and store a reference to the pressed icon so that
+        // we can reset it on return to Launcher (in Launcher.onResume())
+        if (mPressedIcon != null) {
+            mPressedIcon.resetDrawableState();
+        }
+        mPressedIcon = icon;
+    }
+
+    public void resetDrawableState() {
+        if (mPressedIcon != null) {
+            mPressedIcon.resetDrawableState();
+            mPressedIcon = null;
+        }
+    }
+
+    /*
+     * We load an extra page on each side to prevent flashes from scrolling and loading of the
+     * widget previews in the background with the AsyncTasks.
+     */
+    final static int sLookBehindPageCount = 2;
+    final static int sLookAheadPageCount = 2;
+    protected int getAssociatedLowerPageBound(int page) {
+        final int count = getChildCount();
+        int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
+        int windowMinIndex = Math.max(Math.min(page - sLookBehindPageCount, count - windowSize), 0);
+        return windowMinIndex;
+    }
+    protected int getAssociatedUpperPageBound(int page) {
+        final int count = getChildCount();
+        int windowSize = Math.min(count, sLookBehindPageCount + sLookAheadPageCount + 1);
+        int windowMaxIndex = Math.min(Math.max(page + sLookAheadPageCount, windowSize - 1),
+                count - 1);
+        return windowMaxIndex;
+    }
+
+    @Override
+    protected String getCurrentPageDescription() {
+        int page = (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
+        int stringId = R.string.default_scroll_format;
+        int count = 0;
+        
+        if (page < mNumAppsPages) {
+            stringId = R.string.apps_customize_apps_scroll_format;
+            count = mNumAppsPages;
+        } else {
+            page -= mNumAppsPages;
+            stringId = R.string.apps_customize_widgets_scroll_format;
+            count = mNumWidgetPages;
+        }
+
+        return String.format(getContext().getString(stringId), page + 1, count);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/AppsCustomizeTabHost.java b/FairphoneHome/src/org/fairphone/launcher/AppsCustomizeTabHost.java
new file mode 100644
index 0000000..62d5482
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/AppsCustomizeTabHost.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+
+public class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable,
+        TabHost.OnTabChangeListener  {
+    static final String LOG_TAG = "AppsCustomizeTabHost";
+
+    private static final String APPS_TAB_TAG = "APPS";
+    private static final String WIDGETS_TAB_TAG = "WIDGETS";
+
+    private final LayoutInflater mLayoutInflater;
+    private ViewGroup mTabs;
+    private ViewGroup mTabsContainer;
+    private AppsCustomizePagedView mAppsCustomizePane;
+    private FrameLayout mAnimationBuffer;
+    private LinearLayout mContent;
+
+    private boolean mInTransition;
+    private boolean mTransitioningToWorkspace;
+    private boolean mResetAfterTransition;
+    private Runnable mRelayoutAndMakeVisible;
+
+    public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLayoutInflater = LayoutInflater.from(context);
+        mRelayoutAndMakeVisible = new Runnable() {
+                public void run() {
+                    mTabs.requestLayout();
+                    mTabsContainer.setAlpha(1f);
+                }
+            };
+    }
+
+    /**
+     * Convenience methods to select specific tabs.  We want to set the content type immediately
+     * in these cases, but we note that we still call setCurrentTabByTag() so that the tab view
+     * reflects the new content (but doesn't do the animation and logic associated with changing
+     * tabs manually).
+     */
+    void setContentTypeImmediate(AppsCustomizePagedView.ContentType type) {
+        setOnTabChangedListener(null);
+        onTabChangedStart();
+        onTabChangedEnd(type);
+        setCurrentTabByTag(getTabTagForContentType(type));
+        setOnTabChangedListener(this);
+    }
+    void selectAppsTab() {
+        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Applications);
+    }
+    void selectWidgetsTab() {
+        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Widgets);
+    }
+
+    /**
+     * Setup the tab host and create all necessary tabs.
+     */
+    @Override
+    protected void onFinishInflate() {
+        // Setup the tab host
+        setup();
+
+        final ViewGroup tabsContainer = (ViewGroup) findViewById(R.id.tabs_container);
+        final TabWidget tabs = getTabWidget();
+        final AppsCustomizePagedView appsCustomizePane = (AppsCustomizePagedView)
+                findViewById(R.id.apps_customize_pane_content);
+        mTabs = tabs;
+        mTabsContainer = tabsContainer;
+        mAppsCustomizePane = appsCustomizePane;
+        mAnimationBuffer = (FrameLayout) findViewById(R.id.animation_buffer);
+        mContent = (LinearLayout) findViewById(R.id.apps_customize_content);
+        if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException();
+
+        // Configure the tabs content factory to return the same paged view (that we change the
+        // content filter on)
+        TabContentFactory contentFactory = new TabContentFactory() {
+            public View createTabContent(String tag) {
+                return appsCustomizePane;
+            }
+        };
+
+        // Create the tabs
+        TextView tabView;
+        String label;
+        label = getContext().getString(R.string.all_apps_button_label);
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(label);
+        tabView.setContentDescription(label);
+        addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        label = getContext().getString(R.string.widgets_tab_label);
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(label);
+        tabView.setContentDescription(label);
+        addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        setOnTabChangedListener(this);
+
+        // Setup the key listener to jump between the last tab view and the market icon
+        AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener();
+        View lastTab = tabs.getChildTabViewAt(tabs.getTabCount() - 1);
+        lastTab.setOnKeyListener(keyListener);
+        View shopButton = findViewById(R.id.market_button);
+        shopButton.setOnKeyListener(keyListener);
+
+        // Hide the tab bar until we measure
+        mTabsContainer.setAlpha(0f);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        boolean remeasureTabWidth = (mTabs.getLayoutParams().width <= 0);
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        // Set the width of the tab list to the content width
+        if (remeasureTabWidth) {
+            int contentWidth = mAppsCustomizePane.getPageContentWidth();
+            if (contentWidth > 0 && mTabs.getLayoutParams().width != contentWidth) {
+                // Set the width and show the tab bar
+                mTabs.getLayoutParams().width = contentWidth;
+                mRelayoutAndMakeVisible.run();
+            }
+
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+     public boolean onInterceptTouchEvent(MotionEvent ev) {
+         // If we are mid transitioning to the workspace, then intercept touch events here so we
+         // can ignore them, otherwise we just let all apps handle the touch events.
+         if (mInTransition && mTransitioningToWorkspace) {
+             return true;
+         }
+         return super.onInterceptTouchEvent(ev);
+     };
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // Allow touch events to fall through to the workspace if we are transitioning there
+        if (mInTransition && mTransitioningToWorkspace) {
+            return super.onTouchEvent(event);
+        }
+
+        // Intercept all touch events up to the bottom of the AppsCustomizePane so they do not fall
+        // through to the workspace and trigger showWorkspace()
+        if (event.getY() < mAppsCustomizePane.getBottom()) {
+            return true;
+        }
+        return super.onTouchEvent(event);
+    }
+
+    private void onTabChangedStart() {
+        mAppsCustomizePane.hideScrollingIndicator(false);
+    }
+
+    private void reloadCurrentPage() {
+        if (!LauncherApplication.isScreenLarge()) {
+            mAppsCustomizePane.flashScrollingIndicator(true);
+        }
+        mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
+        mAppsCustomizePane.requestFocus();
+    }
+
+    private void onTabChangedEnd(AppsCustomizePagedView.ContentType type) {
+        mAppsCustomizePane.setContentType(type);
+    }
+
+    @Override
+    public void onTabChanged(String tabId) {
+        final AppsCustomizePagedView.ContentType type = getContentTypeForTabTag(tabId);
+
+        // Animate the changing of the tab content by fading pages in and out
+        final Resources res = getResources();
+        final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
+
+        // We post a runnable here because there is a delay while the first page is loading and
+        // the feedback from having changed the tab almost feels better than having it stick
+        post(new Runnable() {
+            @Override
+            public void run() {
+                if (mAppsCustomizePane.getMeasuredWidth() <= 0 ||
+                        mAppsCustomizePane.getMeasuredHeight() <= 0) {
+                    reloadCurrentPage();
+                    return;
+                }
+
+                // Take the visible pages and re-parent them temporarily to mAnimatorBuffer
+                // and then cross fade to the new pages
+                int[] visiblePageRange = new int[2];
+                mAppsCustomizePane.getVisiblePages(visiblePageRange);
+                if (visiblePageRange[0] == -1 && visiblePageRange[1] == -1) {
+                    // If we can't get the visible page ranges, then just skip the animation
+                    reloadCurrentPage();
+                    return;
+                }
+                ArrayList<View> visiblePages = new ArrayList<View>();
+                for (int i = visiblePageRange[0]; i <= visiblePageRange[1]; i++) {
+                    visiblePages.add(mAppsCustomizePane.getPageAt(i));
+                }
+
+                // We want the pages to be rendered in exactly the same way as they were when
+                // their parent was mAppsCustomizePane -- so set the scroll on mAnimationBuffer
+                // to be exactly the same as mAppsCustomizePane, and below, set the left/top
+                // parameters to be correct for each of the pages
+                mAnimationBuffer.scrollTo(mAppsCustomizePane.getScrollX(), 0);
+
+                // mAppsCustomizePane renders its children in reverse order, so
+                // add the pages to mAnimationBuffer in reverse order to match that behavior
+                for (int i = visiblePages.size() - 1; i >= 0; i--) {
+                    View child = visiblePages.get(i);
+                    if (child instanceof PagedViewCellLayout) {
+                        ((PagedViewCellLayout) child).resetChildrenOnKeyListeners();
+                    } else if (child instanceof PagedViewGridLayout) {
+                        ((PagedViewGridLayout) child).resetChildrenOnKeyListeners();
+                    }
+                    PagedViewWidget.setDeletePreviewsWhenDetachedFromWindow(false);
+                    mAppsCustomizePane.removeView(child);
+                    PagedViewWidget.setDeletePreviewsWhenDetachedFromWindow(true);
+                    mAnimationBuffer.setAlpha(1f);
+                    mAnimationBuffer.setVisibility(View.VISIBLE);
+                    LayoutParams p = new FrameLayout.LayoutParams(child.getMeasuredWidth(),
+                            child.getMeasuredHeight());
+                    p.setMargins((int) child.getLeft(), (int) child.getTop(), 0, 0);
+                    mAnimationBuffer.addView(child, p);
+                }
+
+                // Toggle the new content
+                onTabChangedStart();
+                onTabChangedEnd(type);
+
+                // Animate the transition
+                ObjectAnimator outAnim = LauncherAnimUtils.ofFloat(mAnimationBuffer, "alpha", 0f);
+                outAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mAnimationBuffer.setVisibility(View.GONE);
+                        mAnimationBuffer.removeAllViews();
+                    }
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+                        mAnimationBuffer.setVisibility(View.GONE);
+                        mAnimationBuffer.removeAllViews();
+                    }
+                });
+                ObjectAnimator inAnim = LauncherAnimUtils.ofFloat(mAppsCustomizePane, "alpha", 1f);
+                inAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        reloadCurrentPage();
+                    }
+                });
+
+                final AnimatorSet animSet = LauncherAnimUtils.createAnimatorSet();
+                animSet.playTogether(outAnim, inAnim);
+                animSet.setDuration(duration);
+                post(new Runnable() {
+                    public void run() {
+                        animSet.start();
+                    }
+                });
+            }
+        });
+    }
+
+    public void setCurrentTabFromContent(AppsCustomizePagedView.ContentType type) {
+        setOnTabChangedListener(null);
+        setCurrentTabByTag(getTabTagForContentType(type));
+        setOnTabChangedListener(this);
+    }
+
+    /**
+     * Returns the content type for the specified tab tag.
+     */
+    public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) {
+        if (tag.equals(APPS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Applications;
+        } else if (tag.equals(WIDGETS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Widgets;
+        }
+        return AppsCustomizePagedView.ContentType.Applications;
+    }
+
+    /**
+     * Returns the tab tag for a given content type.
+     */
+    public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) {
+        if (type == AppsCustomizePagedView.ContentType.Applications) {
+            return APPS_TAB_TAG;
+        } else if (type == AppsCustomizePagedView.ContentType.Widgets) {
+            return WIDGETS_TAB_TAG;
+        }
+        return APPS_TAB_TAG;
+    }
+
+    /**
+     * Disable focus on anything under this view in the hierarchy if we are not visible.
+     */
+    @Override
+    public int getDescendantFocusability() {
+        if (getVisibility() != View.VISIBLE) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
+
+    void reset() {
+        if (mInTransition) {
+            // Defer to after the transition to reset
+            mResetAfterTransition = true;
+        } else {
+            // Reset immediately
+            mAppsCustomizePane.reset();
+        }
+    }
+
+    private void enableAndBuildHardwareLayer() {
+        // isHardwareAccelerated() checks if we're attached to a window and if that
+        // window is HW accelerated-- we were sometimes not attached to a window
+        // and buildLayer was throwing an IllegalStateException
+        if (isHardwareAccelerated()) {
+            // Turn on hardware layers for performance
+            setLayerType(LAYER_TYPE_HARDWARE, null);
+
+            // force building the layer, so you don't get a blip early in an animation
+            // when the layer is created layer
+            buildLayer();
+        }
+    }
+
+    @Override
+    public View getContent() {
+        return mContent;
+    }
+
+    /* LauncherTransitionable overrides */
+    @Override
+    public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
+        mAppsCustomizePane.onLauncherTransitionPrepare(l, animated, toWorkspace);
+        mInTransition = true;
+        mTransitioningToWorkspace = toWorkspace;
+
+        if (toWorkspace) {
+            // Going from All Apps -> Workspace
+            setVisibilityOfSiblingsWithLowerZOrder(VISIBLE);
+            // Stop the scrolling indicator - we don't want All Apps to be invalidating itself
+            // during the transition, especially since it has a hardware layer set on it
+            mAppsCustomizePane.cancelScrollingIndicatorAnimations();
+        } else {
+            // Going from Workspace -> All Apps
+            mContent.setVisibility(VISIBLE);
+
+            // Make sure the current page is loaded (we start loading the side pages after the
+            // transition to prevent slowing down the animation)
+            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
+
+            if (!LauncherApplication.isScreenLarge()) {
+                mAppsCustomizePane.showScrollingIndicator(true);
+            }
+        }
+
+        if (mResetAfterTransition) {
+            mAppsCustomizePane.reset();
+            mResetAfterTransition = false;
+        }
+    }
+
+    @Override
+    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+        if (animated) {
+            enableAndBuildHardwareLayer();
+        }
+    }
+
+    @Override
+    public void onLauncherTransitionStep(Launcher l, float t) {
+        // Do nothing
+    }
+
+    @Override
+    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+        mAppsCustomizePane.onLauncherTransitionEnd(l, animated, toWorkspace);
+        mInTransition = false;
+        if (animated) {
+            setLayerType(LAYER_TYPE_NONE, null);
+        }
+
+        if (!toWorkspace) {
+            // Dismiss the workspace cling
+            l.dismissWorkspaceCling(null);
+            // Show the all apps cling (if not already shown)
+            mAppsCustomizePane.showAllAppsCling();
+            // Make sure adjacent pages are loaded (we wait until after the transition to
+            // prevent slowing down the animation)
+            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
+
+            if (!LauncherApplication.isScreenLarge()) {
+                mAppsCustomizePane.hideScrollingIndicator(false);
+            }
+
+            // Going from Workspace -> All Apps
+            // NOTE: We should do this at the end since we check visibility state in some of the
+            // cling initialization/dismiss code above.
+            setVisibilityOfSiblingsWithLowerZOrder(INVISIBLE);
+        }
+    }
+
+    private void setVisibilityOfSiblingsWithLowerZOrder(int visibility) {
+        ViewGroup parent = (ViewGroup) getParent();
+        if (parent == null) return;
+
+        final int count = parent.getChildCount();
+        if (!isChildrenDrawingOrderEnabled()) {
+            for (int i = 0; i < count; i++) {
+                final View child = parent.getChildAt(i);
+                if (child == this) {
+                    break;
+                } else {
+                    if (child.getVisibility() == GONE) {
+                        continue;
+                    }
+                    child.setVisibility(visibility);
+                }
+            }
+        } else {
+            throw new RuntimeException("Failed; can't get z-order of views");
+        }
+    }
+
+    public void onWindowVisible() {
+        if (getVisibility() == VISIBLE) {
+            mContent.setVisibility(VISIBLE);
+            // We unload the widget previews when the UI is hidden, so need to reload pages
+            // Load the current page synchronously, and the neighboring pages asynchronously
+            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
+            mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
+        }
+    }
+
+    public void onTrimMemory() {
+        mContent.setVisibility(GONE);
+        // Clear the widget pages of all their subviews - this will trigger the widget previews
+        // to delete their bitmaps
+        mAppsCustomizePane.clearAllWidgetPages();
+    }
+
+    boolean isTransitioning() {
+        return mInTransition;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/BubbleTextView.java b/FairphoneHome/src/org/fairphone/launcher/BubbleTextView.java
new file mode 100644
index 0000000..c2eb5aa
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/BubbleTextView.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.Region.Op;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.TextView;
+
+/**
+ * TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan
+ * because we want to make the bubble taller than the text and TextView's clip is
+ * too aggressive.
+ */
+public class BubbleTextView extends TextView {
+    static final float CORNER_RADIUS = 4.0f;
+    static final float SHADOW_LARGE_RADIUS = 4.0f;
+    static final float SHADOW_SMALL_RADIUS = 1.75f;
+    static final float SHADOW_Y_OFFSET = 2.0f;
+    static final int SHADOW_LARGE_COLOUR = 0xDD000000;
+    static final int SHADOW_SMALL_COLOUR = 0xCC000000;
+    static final float PADDING_H = 8.0f;
+    static final float PADDING_V = 3.0f;
+
+    private int mPrevAlpha = -1;
+
+    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
+    private final Canvas mTempCanvas = new Canvas();
+    private final Rect mTempRect = new Rect();
+    private boolean mDidInvalidateForPressedState;
+    private Bitmap mPressedOrFocusedBackground;
+    private int mFocusedOutlineColor;
+    private int mFocusedGlowColor;
+    private int mPressedOutlineColor;
+    private int mPressedGlowColor;
+
+    private boolean mBackgroundSizeChanged;
+    private Drawable mBackground;
+
+    private boolean mStayPressed;
+    private CheckLongPressHelper mLongPressHelper;
+
+    public BubbleTextView(Context context) {
+        super(context);
+        init();
+    }
+
+    public BubbleTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    private void init() {
+        mLongPressHelper = new CheckLongPressHelper(this);
+        mBackground = getBackground();
+
+        final Resources res = getContext().getResources();
+        mFocusedOutlineColor = mFocusedGlowColor = mPressedOutlineColor = mPressedGlowColor =
+            res.getColor(android.R.color.holo_blue_light);
+
+        setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
+    }
+
+    public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {
+        Bitmap b = info.getIcon(iconCache);
+
+        setCompoundDrawablesWithIntrinsicBounds(null,
+                new FastBitmapDrawable(b),
+                null, null);
+        setText(info.title);
+        setTag(info);
+    }
+
+    @Override
+    protected boolean setFrame(int left, int top, int right, int bottom) {
+        if (getLeft() != left || getRight() != right || getTop() != top || getBottom() != bottom) {
+            mBackgroundSizeChanged = true;
+        }
+        return super.setFrame(left, top, right, bottom);
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return who == mBackground || super.verifyDrawable(who);
+    }
+
+    @Override
+    public void setTag(Object tag) {
+        if (tag != null) {
+            LauncherModel.checkItemInfo((ItemInfo) tag);
+        }
+        super.setTag(tag);
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        if (isPressed()) {
+            // In this case, we have already created the pressed outline on ACTION_DOWN,
+            // so we just need to do an invalidate to trigger draw
+            if (!mDidInvalidateForPressedState) {
+                setCellLayoutPressedOrFocusedIcon();
+            }
+        } else {
+            // Otherwise, either clear the pressed/focused background, or create a background
+            // for the focused state
+            final boolean backgroundEmptyBefore = mPressedOrFocusedBackground == null;
+            if (!mStayPressed) {
+                mPressedOrFocusedBackground = null;
+            }
+            if (isFocused()) {
+                if (getLayout() == null) {
+                    // In some cases, we get focus before we have been layed out. Set the
+                    // background to null so that it will get created when the view is drawn.
+                    mPressedOrFocusedBackground = null;
+                } else {
+                    mPressedOrFocusedBackground = createGlowingOutline(
+                            mTempCanvas, mFocusedGlowColor, mFocusedOutlineColor);
+                }
+                mStayPressed = false;
+                setCellLayoutPressedOrFocusedIcon();
+            }
+            final boolean backgroundEmptyNow = mPressedOrFocusedBackground == null;
+            if (!backgroundEmptyBefore && backgroundEmptyNow) {
+                setCellLayoutPressedOrFocusedIcon();
+            }
+        }
+
+        Drawable d = mBackground;
+        if (d != null && d.isStateful()) {
+            d.setState(getDrawableState());
+        }
+        super.drawableStateChanged();
+    }
+
+    /**
+     * Draw this BubbleTextView into the given Canvas.
+     *
+     * @param destCanvas the canvas to draw on
+     * @param padding the horizontal and vertical padding to use when drawing
+     */
+    private void drawWithPadding(Canvas destCanvas, int padding) {
+        final Rect clipRect = mTempRect;
+        getDrawingRect(clipRect);
+
+        // adjust the clip rect so that we don't include the text label
+        clipRect.bottom =
+            getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + getLayout().getLineTop(0);
+
+        // Draw the View into the bitmap.
+        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
+        // they set scrollX and scrollY to large values to achieve centered text
+        destCanvas.save();
+        destCanvas.scale(getScaleX(), getScaleY(),
+                (getWidth() + padding) / 2, (getHeight() + padding) / 2);
+        destCanvas.translate(-getScrollX() + padding / 2, -getScrollY() + padding / 2);
+        destCanvas.clipRect(clipRect, Op.REPLACE);
+        draw(destCanvas);
+        destCanvas.restore();
+    }
+
+    /**
+     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
+     * Responsibility for the bitmap is transferred to the caller.
+     */
+    private Bitmap createGlowingOutline(Canvas canvas, int outlineColor, int glowColor) {
+        final int padding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
+        final Bitmap b = Bitmap.createBitmap(
+                getWidth() + padding, getHeight() + padding, Bitmap.Config.ARGB_8888);
+
+        canvas.setBitmap(b);
+        drawWithPadding(canvas, padding);
+        mOutlineHelper.applyExtraThickExpensiveOutlineWithBlur(b, canvas, glowColor, outlineColor);
+        canvas.setBitmap(null);
+
+        return b;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // Call the superclass onTouchEvent first, because sometimes it changes the state to
+        // isPressed() on an ACTION_UP
+        boolean result = super.onTouchEvent(event);
+
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                // So that the pressed outline is visible immediately when isPressed() is true,
+                // we pre-create it on ACTION_DOWN (it takes a small but perceptible amount of time
+                // to create it)
+                if (mPressedOrFocusedBackground == null) {
+                    mPressedOrFocusedBackground = createGlowingOutline(
+                            mTempCanvas, mPressedGlowColor, mPressedOutlineColor);
+                }
+                // Invalidate so the pressed state is visible, or set a flag so we know that we
+                // have to call invalidate as soon as the state is "pressed"
+                if (isPressed()) {
+                    mDidInvalidateForPressedState = true;
+                    setCellLayoutPressedOrFocusedIcon();
+                } else {
+                    mDidInvalidateForPressedState = false;
+                }
+
+                mLongPressHelper.postCheckForLongPress();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                // If we've touched down and up on an item, and it's still not "pressed", then
+                // destroy the pressed outline
+                if (!isPressed()) {
+                    mPressedOrFocusedBackground = null;
+                }
+
+                mLongPressHelper.cancelLongPress();
+                break;
+        }
+        return result;
+    }
+
+    void setStayPressed(boolean stayPressed) {
+        mStayPressed = stayPressed;
+        if (!stayPressed) {
+            mPressedOrFocusedBackground = null;
+        }
+        setCellLayoutPressedOrFocusedIcon();
+    }
+
+    void setCellLayoutPressedOrFocusedIcon() {
+        if (getParent() instanceof ShortcutAndWidgetContainer) {
+            ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) getParent();
+            if (parent != null) {
+                CellLayout layout = (CellLayout) parent.getParent();
+                layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null);
+            }
+        }
+    }
+
+    void clearPressedOrFocusedBackground() {
+        mPressedOrFocusedBackground = null;
+        setCellLayoutPressedOrFocusedIcon();
+    }
+
+    Bitmap getPressedOrFocusedBackground() {
+        return mPressedOrFocusedBackground;
+    }
+
+    int getPressedOrFocusedBackgroundPadding() {
+        return HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS / 2;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final Drawable background = mBackground;
+        if (background != null) {
+            final int scrollX = getScrollX();
+            final int scrollY = getScrollY();
+
+            if (mBackgroundSizeChanged) {
+                background.setBounds(0, 0,  getRight() - getLeft(), getBottom() - getTop());
+                mBackgroundSizeChanged = false;
+            }
+
+            if ((scrollX | scrollY) == 0) {
+                background.draw(canvas);
+            } else {
+                canvas.translate(scrollX, scrollY);
+                background.draw(canvas);
+                canvas.translate(-scrollX, -scrollY);
+            }
+        }
+
+        // If text is transparent, don't draw any shadow
+        if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) {
+            getPaint().clearShadowLayer();
+            super.draw(canvas);
+            return;
+        }
+
+        // We enhance the shadow by drawing the shadow twice
+        getPaint().setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
+        super.draw(canvas);
+        canvas.save(Canvas.CLIP_SAVE_FLAG);
+        canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(),
+                getScrollX() + getWidth(),
+                getScrollY() + getHeight(), Region.Op.INTERSECT);
+        getPaint().setShadowLayer(SHADOW_SMALL_RADIUS, 0.0f, 0.0f, SHADOW_SMALL_COLOUR);
+        super.draw(canvas);
+        canvas.restore();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mBackground != null) mBackground.setCallback(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mBackground != null) mBackground.setCallback(null);
+    }
+
+    @Override
+    protected boolean onSetAlpha(int alpha) {
+        if (mPrevAlpha != alpha) {
+            mPrevAlpha = alpha;
+            super.onSetAlpha(alpha);
+        }
+        return true;
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        mLongPressHelper.cancelLongPress();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/ButtonDropTarget.java b/FairphoneHome/src/org/fairphone/launcher/ButtonDropTarget.java
new file mode 100644
index 0000000..b3c31ff
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/ButtonDropTarget.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+
+/**
+ * Implements a DropTarget.
+ */
+public class ButtonDropTarget extends TextView implements DropTarget, DragController.DragListener {
+
+    protected final int mTransitionDuration;
+
+    protected Launcher mLauncher;
+    private int mBottomDragPadding;
+    protected TextView mText;
+    protected SearchDropTargetBar mSearchDropTargetBar;
+
+    /** Whether this drop target is active for the current drag */
+    protected boolean mActive;
+
+    /** The paint applied to the drag view on hover */
+    protected int mHoverColor = 0;
+
+    public ButtonDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ButtonDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        Resources r = getResources();
+        mTransitionDuration = r.getInteger(R.integer.config_dropTargetBgTransitionDuration);
+        mBottomDragPadding = r.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
+    }
+
+    void setLauncher(Launcher launcher) {
+        mLauncher = launcher;
+    }
+
+    public boolean acceptDrop(DragObject d) {
+        return false;
+    }
+
+    public void setSearchDropTargetBar(SearchDropTargetBar searchDropTargetBar) {
+        mSearchDropTargetBar = searchDropTargetBar;
+    }
+
+    protected Drawable getCurrentDrawable() {
+        Drawable[] drawables = getCompoundDrawables();
+        for (int i = 0; i < drawables.length; ++i) {
+            if (drawables[i] != null) {
+                return drawables[i];
+            }
+        }
+        return null;
+    }
+
+    public void onDrop(DragObject d) {
+    }
+
+    public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+        // Do nothing
+    }
+
+    public void onDragEnter(DragObject d) {
+        d.dragView.setColor(mHoverColor);
+    }
+
+    public void onDragOver(DragObject d) {
+        // Do nothing
+    }
+
+    public void onDragExit(DragObject d) {
+        d.dragView.setColor(0);
+    }
+
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        // Do nothing
+    }
+
+    public boolean isDropEnabled() {
+        return mActive;
+    }
+
+    public void onDragEnd() {
+        // Do nothing
+    }
+
+    @Override
+    public void getHitRect(android.graphics.Rect outRect) {
+        super.getHitRect(outRect);
+        outRect.bottom += mBottomDragPadding;
+    }
+
+    Rect getIconRect(int itemWidth, int itemHeight, int drawableWidth, int drawableHeight) {
+        DragLayer dragLayer = mLauncher.getDragLayer();
+
+        // Find the rect to animate to (the view is center aligned)
+        Rect to = new Rect();
+        dragLayer.getViewRectRelativeToSelf(this, to);
+        int width = drawableWidth;
+        int height = drawableHeight;
+        int left = to.left + getPaddingLeft();
+        int top = to.top + (getMeasuredHeight() - height) / 2;
+        to.set(left, top, left + width, top + height);
+
+        // Center the destination rect about the trash icon
+        int xOffset = (int) -(itemWidth - width) / 2;
+        int yOffset = (int) -(itemHeight - height) / 2;
+        to.offset(xOffset, yOffset);
+
+        return to;
+    }
+
+    @Override
+    public DropTarget getDropTargetDelegate(DragObject d) {
+        return null;
+    }
+
+    public void getLocationInDragLayer(int[] loc) {
+        mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/CellLayout.java b/FairphoneHome/src/org/fairphone/launcher/CellLayout.java
new file mode 100644
index 0000000..8ba0dea
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/CellLayout.java
@@ -0,0 +1,3329 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LayoutAnimationController;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Stack;
+
+import org.fairphone.launcher.FolderIcon.FolderRingAnimator;
+
+public class CellLayout extends ViewGroup {
+    static final String TAG = "CellLayout";
+
+    private Launcher mLauncher;
+    private int mCellWidth;
+    private int mCellHeight;
+
+    private int mCountX;
+    private int mCountY;
+
+    private int mOriginalWidthGap;
+    private int mOriginalHeightGap;
+    private int mWidthGap;
+    private int mHeightGap;
+    private int mMaxGap;
+    private boolean mScrollingTransformsDirty = false;
+
+    private final Rect mRect = new Rect();
+    private final CellInfo mCellInfo = new CellInfo();
+
+    // These are temporary variables to prevent having to allocate a new object just to
+    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
+    private final int[] mTmpXY = new int[2];
+    private final int[] mTmpPoint = new int[2];
+    int[] mTempLocation = new int[2];
+
+    boolean[][] mOccupied;
+    boolean[][] mTmpOccupied;
+    private boolean mLastDownOnOccupiedCell = false;
+
+    private OnTouchListener mInterceptTouchListener;
+
+    private ArrayList<FolderRingAnimator> mFolderOuterRings = new ArrayList<FolderRingAnimator>();
+    private int[] mFolderLeaveBehindCell = {-1, -1};
+
+    private int mForegroundAlpha = 0;
+    private float mBackgroundAlpha;
+    private float mBackgroundAlphaMultiplier = 1.0f;
+
+    private Drawable mNormalBackground;
+    private Drawable mActiveGlowBackground;
+    private Drawable mOverScrollForegroundDrawable;
+    private Drawable mOverScrollLeft;
+    private Drawable mOverScrollRight;
+    private Rect mBackgroundRect;
+    private Rect mForegroundRect;
+    private int mForegroundPadding;
+
+    // If we're actively dragging something over this screen, mIsDragOverlapping is true
+    private boolean mIsDragOverlapping = false;
+    private final Point mDragCenter = new Point();
+
+    // These arrays are used to implement the drag visualization on x-large screens.
+    // They are used as circular arrays, indexed by mDragOutlineCurrent.
+    private Rect[] mDragOutlines = new Rect[4];
+    private float[] mDragOutlineAlphas = new float[mDragOutlines.length];
+    private InterruptibleInOutAnimator[] mDragOutlineAnims =
+            new InterruptibleInOutAnimator[mDragOutlines.length];
+
+    // Used as an index into the above 3 arrays; indicates which is the most current value.
+    private int mDragOutlineCurrent = 0;
+    private final Paint mDragOutlinePaint = new Paint();
+
+    private BubbleTextView mPressedOrFocusedIcon;
+
+    private HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new
+            HashMap<CellLayout.LayoutParams, Animator>();
+    private HashMap<View, ReorderHintAnimation>
+            mShakeAnimators = new HashMap<View, ReorderHintAnimation>();
+
+    private boolean mItemPlacementDirty = false;
+
+    // When a drag operation is in progress, holds the nearest cell to the touch point
+    private final int[] mDragCell = new int[2];
+
+    private boolean mDragging = false;
+
+    private TimeInterpolator mEaseOutInterpolator;
+    private ShortcutAndWidgetContainer mShortcutsAndWidgets;
+
+    private boolean mIsHotseat = false;
+    private float mHotseatScale = 1f;
+
+    public static final int MODE_DRAG_OVER = 0;
+    public static final int MODE_ON_DROP = 1;
+    public static final int MODE_ON_DROP_EXTERNAL = 2;
+    public static final int MODE_ACCEPT_DROP = 3;
+    private static final boolean DESTRUCTIVE_REORDER = false;
+    private static final boolean DEBUG_VISUALIZE_OCCUPIED = false;
+
+    static final int LANDSCAPE = 0;
+    static final int PORTRAIT = 1;
+
+    private static final float REORDER_HINT_MAGNITUDE = 0.12f;
+    private static final int REORDER_ANIMATION_DURATION = 150;
+    private float mReorderHintAnimationMagnitude;
+
+    private ArrayList<View> mIntersectingViews = new ArrayList<View>();
+    private Rect mOccupiedRect = new Rect();
+    private int[] mDirectionVector = new int[2];
+    int[] mPreviousReorderDirection = new int[2];
+    private static final int INVALID_DIRECTION = -100;
+    private DropTarget.DragEnforcer mDragEnforcer;
+
+    private final static PorterDuffXfermode sAddBlendMode =
+            new PorterDuffXfermode(PorterDuff.Mode.ADD);
+    private final static Paint sPaint = new Paint();
+
+    public CellLayout(Context context) {
+        this(context, null);
+    }
+
+    public CellLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CellLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mDragEnforcer = new DropTarget.DragEnforcer(context);
+
+        // A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show
+        // the user where a dragged item will land when dropped.
+        setWillNotDraw(false);
+        mLauncher = (Launcher) context;
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
+
+        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
+       
+        mCountX = LauncherModel.getCellCountX();
+        mCountY = LauncherModel.getCellCountY();
+        
+        mCellWidth  = displayMetrics.widthPixels / mCountX; //a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10); // 180
+        mCellHeight = (displayMetrics.heightPixels - 48) / mCountY;//a.getDimensionPixelSize(R.styleable.CellLayout_cellHeight, 10); // 175
+        mWidthGap  = mOriginalWidthGap  = a.getDimensionPixelSize(R.styleable.CellLayout_widthGap, 0);
+        mHeightGap = mOriginalHeightGap = a.getDimensionPixelSize(R.styleable.CellLayout_heightGap, 0);
+        mMaxGap = a.getDimensionPixelSize(R.styleable.CellLayout_maxGap, 0);
+        
+        mOccupied = new boolean[mCountX][mCountY];
+        mTmpOccupied = new boolean[mCountX][mCountY];
+        mPreviousReorderDirection[0] = INVALID_DIRECTION;
+        mPreviousReorderDirection[1] = INVALID_DIRECTION;
+
+        a.recycle();
+
+        setAlwaysDrawnWithCacheEnabled(false);
+
+        final Resources res = getResources();
+        mHotseatScale = (res.getInteger(R.integer.hotseat_item_scale_percentage) / 100f);
+
+        mNormalBackground = res.getDrawable(R.drawable.homescreen_blue_normal_holo);
+        mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_blue_strong_holo);
+
+        mOverScrollLeft = res.getDrawable(R.drawable.overscroll_glow_left);
+        mOverScrollRight = res.getDrawable(R.drawable.overscroll_glow_right);
+        mForegroundPadding =
+                res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding);
+
+        mReorderHintAnimationMagnitude = (REORDER_HINT_MAGNITUDE *
+                res.getDimensionPixelSize(R.dimen.app_icon_size));
+
+        mNormalBackground.setFilterBitmap(true);
+        mActiveGlowBackground.setFilterBitmap(true);
+
+        // Initialize the data structures used for the drag visualization.
+
+        mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease out
+
+
+        mDragCell[0] = mDragCell[1] = -1;
+        for (int i = 0; i < mDragOutlines.length; i++) {
+            mDragOutlines[i] = new Rect(-1, -1, -1, -1);
+        }
+
+        // When dragging things around the home screens, we show a green outline of
+        // where the item will land. The outlines gradually fade out, leaving a trail
+        // behind the drag path.
+        // Set up all the animations that are used to implement this fading.
+        final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);
+        final float fromAlphaValue = 0;
+        final float toAlphaValue = (float)res.getInteger(R.integer.config_dragOutlineMaxAlpha);
+
+        Arrays.fill(mDragOutlineAlphas, fromAlphaValue);
+
+        for (int i = 0; i < mDragOutlineAnims.length; i++) {
+            final InterruptibleInOutAnimator anim =
+                new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
+            anim.getAnimator().setInterpolator(mEaseOutInterpolator);
+            final int thisIndex = i;
+            anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    final Bitmap outline = (Bitmap)anim.getTag();
+
+                    // If an animation is started and then stopped very quickly, we can still
+                    // get spurious updates we've cleared the tag. Guard against this.
+                    if (outline == null) {
+                        @SuppressWarnings("all") // suppress dead code warning
+                        final boolean debug = false;
+                        if (debug) {
+                            Object val = animation.getAnimatedValue();
+                            Log.d(TAG, "anim " + thisIndex + " update: " + val +
+                                     ", isStopped " + anim.isStopped());
+                        }
+                        // Try to prevent it from continuing to run
+                        animation.cancel();
+                    } else {
+                        mDragOutlineAlphas[thisIndex] = (Float) animation.getAnimatedValue();
+                        CellLayout.this.invalidate(mDragOutlines[thisIndex]);
+                    }
+                }
+            });
+            // The animation holds a reference to the drag outline bitmap as long is it's
+            // running. This way the bitmap can be GCed when the animations are complete.
+            anim.getAnimator().addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if ((Float) ((ValueAnimator) animation).getAnimatedValue() == 0f) {
+                        anim.setTag(null);
+                    }
+                }
+            });
+            mDragOutlineAnims[i] = anim;
+        }
+
+        mBackgroundRect = new Rect();
+        mForegroundRect = new Rect();
+
+        mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context);
+        mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
+        addView(mShortcutsAndWidgets);
+    }
+
+    static int widthInPortrait(Resources r, int numCells) {
+        // We use this method from Workspace to figure out how many rows/columns Launcher should
+        // have. We ignore the left/right padding on CellLayout because it turns out in our design
+        // the padding extends outside the visible screen size, but it looked fine anyway.
+        int cellWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
+        int minGap = Math.min(r.getDimensionPixelSize(R.dimen.workspace_width_gap),
+                r.getDimensionPixelSize(R.dimen.workspace_height_gap));
+
+        return  minGap * (numCells - 1) + cellWidth * numCells;
+    }
+
+    static int heightInLandscape(Resources r, int numCells) {
+        // We use this method from Workspace to figure out how many rows/columns Launcher should
+        // have. We ignore the left/right padding on CellLayout because it turns out in our design
+        // the padding extends outside the visible screen size, but it looked fine anyway.
+        int cellHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
+        int minGap = Math.min(r.getDimensionPixelSize(R.dimen.workspace_width_gap),
+                r.getDimensionPixelSize(R.dimen.workspace_height_gap));
+
+        return minGap * (numCells - 1) + cellHeight * numCells;
+    }
+
+    public void enableHardwareLayers() {
+        mShortcutsAndWidgets.setLayerType(LAYER_TYPE_HARDWARE, sPaint);
+    }
+
+    public void disableHardwareLayers() {
+        mShortcutsAndWidgets.setLayerType(LAYER_TYPE_NONE, sPaint);
+    }
+
+    public void buildHardwareLayer() {
+        mShortcutsAndWidgets.buildLayer();
+    }
+
+    public float getChildrenScale() {
+        return mIsHotseat ? mHotseatScale : 1.0f;
+    }
+
+    public void setGridSize(int x, int y) {
+        mCountX = x;
+        mCountY = y;
+        mOccupied = new boolean[mCountX][mCountY];
+        mTmpOccupied = new boolean[mCountX][mCountY];
+        mTempRectStack.clear();
+        requestLayout();
+    }
+
+    private void invalidateBubbleTextView(BubbleTextView icon) {
+        final int padding = icon.getPressedOrFocusedBackgroundPadding();
+        invalidate(icon.getLeft() + getPaddingLeft() - padding,
+                icon.getTop() + getPaddingTop() - padding,
+                icon.getRight() + getPaddingLeft() + padding,
+                icon.getBottom() + getPaddingTop() + padding);
+    }
+
+    void setOverScrollAmount(float r, boolean left) {
+        if (left && mOverScrollForegroundDrawable != mOverScrollLeft) {
+            mOverScrollForegroundDrawable = mOverScrollLeft;
+        } else if (!left && mOverScrollForegroundDrawable != mOverScrollRight) {
+            mOverScrollForegroundDrawable = mOverScrollRight;
+        }
+
+        mForegroundAlpha = (int) Math.round((r * 255));
+        mOverScrollForegroundDrawable.setAlpha(mForegroundAlpha);
+        invalidate();
+    }
+
+    void setPressedOrFocusedIcon(BubbleTextView icon) {
+        // We draw the pressed or focused BubbleTextView's background in CellLayout because it
+        // requires an expanded clip rect (due to the glow's blur radius)
+        BubbleTextView oldIcon = mPressedOrFocusedIcon;
+        mPressedOrFocusedIcon = icon;
+        if (oldIcon != null) {
+            invalidateBubbleTextView(oldIcon);
+        }
+        if (mPressedOrFocusedIcon != null) {
+            invalidateBubbleTextView(mPressedOrFocusedIcon);
+        }
+    }
+
+    void setIsDragOverlapping(boolean isDragOverlapping) {
+        if (mIsDragOverlapping != isDragOverlapping) {
+            mIsDragOverlapping = isDragOverlapping;
+            invalidate();
+        }
+    }
+
+    boolean getIsDragOverlapping() {
+        return mIsDragOverlapping;
+    }
+
+    protected void setOverscrollTransformsDirty(boolean dirty) {
+        mScrollingTransformsDirty = dirty;
+    }
+
+    protected void resetOverscrollTransforms() {
+        if (mScrollingTransformsDirty) {
+            setOverscrollTransformsDirty(false);
+            setTranslationX(0);
+            setRotationY(0);
+            // It doesn't matter if we pass true or false here, the important thing is that we
+            // pass 0, which results in the overscroll drawable not being drawn any more.
+            setOverScrollAmount(0, false);
+            setPivotX(getMeasuredWidth() / 2);
+            setPivotY(getMeasuredHeight() / 2);
+        }
+    }
+
+    public void scaleRect(Rect r, float scale) {
+        if (scale != 1.0f) {
+            r.left = (int) (r.left * scale + 0.5f);
+            r.top = (int) (r.top * scale + 0.5f);
+            r.right = (int) (r.right * scale + 0.5f);
+            r.bottom = (int) (r.bottom * scale + 0.5f);
+        }
+    }
+
+    Rect temp = new Rect();
+    void scaleRectAboutCenter(Rect in, Rect out, float scale) {
+        int cx = in.centerX();
+        int cy = in.centerY();
+        out.set(in);
+        out.offset(-cx, -cy);
+        scaleRect(out, scale);
+        out.offset(cx, cy);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        // When we're large, we are either drawn in a "hover" state (ie when dragging an item to
+        // a neighboring page) or with just a normal background (if backgroundAlpha > 0.0f)
+        // When we're small, we are either drawn normally or in the "accepts drops" state (during
+        // a drag). However, we also drag the mini hover background *over* one of those two
+        // backgrounds
+        if (mBackgroundAlpha > 0.0f) {
+            Drawable bg;
+
+            if (mIsDragOverlapping) {
+                // In the mini case, we draw the active_glow bg *over* the active background
+                bg = mActiveGlowBackground;
+            } else {
+                bg = mNormalBackground;
+            }
+
+            bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
+            bg.setBounds(mBackgroundRect);
+            bg.draw(canvas);
+        }
+
+        final Paint paint = mDragOutlinePaint;
+        for (int i = 0; i < mDragOutlines.length; i++) {
+            final float alpha = mDragOutlineAlphas[i];
+            if (alpha > 0) {
+                final Rect r = mDragOutlines[i];
+                scaleRectAboutCenter(r, temp, getChildrenScale());
+                final Bitmap b = (Bitmap) mDragOutlineAnims[i].getTag();
+                paint.setAlpha((int)(alpha + .5f));
+                canvas.drawBitmap(b, null, temp, paint);
+            }
+        }
+
+        // We draw the pressed or focused BubbleTextView's background in CellLayout because it
+        // requires an expanded clip rect (due to the glow's blur radius)
+        if (mPressedOrFocusedIcon != null) {
+            final int padding = mPressedOrFocusedIcon.getPressedOrFocusedBackgroundPadding();
+            final Bitmap b = mPressedOrFocusedIcon.getPressedOrFocusedBackground();
+            if (b != null) {
+                canvas.drawBitmap(b,
+                        mPressedOrFocusedIcon.getLeft() + getPaddingLeft() - padding,
+                        mPressedOrFocusedIcon.getTop() + getPaddingTop() - padding,
+                        null);
+            }
+        }
+
+        if (DEBUG_VISUALIZE_OCCUPIED) {
+            int[] pt = new int[2];
+            ColorDrawable cd = new ColorDrawable(Color.RED);
+            cd.setBounds(0, 0,  mCellWidth, mCellHeight);
+            for (int i = 0; i < mCountX; i++) {
+                for (int j = 0; j < mCountY; j++) {
+                    if (mOccupied[i][j]) {
+                        cellToPoint(i, j, pt);
+                        canvas.save();
+                        canvas.translate(pt[0], pt[1]);
+                        cd.draw(canvas);
+                        canvas.restore();
+                    }
+                }
+            }
+        }
+
+        int previewOffset = FolderRingAnimator.sPreviewSize;
+
+        // The folder outer / inner ring image(s)
+        for (int i = 0; i < mFolderOuterRings.size(); i++) {
+            FolderRingAnimator fra = mFolderOuterRings.get(i);
+
+            // Draw outer ring
+            Drawable d = FolderRingAnimator.sSharedOuterRingDrawable;
+            int width = (int) fra.getOuterRingSize();
+            int height = width;
+            cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
+
+            int centerX = mTempLocation[0] + mCellWidth / 2;
+            int centerY = mTempLocation[1] + previewOffset / 2;
+
+            canvas.save();
+            canvas.translate(centerX - width / 2, centerY - height / 2);
+            d.setBounds(0, 0, width, height);
+            d.draw(canvas);
+            canvas.restore();
+
+            // Draw inner ring
+            d = FolderRingAnimator.sSharedInnerRingDrawable;
+            width = (int) fra.getInnerRingSize();
+            height = width;
+            cellToPoint(fra.mCellX, fra.mCellY, mTempLocation);
+
+            centerX = mTempLocation[0] + mCellWidth / 2;
+            centerY = mTempLocation[1] + previewOffset / 2;
+            canvas.save();
+            canvas.translate(centerX - width / 2, centerY - width / 2);
+            d.setBounds(0, 0, width, height);
+            d.draw(canvas);
+            canvas.restore();
+        }
+
+        if (mFolderLeaveBehindCell[0] >= 0 && mFolderLeaveBehindCell[1] >= 0) {
+            Drawable d = FolderIcon.sSharedFolderLeaveBehind;
+            int width = d.getIntrinsicWidth();
+            int height = d.getIntrinsicHeight();
+
+            cellToPoint(mFolderLeaveBehindCell[0], mFolderLeaveBehindCell[1], mTempLocation);
+            int centerX = mTempLocation[0] + mCellWidth / 2;
+            int centerY = mTempLocation[1] + previewOffset / 2;
+
+            canvas.save();
+            canvas.translate(centerX - width / 2, centerY - width / 2);
+            d.setBounds(0, 0, width, height);
+            d.draw(canvas);
+            canvas.restore();
+        }
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mForegroundAlpha > 0) {
+            mOverScrollForegroundDrawable.setBounds(mForegroundRect);
+            Paint p = ((NinePatchDrawable) mOverScrollForegroundDrawable).getPaint();
+            p.setXfermode(sAddBlendMode);
+            mOverScrollForegroundDrawable.draw(canvas);
+            p.setXfermode(null);
+        }
+    }
+
+    public void showFolderAccept(FolderRingAnimator fra) {
+        mFolderOuterRings.add(fra);
+    }
+
+    public void hideFolderAccept(FolderRingAnimator fra) {
+        if (mFolderOuterRings.contains(fra)) {
+            mFolderOuterRings.remove(fra);
+        }
+        invalidate();
+    }
+
+    public void setFolderLeaveBehindCell(int x, int y) {
+        mFolderLeaveBehindCell[0] = x;
+        mFolderLeaveBehindCell[1] = y;
+        invalidate();
+    }
+
+    public void clearFolderLeaveBehind() {
+        mFolderLeaveBehindCell[0] = -1;
+        mFolderLeaveBehindCell[1] = -1;
+        invalidate();
+    }
+
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
+    public void restoreInstanceState(SparseArray<Parcelable> states) {
+        dispatchRestoreInstanceState(states);
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        // Cancel long press for all children
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.cancelLongPress();
+        }
+    }
+
+    public void setOnInterceptTouchListener(View.OnTouchListener listener) {
+        mInterceptTouchListener = listener;
+    }
+
+    int getCountX() {
+        return mCountX;
+    }
+
+    int getCountY() {
+        return mCountY;
+    }
+
+    public void setIsHotseat(boolean isHotseat) {
+        mIsHotseat = isHotseat;
+    }
+
+    public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params,
+            boolean markCells) {
+        final LayoutParams lp = params;
+
+        // Hotseat icons - remove text
+        if (child instanceof BubbleTextView) {
+            BubbleTextView bubbleChild = (BubbleTextView) child;
+
+            Resources res = getResources();
+            if (mIsHotseat) {
+                bubbleChild.setTextColor(res.getColor(android.R.color.transparent));
+            } else {
+                bubbleChild.setTextColor(res.getColor(R.color.workspace_icon_text_color));
+            }
+        }
+
+        child.setScaleX(getChildrenScale());
+        child.setScaleY(getChildrenScale());
+
+        // Generate an id for each view, this assumes we have at most 256x256 cells
+        // per workspace screen
+        if (lp.cellX >= 0 && lp.cellX <= mCountX - 1 && lp.cellY >= 0 && lp.cellY <= mCountY - 1) {
+            // If the horizontal or vertical span is set to -1, it is taken to
+            // mean that it spans the extent of the CellLayout
+            if (lp.cellHSpan < 0) lp.cellHSpan = mCountX;
+            if (lp.cellVSpan < 0) lp.cellVSpan = mCountY;
+
+            child.setId(childId);
+
+            mShortcutsAndWidgets.addView(child, index, lp);
+
+            if (markCells) markCellsAsOccupiedForView(child);
+
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void removeAllViews() {
+        clearOccupiedCells();
+        mShortcutsAndWidgets.removeAllViews();
+    }
+
+    @Override
+    public void removeAllViewsInLayout() {
+        if (mShortcutsAndWidgets.getChildCount() > 0) {
+            clearOccupiedCells();
+            mShortcutsAndWidgets.removeAllViewsInLayout();
+        }
+    }
+
+    public void removeViewWithoutMarkingCells(View view) {
+        mShortcutsAndWidgets.removeView(view);
+    }
+
+    @Override
+    public void removeView(View view) {
+        markCellsAsUnoccupiedForView(view);
+        mShortcutsAndWidgets.removeView(view);
+    }
+
+    @Override
+    public void removeViewAt(int index) {
+        markCellsAsUnoccupiedForView(mShortcutsAndWidgets.getChildAt(index));
+        mShortcutsAndWidgets.removeViewAt(index);
+    }
+
+    @Override
+    public void removeViewInLayout(View view) {
+        markCellsAsUnoccupiedForView(view);
+        mShortcutsAndWidgets.removeViewInLayout(view);
+    }
+
+    @Override
+    public void removeViews(int start, int count) {
+        for (int i = start; i < start + count; i++) {
+            markCellsAsUnoccupiedForView(mShortcutsAndWidgets.getChildAt(i));
+        }
+        mShortcutsAndWidgets.removeViews(start, count);
+    }
+
+    @Override
+    public void removeViewsInLayout(int start, int count) {
+        for (int i = start; i < start + count; i++) {
+            markCellsAsUnoccupiedForView(mShortcutsAndWidgets.getChildAt(i));
+        }
+        mShortcutsAndWidgets.removeViewsInLayout(start, count);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mCellInfo.screen = ((ViewGroup) getParent()).indexOfChild(this);
+    }
+
+    public void setTagToCellInfoForPoint(int touchX, int touchY) {
+        final CellInfo cellInfo = mCellInfo;
+        Rect frame = mRect;
+        final int x = touchX + getScrollX();
+        final int y = touchY + getScrollY();
+        final int count = mShortcutsAndWidgets.getChildCount();
+
+        boolean found = false;
+        for (int i = count - 1; i >= 0; i--) {
+            final View child = mShortcutsAndWidgets.getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            if ((child.getVisibility() == VISIBLE || child.getAnimation() != null) &&
+                    lp.isLockedToGrid) {
+                child.getHitRect(frame);
+
+                float scale = child.getScaleX();
+                frame = new Rect(child.getLeft(), child.getTop(), child.getRight(),
+                        child.getBottom());
+                // The child hit rect is relative to the CellLayoutChildren parent, so we need to
+                // offset that by this CellLayout's padding to test an (x,y) point that is relative
+                // to this view.
+                frame.offset(getPaddingLeft(), getPaddingTop());
+                frame.inset((int) (frame.width() * (1f - scale) / 2),
+                        (int) (frame.height() * (1f - scale) / 2));
+
+                if (frame.contains(x, y)) {
+                    cellInfo.cell = child;
+                    cellInfo.cellX = lp.cellX;
+                    cellInfo.cellY = lp.cellY;
+                    cellInfo.spanX = lp.cellHSpan;
+                    cellInfo.spanY = lp.cellVSpan;
+                    found = true;
+                    break;
+                }
+            }
+        }
+
+        mLastDownOnOccupiedCell = found;
+
+        if (!found) {
+            final int cellXY[] = mTmpXY;
+            pointToCellExact(x, y, cellXY);
+
+            cellInfo.cell = null;
+            cellInfo.cellX = cellXY[0];
+            cellInfo.cellY = cellXY[1];
+            cellInfo.spanX = 1;
+            cellInfo.spanY = 1;
+        }
+        setTag(cellInfo);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // First we clear the tag to ensure that on every touch down we start with a fresh slate,
+        // even in the case where we return early. Not clearing here was causing bugs whereby on
+        // long-press we'd end up picking up an item from a previous drag operation.
+        final int action = ev.getAction();
+
+        if (action == MotionEvent.ACTION_DOWN) {
+            clearTagCellInfo();
+        }
+
+        if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) {
+            return true;
+        }
+
+        if (action == MotionEvent.ACTION_DOWN) {
+            setTagToCellInfoForPoint((int) ev.getX(), (int) ev.getY());
+        }
+
+        return false;
+    }
+
+    private void clearTagCellInfo() {
+        final CellInfo cellInfo = mCellInfo;
+        cellInfo.cell = null;
+        cellInfo.cellX = -1;
+        cellInfo.cellY = -1;
+        cellInfo.spanX = 0;
+        cellInfo.spanY = 0;
+        setTag(cellInfo);
+    }
+
+    public CellInfo getTag() {
+        return (CellInfo) super.getTag();
+    }
+
+    /**
+     * Given a point, return the cell that strictly encloses that point
+     * @param x X coordinate of the point
+     * @param y Y coordinate of the point
+     * @param result Array of 2 ints to hold the x and y coordinate of the cell
+     */
+    void pointToCellExact(int x, int y, int[] result) {
+        final int hStartPadding = getPaddingLeft();
+        final int vStartPadding = getPaddingTop();
+
+        result[0] = (x - hStartPadding) / (mCellWidth + mWidthGap);
+        result[1] = (y - vStartPadding) / (mCellHeight + mHeightGap);
+
+        final int xAxis = mCountX;
+        final int yAxis = mCountY;
+
+        if (result[0] < 0) result[0] = 0;
+        if (result[0] >= xAxis) result[0] = xAxis - 1;
+        if (result[1] < 0) result[1] = 0;
+        if (result[1] >= yAxis) result[1] = yAxis - 1;
+    }
+
+    /**
+     * Given a point, return the cell that most closely encloses that point
+     * @param x X coordinate of the point
+     * @param y Y coordinate of the point
+     * @param result Array of 2 ints to hold the x and y coordinate of the cell
+     */
+    void pointToCellRounded(int x, int y, int[] result) {
+        pointToCellExact(x + (mCellWidth / 2), y + (mCellHeight / 2), result);
+    }
+
+    /**
+     * Given a cell coordinate, return the point that represents the upper left corner of that cell
+     *
+     * @param cellX X coordinate of the cell
+     * @param cellY Y coordinate of the cell
+     *
+     * @param result Array of 2 ints to hold the x and y coordinate of the point
+     */
+    void cellToPoint(int cellX, int cellY, int[] result) {
+        final int hStartPadding = getPaddingLeft();
+        final int vStartPadding = getPaddingTop();
+
+        result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap);
+        result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap);
+    }
+
+    /**
+     * Given a cell coordinate, return the point that represents the center of the cell
+     *
+     * @param cellX X coordinate of the cell
+     * @param cellY Y coordinate of the cell
+     *
+     * @param result Array of 2 ints to hold the x and y coordinate of the point
+     */
+    void cellToCenterPoint(int cellX, int cellY, int[] result) {
+        regionToCenterPoint(cellX, cellY, 1, 1, result);
+    }
+
+    /**
+     * Given a cell coordinate and span return the point that represents the center of the regio
+     *
+     * @param cellX X coordinate of the cell
+     * @param cellY Y coordinate of the cell
+     *
+     * @param result Array of 2 ints to hold the x and y coordinate of the point
+     */
+    void regionToCenterPoint(int cellX, int cellY, int spanX, int spanY, int[] result) {
+        final int hStartPadding = getPaddingLeft();
+        final int vStartPadding = getPaddingTop();
+        result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap) +
+                (spanX * mCellWidth + (spanX - 1) * mWidthGap) / 2;
+        result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap) +
+                (spanY * mCellHeight + (spanY - 1) * mHeightGap) / 2;
+    }
+
+     /**
+     * Given a cell coordinate and span fills out a corresponding pixel rect
+     *
+     * @param cellX X coordinate of the cell
+     * @param cellY Y coordinate of the cell
+     * @param result Rect in which to write the result
+     */
+     void regionToRect(int cellX, int cellY, int spanX, int spanY, Rect result) {
+        final int hStartPadding = getPaddingLeft();
+        final int vStartPadding = getPaddingTop();
+        final int left = hStartPadding + cellX * (mCellWidth + mWidthGap);
+        final int top = vStartPadding + cellY * (mCellHeight + mHeightGap);
+        result.set(left, top, left + (spanX * mCellWidth + (spanX - 1) * mWidthGap),
+                top + (spanY * mCellHeight + (spanY - 1) * mHeightGap));
+    }
+
+    public float getDistanceFromCell(float x, float y, int[] cell) {
+        cellToCenterPoint(cell[0], cell[1], mTmpPoint);
+        float distance = (float) Math.sqrt( Math.pow(x - mTmpPoint[0], 2) +
+                Math.pow(y - mTmpPoint[1], 2));
+        return distance;
+    }
+
+    int getCellWidth() {
+        return mCellWidth;
+    }
+
+    int getCellHeight() {
+        return mCellHeight;
+    }
+
+    int getWidthGap() {
+        return mWidthGap;
+    }
+
+    int getHeightGap() {
+        return mHeightGap;
+    }
+
+    Rect getContentRect(Rect r) {
+        if (r == null) {
+            r = new Rect();
+        }
+        int left = getPaddingLeft();
+        int top = getPaddingTop();
+        int right = left + getWidth() - getPaddingLeft() - getPaddingRight();
+        int bottom = top + getHeight() - getPaddingTop() - getPaddingBottom();
+        r.set(left, top, right, bottom);
+        return r;
+    }
+
+    static void getMetrics(Rect metrics, Resources res, int measureWidth, int measureHeight,
+            int countX, int countY, int orientation) {
+        int numWidthGaps = countX - 1;
+        int numHeightGaps = countY - 1;
+
+        int widthGap;
+        int heightGap;
+        int cellWidth;
+        int cellHeight;
+        int paddingLeft;
+        int paddingRight;
+        int paddingTop;
+        int paddingBottom;
+
+        int maxGap = res.getDimensionPixelSize(R.dimen.workspace_max_gap);
+        if (orientation == LANDSCAPE) {
+            cellWidth = res.getDimensionPixelSize(R.dimen.workspace_cell_width_land);
+            cellHeight = res.getDimensionPixelSize(R.dimen.workspace_cell_height_land);
+            widthGap = res.getDimensionPixelSize(R.dimen.workspace_width_gap_land);
+            heightGap = res.getDimensionPixelSize(R.dimen.workspace_height_gap_land);
+            paddingLeft = res.getDimensionPixelSize(R.dimen.cell_layout_left_padding_land);
+            paddingRight = res.getDimensionPixelSize(R.dimen.cell_layout_right_padding_land);
+            paddingTop = res.getDimensionPixelSize(R.dimen.cell_layout_top_padding_land);
+            paddingBottom = res.getDimensionPixelSize(R.dimen.cell_layout_bottom_padding_land);
+        } else {
+            // PORTRAIT
+            cellWidth = res.getDimensionPixelSize(R.dimen.workspace_cell_width_port);
+            cellHeight = res.getDimensionPixelSize(R.dimen.workspace_cell_height_port);
+            widthGap = res.getDimensionPixelSize(R.dimen.workspace_width_gap_port);
+            heightGap = res.getDimensionPixelSize(R.dimen.workspace_height_gap_port);
+            paddingLeft = res.getDimensionPixelSize(R.dimen.cell_layout_left_padding_port);
+            paddingRight = res.getDimensionPixelSize(R.dimen.cell_layout_right_padding_port);
+            paddingTop = res.getDimensionPixelSize(R.dimen.cell_layout_top_padding_port);
+            paddingBottom = res.getDimensionPixelSize(R.dimen.cell_layout_bottom_padding_port);
+        }
+
+        if (widthGap < 0 || heightGap < 0) {
+            int hSpace = measureWidth - paddingLeft - paddingRight;
+            int vSpace = measureHeight - paddingTop - paddingBottom;
+            int hFreeSpace = hSpace - (countX * cellWidth);
+            int vFreeSpace = vSpace - (countY * cellHeight);
+            widthGap = Math.min(maxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
+            heightGap = Math.min(maxGap, numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
+        }
+        metrics.set(cellWidth, cellHeight, widthGap, heightGap);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+
+        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
+
+        if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
+            throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
+        }
+
+        int numWidthGaps = mCountX - 1;
+        int numHeightGaps = mCountY - 1;
+
+        if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
+            int hSpace = widthSpecSize - getPaddingLeft() - getPaddingRight();
+            int vSpace = heightSpecSize - getPaddingTop() - getPaddingBottom();
+            int hFreeSpace = hSpace - (mCountX * mCellWidth);
+            int vFreeSpace = vSpace - (mCountY * mCellHeight);
+            mWidthGap = Math.min(mMaxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
+            mHeightGap = Math.min(mMaxGap,numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
+            mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
+        } else {
+            mWidthGap = mOriginalWidthGap;
+            mHeightGap = mOriginalHeightGap;
+        }
+
+        // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
+        int newWidth = widthSpecSize;
+        int newHeight = heightSpecSize;
+        if (widthSpecMode == MeasureSpec.AT_MOST) {
+            newWidth = getPaddingLeft() + getPaddingRight() + (mCountX * mCellWidth) +
+                ((mCountX - 1) * mWidthGap);
+            newHeight = getPaddingTop() + getPaddingBottom() + (mCountY * mCellHeight) +
+                ((mCountY - 1) * mHeightGap);
+            setMeasuredDimension(newWidth, newHeight);
+        }
+
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth - getPaddingLeft() -
+                    getPaddingRight(), MeasureSpec.EXACTLY);
+            int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight - getPaddingTop() -
+                    getPaddingBottom(), MeasureSpec.EXACTLY);
+            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+        }
+        setMeasuredDimension(newWidth, newHeight);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            child.layout(getPaddingLeft(), getPaddingTop(),
+                    r - l - getPaddingRight(), b - t - getPaddingBottom());
+        }
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mBackgroundRect.set(0, 0, w, h);
+        mForegroundRect.set(mForegroundPadding, mForegroundPadding,
+                w - mForegroundPadding, h - mForegroundPadding);
+    }
+
+    @Override
+    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
+        mShortcutsAndWidgets.setChildrenDrawingCacheEnabled(enabled);
+    }
+
+    @Override
+    protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
+        mShortcutsAndWidgets.setChildrenDrawnWithCacheEnabled(enabled);
+    }
+
+    public float getBackgroundAlpha() {
+        return mBackgroundAlpha;
+    }
+
+    public void setBackgroundAlphaMultiplier(float multiplier) {
+        if (mBackgroundAlphaMultiplier != multiplier) {
+            mBackgroundAlphaMultiplier = multiplier;
+            invalidate();
+        }
+    }
+
+    public float getBackgroundAlphaMultiplier() {
+        return mBackgroundAlphaMultiplier;
+    }
+
+    public void setBackgroundAlpha(float alpha) {
+        if (mBackgroundAlpha != alpha) {
+            mBackgroundAlpha = alpha;
+            invalidate();
+        }
+    }
+
+    public void setShortcutAndWidgetAlpha(float alpha) {
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            getChildAt(i).setAlpha(alpha);
+        }
+    }
+
+    public ShortcutAndWidgetContainer getShortcutsAndWidgets() {
+        if (getChildCount() > 0) {
+            return (ShortcutAndWidgetContainer) getChildAt(0);
+        }
+        return null;
+    }
+
+    public View getChildAt(int x, int y) {
+        return mShortcutsAndWidgets.getChildAt(x, y);
+    }
+
+    public boolean animateChildToPosition(final View child, int cellX, int cellY, int duration,
+            int delay, boolean permanent, boolean adjustOccupied) {
+        ShortcutAndWidgetContainer clc = getShortcutsAndWidgets();
+        boolean[][] occupied = mOccupied;
+        if (!permanent) {
+            occupied = mTmpOccupied;
+        }
+
+        if (clc.indexOfChild(child) != -1) {
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            final ItemInfo info = (ItemInfo) child.getTag();
+
+            // We cancel any existing animations
+            if (mReorderAnimators.containsKey(lp)) {
+                mReorderAnimators.get(lp).cancel();
+                mReorderAnimators.remove(lp);
+            }
+
+            final int oldX = lp.x;
+            final int oldY = lp.y;
+            if (adjustOccupied) {
+                occupied[lp.cellX][lp.cellY] = false;
+                occupied[cellX][cellY] = true;
+            }
+            lp.isLockedToGrid = true;
+            if (permanent) {
+                lp.cellX = info.cellX = cellX;
+                lp.cellY = info.cellY = cellY;
+            } else {
+                lp.tmpCellX = cellX;
+                lp.tmpCellY = cellY;
+            }
+            clc.setupLp(lp);
+            lp.isLockedToGrid = false;
+            final int newX = lp.x;
+            final int newY = lp.y;
+
+            lp.x = oldX;
+            lp.y = oldY;
+
+            // Exit early if we're not actually moving the view
+            if (oldX == newX && oldY == newY) {
+                lp.isLockedToGrid = true;
+                return true;
+            }
+
+            ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
+            va.setDuration(duration);
+            mReorderAnimators.put(lp, va);
+
+            va.addUpdateListener(new AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    float r = ((Float) animation.getAnimatedValue()).floatValue();
+                    lp.x = (int) ((1 - r) * oldX + r * newX);
+                    lp.y = (int) ((1 - r) * oldY + r * newY);
+                    child.requestLayout();
+                }
+            });
+            va.addListener(new AnimatorListenerAdapter() {
+                boolean cancelled = false;
+                public void onAnimationEnd(Animator animation) {
+                    // If the animation was cancelled, it means that another animation
+                    // has interrupted this one, and we don't want to lock the item into
+                    // place just yet.
+                    if (!cancelled) {
+                        lp.isLockedToGrid = true;
+                        child.requestLayout();
+                    }
+                    if (mReorderAnimators.containsKey(lp)) {
+                        mReorderAnimators.remove(lp);
+                    }
+                }
+                public void onAnimationCancel(Animator animation) {
+                    cancelled = true;
+                }
+            });
+            va.setStartDelay(delay);
+            va.start();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Estimate where the top left cell of the dragged item will land if it is dropped.
+     *
+     * @param originX The X value of the top left corner of the item
+     * @param originY The Y value of the top left corner of the item
+     * @param spanX The number of horizontal cells that the item spans
+     * @param spanY The number of vertical cells that the item spans
+     * @param result The estimated drop cell X and Y.
+     */
+    void estimateDropCell(int originX, int originY, int spanX, int spanY, int[] result) {
+        final int countX = mCountX;
+        final int countY = mCountY;
+
+        // pointToCellRounded takes the top left of a cell but will pad that with
+        // cellWidth/2 and cellHeight/2 when finding the matching cell
+        pointToCellRounded(originX, originY, result);
+
+        // If the item isn't fully on this screen, snap to the edges
+        int rightOverhang = result[0] + spanX - countX;
+        if (rightOverhang > 0) {
+            result[0] -= rightOverhang; // Snap to right
+        }
+        result[0] = Math.max(0, result[0]); // Snap to left
+        int bottomOverhang = result[1] + spanY - countY;
+        if (bottomOverhang > 0) {
+            result[1] -= bottomOverhang; // Snap to bottom
+        }
+        result[1] = Math.max(0, result[1]); // Snap to top
+    }
+
+    void visualizeDropLocation(View v, Bitmap dragOutline, int originX, int originY, int cellX,
+            int cellY, int spanX, int spanY, boolean resize, Point dragOffset, Rect dragRegion) {
+        final int oldDragCellX = mDragCell[0];
+        final int oldDragCellY = mDragCell[1];
+
+        if (v != null && dragOffset == null) {
+            mDragCenter.set(originX + (v.getWidth() / 2), originY + (v.getHeight() / 2));
+        } else {
+            mDragCenter.set(originX, originY);
+        }
+
+        if (dragOutline == null && v == null) {
+            return;
+        }
+
+        if (cellX != oldDragCellX || cellY != oldDragCellY) {
+            mDragCell[0] = cellX;
+            mDragCell[1] = cellY;
+            // Find the top left corner of the rect the object will occupy
+            final int[] topLeft = mTmpPoint;
+            cellToPoint(cellX, cellY, topLeft);
+
+            int left = topLeft[0];
+            int top = topLeft[1];
+
+            if (v != null && dragOffset == null) {
+                // When drawing the drag outline, it did not account for margin offsets
+                // added by the view's parent.
+                MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams();
+                left += lp.leftMargin;
+                top += lp.topMargin;
+
+                // Offsets due to the size difference between the View and the dragOutline.
+                // There is a size difference to account for the outer blur, which may lie
+                // outside the bounds of the view.
+                top += (v.getHeight() - dragOutline.getHeight()) / 2;
+                // We center about the x axis
+                left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+                        - dragOutline.getWidth()) / 2;
+            } else {
+                if (dragOffset != null && dragRegion != null) {
+                    // Center the drag region *horizontally* in the cell and apply a drag
+                    // outline offset
+                    left += dragOffset.x + ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+                             - dragRegion.width()) / 2;
+                    top += dragOffset.y;
+                } else {
+                    // Center the drag outline in the cell
+                    left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+                            - dragOutline.getWidth()) / 2;
+                    top += ((mCellHeight * spanY) + ((spanY - 1) * mHeightGap)
+                            - dragOutline.getHeight()) / 2;
+                }
+            }
+            final int oldIndex = mDragOutlineCurrent;
+            mDragOutlineAnims[oldIndex].animateOut();
+            mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length;
+            Rect r = mDragOutlines[mDragOutlineCurrent];
+            r.set(left, top, left + dragOutline.getWidth(), top + dragOutline.getHeight());
+            if (resize) {
+                cellToRect(cellX, cellY, spanX, spanY, r);
+            }
+
+            mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline);
+            mDragOutlineAnims[mDragOutlineCurrent].animateIn();
+        }
+    }
+
+    public void clearDragOutlines() {
+        final int oldIndex = mDragOutlineCurrent;
+        mDragOutlineAnims[oldIndex].animateOut();
+        mDragCell[0] = mDragCell[1] = -1;
+    }
+
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param result Array in which to place the result, or null (in which case a new array will
+     *        be allocated)
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY,
+            int[] result) {
+        return findNearestVacantArea(pixelX, pixelY, spanX, spanY, null, result);
+    }
+
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param minSpanX The minimum horizontal span required
+     * @param minSpanY The minimum vertical span required
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param result Array in which to place the result, or null (in which case a new array will
+     *        be allocated)
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
+            int spanY, int[] result, int[] resultSpan) {
+        return findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, null,
+                result, resultSpan);
+    }
+
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreOccupied If true, the result can be an occupied cell
+     * @param result Array in which to place the result, or null (in which case a new array will
+     *        be allocated)
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, View ignoreView,
+            boolean ignoreOccupied, int[] result) {
+        return findNearestArea(pixelX, pixelY, spanX, spanY,
+                spanX, spanY, ignoreView, ignoreOccupied, result, null, mOccupied);
+    }
+
+    private final Stack<Rect> mTempRectStack = new Stack<Rect>();
+    private void lazyInitTempRectStack() {
+        if (mTempRectStack.isEmpty()) {
+            for (int i = 0; i < mCountX * mCountY; i++) {
+                mTempRectStack.push(new Rect());
+            }
+        }
+    }
+
+    private void recycleTempRects(Stack<Rect> used) {
+        while (!used.isEmpty()) {
+            mTempRectStack.push(used.pop());
+        }
+    }
+
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param minSpanX The minimum horizontal span required
+     * @param minSpanY The minimum vertical span required
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreOccupied If true, the result can be an occupied cell
+     * @param result Array in which to place the result, or null (in which case a new array will
+     *        be allocated)
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
+            View ignoreView, boolean ignoreOccupied, int[] result, int[] resultSpan,
+            boolean[][] occupied) {
+        lazyInitTempRectStack();
+        // mark space take by ignoreView as available (method checks if ignoreView is null)
+        markCellsAsUnoccupiedForView(ignoreView, occupied);
+
+        // For items with a spanX / spanY > 1, the passed in point (pixelX, pixelY) corresponds
+        // to the center of the item, but we are searching based on the top-left cell, so
+        // we translate the point over to correspond to the top-left.
+        pixelX -= (mCellWidth + mWidthGap) * (spanX - 1) / 2f;
+        pixelY -= (mCellHeight + mHeightGap) * (spanY - 1) / 2f;
+
+        // Keep track of best-scoring drop area
+        final int[] bestXY = result != null ? result : new int[2];
+        double bestDistance = Double.MAX_VALUE;
+        final Rect bestRect = new Rect(-1, -1, -1, -1);
+        final Stack<Rect> validRegions = new Stack<Rect>();
+
+        final int countX = mCountX;
+        final int countY = mCountY;
+
+        if (minSpanX <= 0 || minSpanY <= 0 || spanX <= 0 || spanY <= 0 ||
+                spanX < minSpanX || spanY < minSpanY) {
+            return bestXY;
+        }
+
+        for (int y = 0; y < countY - (minSpanY - 1); y++) {
+            inner:
+            for (int x = 0; x < countX - (minSpanX - 1); x++) {
+                int ySize = -1;
+                int xSize = -1;
+                if (ignoreOccupied) {
+                    // First, let's see if this thing fits anywhere
+                    for (int i = 0; i < minSpanX; i++) {
+                        for (int j = 0; j < minSpanY; j++) {
+                            if (occupied[x + i][y + j]) {
+                                continue inner;
+                            }
+                        }
+                    }
+                    xSize = minSpanX;
+                    ySize = minSpanY;
+
+                    // We know that the item will fit at _some_ acceptable size, now let's see
+                    // how big we can make it. We'll alternate between incrementing x and y spans
+                    // until we hit a limit.
+                    boolean incX = true;
+                    boolean hitMaxX = xSize >= spanX;
+                    boolean hitMaxY = ySize >= spanY;
+                    while (!(hitMaxX && hitMaxY)) {
+                        if (incX && !hitMaxX) {
+                            for (int j = 0; j < ySize; j++) {
+                                if (x + xSize > countX -1 || occupied[x + xSize][y + j]) {
+                                    // We can't move out horizontally
+                                    hitMaxX = true;
+                                }
+                            }
+                            if (!hitMaxX) {
+                                xSize++;
+                            }
+                        } else if (!hitMaxY) {
+                            for (int i = 0; i < xSize; i++) {
+                                if (y + ySize > countY - 1 || occupied[x + i][y + ySize]) {
+                                    // We can't move out vertically
+                                    hitMaxY = true;
+                                }
+                            }
+                            if (!hitMaxY) {
+                                ySize++;
+                            }
+                        }
+                        hitMaxX |= xSize >= spanX;
+                        hitMaxY |= ySize >= spanY;
+                        incX = !incX;
+                    }
+                    incX = true;
+                    hitMaxX = xSize >= spanX;
+                    hitMaxY = ySize >= spanY;
+                }
+                final int[] cellXY = mTmpXY;
+                cellToCenterPoint(x, y, cellXY);
+
+                // We verify that the current rect is not a sub-rect of any of our previous
+                // candidates. In this case, the current rect is disqualified in favour of the
+                // containing rect.
+                Rect currentRect = mTempRectStack.pop();
+                currentRect.set(x, y, x + xSize, y + ySize);
+                boolean contained = false;
+                for (Rect r : validRegions) {
+                    if (r.contains(currentRect)) {
+                        contained = true;
+                        break;
+                    }
+                }
+                validRegions.push(currentRect);
+                double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
+                        + Math.pow(cellXY[1] - pixelY, 2));
+
+                if ((distance <= bestDistance && !contained) ||
+                        currentRect.contains(bestRect)) {
+                    bestDistance = distance;
+                    bestXY[0] = x;
+                    bestXY[1] = y;
+                    if (resultSpan != null) {
+                        resultSpan[0] = xSize;
+                        resultSpan[1] = ySize;
+                    }
+                    bestRect.set(currentRect);
+                }
+            }
+        }
+        // re-mark space taken by ignoreView as occupied
+        markCellsAsOccupiedForView(ignoreView, occupied);
+
+        // Return -1, -1 if no suitable location found
+        if (bestDistance == Double.MAX_VALUE) {
+            bestXY[0] = -1;
+            bestXY[1] = -1;
+        }
+        recycleTempRects(validRegions);
+        return bestXY;
+    }
+
+     /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location, and will also weigh in a suggested direction vector of the
+     * desired location. This method computers distance based on unit grid distances,
+     * not pixel distances.
+     *
+     * @param cellX The X cell nearest to which you want to search for a vacant area.
+     * @param cellY The Y cell nearest which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param direction The favored direction in which the views should move from x, y
+     * @param exactDirectionOnly If this parameter is true, then only solutions where the direction
+     *        matches exactly. Otherwise we find the best matching direction.
+     * @param occoupied The array which represents which cells in the CellLayout are occupied
+     * @param blockOccupied The array which represents which cells in the specified block (cellX,
+     *        cellY, spanX, spanY) are occupied. This is used when try to move a group of views. 
+     * @param result Array in which to place the result, or null (in which case a new array will
+     *        be allocated)
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    private int[] findNearestArea(int cellX, int cellY, int spanX, int spanY, int[] direction,
+            boolean[][] occupied, boolean blockOccupied[][], int[] result) {
+        // Keep track of best-scoring drop area
+        final int[] bestXY = result != null ? result : new int[2];
+        float bestDistance = Float.MAX_VALUE;
+        int bestDirectionScore = Integer.MIN_VALUE;
+
+        final int countX = mCountX;
+        final int countY = mCountY;
+
+        for (int y = 0; y < countY - (spanY - 1); y++) {
+            inner:
+            for (int x = 0; x < countX - (spanX - 1); x++) {
+                // First, let's see if this thing fits anywhere
+                for (int i = 0; i < spanX; i++) {
+                    for (int j = 0; j < spanY; j++) {
+                        if (occupied[x + i][y + j] && (blockOccupied == null || blockOccupied[i][j])) {
+                            continue inner;
+                        }
+                    }
+                }
+
+                float distance = (float)
+                        Math.sqrt((x - cellX) * (x - cellX) + (y - cellY) * (y - cellY));
+                int[] curDirection = mTmpPoint;
+                computeDirectionVector(x - cellX, y - cellY, curDirection);
+                // The direction score is just the dot product of the two candidate direction
+                // and that passed in.
+                int curDirectionScore = direction[0] * curDirection[0] +
+                        direction[1] * curDirection[1];
+                boolean exactDirectionOnly = false;
+                boolean directionMatches = direction[0] == curDirection[0] &&
+                        direction[0] == curDirection[0];
+                if ((directionMatches || !exactDirectionOnly) &&
+                        Float.compare(distance,  bestDistance) < 0 || (Float.compare(distance,
+                        bestDistance) == 0 && curDirectionScore > bestDirectionScore)) {
+                    bestDistance = distance;
+                    bestDirectionScore = curDirectionScore;
+                    bestXY[0] = x;
+                    bestXY[1] = y;
+                }
+            }
+        }
+
+        // Return -1, -1 if no suitable location found
+        if (bestDistance == Float.MAX_VALUE) {
+            bestXY[0] = -1;
+            bestXY[1] = -1;
+        }
+        return bestXY;
+    }
+
+    private boolean addViewToTempLocation(View v, Rect rectOccupiedByPotentialDrop,
+            int[] direction, ItemConfiguration currentState) {
+        CellAndSpan c = currentState.map.get(v);
+        boolean success = false;
+        markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, false);
+        markCellsForRect(rectOccupiedByPotentialDrop, mTmpOccupied, true);
+
+        findNearestArea(c.x, c.y, c.spanX, c.spanY, direction, mTmpOccupied, null, mTempLocation);
+
+        if (mTempLocation[0] >= 0 && mTempLocation[1] >= 0) {
+            c.x = mTempLocation[0];
+            c.y = mTempLocation[1];
+            success = true;
+        }
+        markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, true);
+        return success;
+    }
+
+    /**
+     * This helper class defines a cluster of views. It helps with defining complex edges
+     * of the cluster and determining how those edges interact with other views. The edges
+     * essentially define a fine-grained boundary around the cluster of views -- like a more
+     * precise version of a bounding box.
+     */
+    private class ViewCluster {
+        final static int LEFT = 0;
+        final static int TOP = 1;
+        final static int RIGHT = 2;
+        final static int BOTTOM = 3;
+
+        ArrayList<View> views;
+        ItemConfiguration config;
+        Rect boundingRect = new Rect();
+
+        int[] leftEdge = new int[mCountY];
+        int[] rightEdge = new int[mCountY];
+        int[] topEdge = new int[mCountX];
+        int[] bottomEdge = new int[mCountX];
+        boolean leftEdgeDirty, rightEdgeDirty, topEdgeDirty, bottomEdgeDirty, boundingRectDirty;
+
+        @SuppressWarnings("unchecked")
+        public ViewCluster(ArrayList<View> views, ItemConfiguration config) {
+            this.views = (ArrayList<View>) views.clone();
+            this.config = config;
+            resetEdges();
+        }
+
+        void resetEdges() {
+            for (int i = 0; i < mCountX; i++) {
+                topEdge[i] = -1;
+                bottomEdge[i] = -1;
+            }
+            for (int i = 0; i < mCountY; i++) {
+                leftEdge[i] = -1;
+                rightEdge[i] = -1;
+            }
+            leftEdgeDirty = true;
+            rightEdgeDirty = true;
+            bottomEdgeDirty = true;
+            topEdgeDirty = true;
+            boundingRectDirty = true;
+        }
+
+        void computeEdge(int which, int[] edge) {
+            int count = views.size();
+            for (int i = 0; i < count; i++) {
+                CellAndSpan cs = config.map.get(views.get(i));
+                switch (which) {
+                    case LEFT:
+                        int left = cs.x;
+                        for (int j = cs.y; j < cs.y + cs.spanY; j++) {
+                            if (left < edge[j] || edge[j] < 0) {
+                                edge[j] = left;
+                            }
+                        }
+                        break;
+                    case RIGHT:
+                        int right = cs.x + cs.spanX;
+                        for (int j = cs.y; j < cs.y + cs.spanY; j++) {
+                            if (right > edge[j]) {
+                                edge[j] = right;
+                            }
+                        }
+                        break;
+                    case TOP:
+                        int top = cs.y;
+                        for (int j = cs.x; j < cs.x + cs.spanX; j++) {
+                            if (top < edge[j] || edge[j] < 0) {
+                                edge[j] = top;
+                            }
+                        }
+                        break;
+                    case BOTTOM:
+                        int bottom = cs.y + cs.spanY;
+                        for (int j = cs.x; j < cs.x + cs.spanX; j++) {
+                            if (bottom > edge[j]) {
+                                edge[j] = bottom;
+                            }
+                        }
+                        break;
+                }
+            }
+        }
+
+        boolean isViewTouchingEdge(View v, int whichEdge) {
+            CellAndSpan cs = config.map.get(v);
+
+            int[] edge = getEdge(whichEdge);
+
+            switch (whichEdge) {
+                case LEFT:
+                    for (int i = cs.y; i < cs.y + cs.spanY; i++) {
+                        if (edge[i] == cs.x + cs.spanX) {
+                            return true;
+                        }
+                    }
+                    break;
+                case RIGHT:
+                    for (int i = cs.y; i < cs.y + cs.spanY; i++) {
+                        if (edge[i] == cs.x) {
+                            return true;
+                        }
+                    }
+                    break;
+                case TOP:
+                    for (int i = cs.x; i < cs.x + cs.spanX; i++) {
+                        if (edge[i] == cs.y + cs.spanY) {
+                            return true;
+                        }
+                    }
+                    break;
+                case BOTTOM:
+                    for (int i = cs.x; i < cs.x + cs.spanX; i++) {
+                        if (edge[i] == cs.y) {
+                            return true;
+                        }
+                    }
+                    break;
+            }
+            return false;
+        }
+
+        void shift(int whichEdge, int delta) {
+            for (View v: views) {
+                CellAndSpan c = config.map.get(v);
+                switch (whichEdge) {
+                    case LEFT:
+                        c.x -= delta;
+                        break;
+                    case RIGHT:
+                        c.x += delta;
+                        break;
+                    case TOP:
+                        c.y -= delta;
+                        break;
+                    case BOTTOM:
+                    default:
+                        c.y += delta;
+                        break;
+                }
+            }
+            resetEdges();
+        }
+
+        public void addView(View v) {
+            views.add(v);
+            resetEdges();
+        }
+
+        public Rect getBoundingRect() {
+            if (boundingRectDirty) {
+                boolean first = true;
+                for (View v: views) {
+                    CellAndSpan c = config.map.get(v);
+                    if (first) {
+                        boundingRect.set(c.x, c.y, c.x + c.spanX, c.y + c.spanY);
+                        first = false;
+                    } else {
+                        boundingRect.union(c.x, c.y, c.x + c.spanX, c.y + c.spanY);
+                    }
+                }
+            }
+            return boundingRect;
+        }
+
+        public int[] getEdge(int which) {
+            switch (which) {
+                case LEFT:
+                    return getLeftEdge();
+                case RIGHT:
+                    return getRightEdge();
+                case TOP:
+                    return getTopEdge();
+                case BOTTOM:
+                default:
+                    return getBottomEdge();
+            }
+        }
+
+        public int[] getLeftEdge() {
+            if (leftEdgeDirty) {
+                computeEdge(LEFT, leftEdge);
+            }
+            return leftEdge;
+        }
+
+        public int[] getRightEdge() {
+            if (rightEdgeDirty) {
+                computeEdge(RIGHT, rightEdge);
+            }
+            return rightEdge;
+        }
+
+        public int[] getTopEdge() {
+            if (topEdgeDirty) {
+                computeEdge(TOP, topEdge);
+            }
+            return topEdge;
+        }
+
+        public int[] getBottomEdge() {
+            if (bottomEdgeDirty) {
+                computeEdge(BOTTOM, bottomEdge);
+            }
+            return bottomEdge;
+        }
+
+        PositionComparator comparator = new PositionComparator();
+        class PositionComparator implements Comparator<View> {
+            int whichEdge = 0;
+            public int compare(View left, View right) {
+                CellAndSpan l = config.map.get(left);
+                CellAndSpan r = config.map.get(right);
+                switch (whichEdge) {
+                    case LEFT:
+                        return (r.x + r.spanX) - (l.x + l.spanX);
+                    case RIGHT:
+                        return l.x - r.x;
+                    case TOP:
+                        return (r.y + r.spanY) - (l.y + l.spanY);
+                    case BOTTOM:
+                    default:
+                        return l.y - r.y;
+                }
+            }
+        }
+
+        public void sortConfigurationForEdgePush(int edge) {
+            comparator.whichEdge = edge;
+            Collections.sort(config.sortedViews, comparator);
+        }
+    }
+
+    private boolean pushViewsToTempLocation(ArrayList<View> views, Rect rectOccupiedByPotentialDrop,
+            int[] direction, View dragView, ItemConfiguration currentState) {
+
+        ViewCluster cluster = new ViewCluster(views, currentState);
+        Rect clusterRect = cluster.getBoundingRect();
+        int whichEdge;
+        int pushDistance;
+        boolean fail = false;
+
+        // Determine the edge of the cluster that will be leading the push and how far
+        // the cluster must be shifted.
+        if (direction[0] < 0) {
+            whichEdge = ViewCluster.LEFT;
+            pushDistance = clusterRect.right - rectOccupiedByPotentialDrop.left;
+        } else if (direction[0] > 0) {
+            whichEdge = ViewCluster.RIGHT;
+            pushDistance = rectOccupiedByPotentialDrop.right - clusterRect.left;
+        } else if (direction[1] < 0) {
+            whichEdge = ViewCluster.TOP;
+            pushDistance = clusterRect.bottom - rectOccupiedByPotentialDrop.top;
+        } else {
+            whichEdge = ViewCluster.BOTTOM;
+            pushDistance = rectOccupiedByPotentialDrop.bottom - clusterRect.top;
+        }
+
+        // Break early for invalid push distance.
+        if (pushDistance <= 0) {
+            return false;
+        }
+
+        // Mark the occupied state as false for the group of views we want to move.
+        for (View v: views) {
+            CellAndSpan c = currentState.map.get(v);
+            markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, false);
+        }
+
+        // We save the current configuration -- if we fail to find a solution we will revert
+        // to the initial state. The process of finding a solution modifies the configuration
+        // in place, hence the need for revert in the failure case.
+        currentState.save();
+
+        // The pushing algorithm is simplified by considering the views in the order in which
+        // they would be pushed by the cluster. For example, if the cluster is leading with its
+        // left edge, we consider sort the views by their right edge, from right to left.
+        cluster.sortConfigurationForEdgePush(whichEdge);
+
+        while (pushDistance > 0 && !fail) {
+            for (View v: currentState.sortedViews) {
+                // For each view that isn't in the cluster, we see if the leading edge of the
+                // cluster is contacting the edge of that view. If so, we add that view to the
+                // cluster.
+                if (!cluster.views.contains(v) && v != dragView) {
+                    if (cluster.isViewTouchingEdge(v, whichEdge)) {
+                        LayoutParams lp = (LayoutParams) v.getLayoutParams();
+                        if (!lp.canReorder) {
+                            // The push solution includes the all apps button, this is not viable.
+                            fail = true;
+                            break;
+                        }
+                        cluster.addView(v);
+                        CellAndSpan c = currentState.map.get(v);
+
+                        // Adding view to cluster, mark it as not occupied.
+                        markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, false);
+                    }
+                }
+            }
+            pushDistance--;
+
+            // The cluster has been completed, now we move the whole thing over in the appropriate
+            // direction.
+            cluster.shift(whichEdge, 1);
+        }
+
+        boolean foundSolution = false;
+        clusterRect = cluster.getBoundingRect();
+
+        // Due to the nature of the algorithm, the only check required to verify a valid solution
+        // is to ensure that completed shifted cluster lies completely within the cell layout.
+        if (!fail && clusterRect.left >= 0 && clusterRect.right <= mCountX && clusterRect.top >= 0 &&
+                clusterRect.bottom <= mCountY) {
+            foundSolution = true;
+        } else {
+            currentState.restore();
+        }
+
+        // In either case, we set the occupied array as marked for the location of the views
+        for (View v: cluster.views) {
+            CellAndSpan c = currentState.map.get(v);
+            markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, true);
+        }
+
+        return foundSolution;
+    }
+
+    private boolean addViewsToTempLocation(ArrayList<View> views, Rect rectOccupiedByPotentialDrop,
+            int[] direction, View dragView, ItemConfiguration currentState) {
+        if (views.size() == 0) return true;
+
+        boolean success = false;
+        Rect boundingRect = null;
+        // We construct a rect which represents the entire group of views passed in
+        for (View v: views) {
+            CellAndSpan c = currentState.map.get(v);
+            if (boundingRect == null) {
+                boundingRect = new Rect(c.x, c.y, c.x + c.spanX, c.y + c.spanY);
+            } else {
+                boundingRect.union(c.x, c.y, c.x + c.spanX, c.y + c.spanY);
+            }
+        }
+
+        // Mark the occupied state as false for the group of views we want to move.
+        for (View v: views) {
+            CellAndSpan c = currentState.map.get(v);
+            markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, false);
+        }
+
+        boolean[][] blockOccupied = new boolean[boundingRect.width()][boundingRect.height()];
+        int top = boundingRect.top;
+        int left = boundingRect.left;
+        // We mark more precisely which parts of the bounding rect are truly occupied, allowing
+        // for interlocking.
+        for (View v: views) {
+            CellAndSpan c = currentState.map.get(v);
+            markCellsForView(c.x - left, c.y - top, c.spanX, c.spanY, blockOccupied, true);
+        }
+
+        markCellsForRect(rectOccupiedByPotentialDrop, mTmpOccupied, true);
+
+        findNearestArea(boundingRect.left, boundingRect.top, boundingRect.width(),
+                boundingRect.height(), direction, mTmpOccupied, blockOccupied, mTempLocation);
+
+        // If we successfuly found a location by pushing the block of views, we commit it
+        if (mTempLocation[0] >= 0 && mTempLocation[1] >= 0) {
+            int deltaX = mTempLocation[0] - boundingRect.left;
+            int deltaY = mTempLocation[1] - boundingRect.top;
+            for (View v: views) {
+                CellAndSpan c = currentState.map.get(v);
+                c.x += deltaX;
+                c.y += deltaY;
+            }
+            success = true;
+        }
+
+        // In either case, we set the occupied array as marked for the location of the views
+        for (View v: views) {
+            CellAndSpan c = currentState.map.get(v);
+            markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, true);
+        }
+        return success;
+    }
+
+    private void markCellsForRect(Rect r, boolean[][] occupied, boolean value) {
+        markCellsForView(r.left, r.top, r.width(), r.height(), occupied, value);
+    }
+
+    // This method tries to find a reordering solution which satisfies the push mechanic by trying
+    // to push items in each of the cardinal directions, in an order based on the direction vector
+    // passed.
+    private boolean attemptPushInDirection(ArrayList<View> intersectingViews, Rect occupied,
+            int[] direction, View ignoreView, ItemConfiguration solution) {
+        if ((Math.abs(direction[0]) + Math.abs(direction[1])) > 1) {
+            // If the direction vector has two non-zero components, we try pushing 
+            // separately in each of the components.
+            int temp = direction[1];
+            direction[1] = 0;
+
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+            direction[1] = temp;
+            temp = direction[0];
+            direction[0] = 0;
+
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Revert the direction
+            direction[0] = temp;
+
+            // Now we try pushing in each component of the opposite direction
+            direction[0] *= -1;
+            direction[1] *= -1;
+            temp = direction[1];
+            direction[1] = 0;
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+
+            direction[1] = temp;
+            temp = direction[0];
+            direction[0] = 0;
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // revert the direction
+            direction[0] = temp;
+            direction[0] *= -1;
+            direction[1] *= -1;
+            
+        } else {
+            // If the direction vector has a single non-zero component, we push first in the
+            // direction of the vector
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Then we try the opposite direction
+            direction[0] *= -1;
+            direction[1] *= -1;
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Switch the direction back
+            direction[0] *= -1;
+            direction[1] *= -1;
+            
+            // If we have failed to find a push solution with the above, then we try 
+            // to find a solution by pushing along the perpendicular axis.
+
+            // Swap the components
+            int temp = direction[1];
+            direction[1] = direction[0];
+            direction[0] = temp;
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+
+            // Then we try the opposite direction
+            direction[0] *= -1;
+            direction[1] *= -1;
+            if (pushViewsToTempLocation(intersectingViews, occupied, direction,
+                    ignoreView, solution)) {
+                return true;
+            }
+            // Switch the direction back
+            direction[0] *= -1;
+            direction[1] *= -1;
+
+            // Swap the components back
+            temp = direction[1];
+            direction[1] = direction[0];
+            direction[0] = temp;
+        }
+        return false;
+    }
+
+    private boolean rearrangementExists(int cellX, int cellY, int spanX, int spanY, int[] direction,
+            View ignoreView, ItemConfiguration solution) {
+        // Return early if get invalid cell positions
+        if (cellX < 0 || cellY < 0) return false;
+
+        mIntersectingViews.clear();
+        mOccupiedRect.set(cellX, cellY, cellX + spanX, cellY + spanY);
+
+        // Mark the desired location of the view currently being dragged.
+        if (ignoreView != null) {
+            CellAndSpan c = solution.map.get(ignoreView);
+            if (c != null) {
+                c.x = cellX;
+                c.y = cellY;
+            }
+        }
+        Rect r0 = new Rect(cellX, cellY, cellX + spanX, cellY + spanY);
+        Rect r1 = new Rect();
+        for (View child: solution.map.keySet()) {
+            if (child == ignoreView) continue;
+            CellAndSpan c = solution.map.get(child);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            r1.set(c.x, c.y, c.x + c.spanX, c.y + c.spanY);
+            if (Rect.intersects(r0, r1)) {
+                if (!lp.canReorder) {
+                    return false;
+                }
+                mIntersectingViews.add(child);
+            }
+        }
+
+        // First we try to find a solution which respects the push mechanic. That is, 
+        // we try to find a solution such that no displaced item travels through another item
+        // without also displacing that item.
+        if (attemptPushInDirection(mIntersectingViews, mOccupiedRect, direction, ignoreView,
+                solution)) {
+            return true;
+        }
+
+        // Next we try moving the views as a block, but without requiring the push mechanic.
+        if (addViewsToTempLocation(mIntersectingViews, mOccupiedRect, direction, ignoreView,
+                solution)) {
+            return true;
+        }
+
+        // Ok, they couldn't move as a block, let's move them individually
+        for (View v : mIntersectingViews) {
+            if (!addViewToTempLocation(v, mOccupiedRect, direction, solution)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * Returns a pair (x, y), where x,y are in {-1, 0, 1} corresponding to vector between
+     * the provided point and the provided cell
+     */
+    private void computeDirectionVector(float deltaX, float deltaY, int[] result) {
+        double angle = Math.atan(((float) deltaY) / deltaX);
+
+        result[0] = 0;
+        result[1] = 0;
+        if (Math.abs(Math.cos(angle)) > 0.5f) {
+            result[0] = (int) Math.signum(deltaX);
+        }
+        if (Math.abs(Math.sin(angle)) > 0.5f) {
+            result[1] = (int) Math.signum(deltaY);
+        }
+    }
+
+    private void copyOccupiedArray(boolean[][] occupied) {
+        for (int i = 0; i < mCountX; i++) {
+            for (int j = 0; j < mCountY; j++) {
+                occupied[i][j] = mOccupied[i][j];
+            }
+        }
+    }
+
+    ItemConfiguration simpleSwap(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
+            int spanY, int[] direction, View dragView, boolean decX, ItemConfiguration solution) {
+        // Copy the current state into the solution. This solution will be manipulated as necessary.
+        copyCurrentStateToSolution(solution, false);
+        // Copy the current occupied array into the temporary occupied array. This array will be
+        // manipulated as necessary to find a solution.
+        copyOccupiedArray(mTmpOccupied);
+
+        // We find the nearest cell into which we would place the dragged item, assuming there's
+        // nothing in its way.
+        int result[] = new int[2];
+        result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
+
+        boolean success = false;
+        // First we try the exact nearest position of the item being dragged,
+        // we will then want to try to move this around to other neighbouring positions
+        success = rearrangementExists(result[0], result[1], spanX, spanY, direction, dragView,
+                solution);
+
+        if (!success) {
+            // We try shrinking the widget down to size in an alternating pattern, shrink 1 in
+            // x, then 1 in y etc.
+            if (spanX > minSpanX && (minSpanY == spanY || decX)) {
+                return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY, direction,
+                        dragView, false, solution);
+            } else if (spanY > minSpanY) {
+                return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1, direction,
+                        dragView, true, solution);
+            }
+            solution.isSolution = false;
+        } else {
+            solution.isSolution = true;
+            solution.dragViewX = result[0];
+            solution.dragViewY = result[1];
+            solution.dragViewSpanX = spanX;
+            solution.dragViewSpanY = spanY;
+        }
+        return solution;
+    }
+
+    private void copyCurrentStateToSolution(ItemConfiguration solution, boolean temp) {
+        int childCount = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            CellAndSpan c;
+            if (temp) {
+                c = new CellAndSpan(lp.tmpCellX, lp.tmpCellY, lp.cellHSpan, lp.cellVSpan);
+            } else {
+                c = new CellAndSpan(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan);
+            }
+            solution.add(child, c);
+        }
+    }
+
+    private void copySolutionToTempState(ItemConfiguration solution, View dragView) {
+        for (int i = 0; i < mCountX; i++) {
+            for (int j = 0; j < mCountY; j++) {
+                mTmpOccupied[i][j] = false;
+            }
+        }
+
+        int childCount = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            if (child == dragView) continue;
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            CellAndSpan c = solution.map.get(child);
+            if (c != null) {
+                lp.tmpCellX = c.x;
+                lp.tmpCellY = c.y;
+                lp.cellHSpan = c.spanX;
+                lp.cellVSpan = c.spanY;
+                markCellsForView(c.x, c.y, c.spanX, c.spanY, mTmpOccupied, true);
+            }
+        }
+        markCellsForView(solution.dragViewX, solution.dragViewY, solution.dragViewSpanX,
+                solution.dragViewSpanY, mTmpOccupied, true);
+    }
+
+    private void animateItemsToSolution(ItemConfiguration solution, View dragView, boolean
+            commitDragView) {
+
+        boolean[][] occupied = DESTRUCTIVE_REORDER ? mOccupied : mTmpOccupied;
+        for (int i = 0; i < mCountX; i++) {
+            for (int j = 0; j < mCountY; j++) {
+                occupied[i][j] = false;
+            }
+        }
+
+        int childCount = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            if (child == dragView) continue;
+            CellAndSpan c = solution.map.get(child);
+            if (c != null) {
+                animateChildToPosition(child, c.x, c.y, REORDER_ANIMATION_DURATION, 0,
+                        DESTRUCTIVE_REORDER, false);
+                markCellsForView(c.x, c.y, c.spanX, c.spanY, occupied, true);
+            }
+        }
+        if (commitDragView) {
+            markCellsForView(solution.dragViewX, solution.dragViewY, solution.dragViewSpanX,
+                    solution.dragViewSpanY, occupied, true);
+        }
+    }
+
+    // This method starts or changes the reorder hint animations
+    private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) {
+        int childCount = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            if (child == dragView) continue;
+            CellAndSpan c = solution.map.get(child);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (c != null) {
+                ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY,
+                        c.x, c.y, c.spanX, c.spanY);
+                rha.animate();
+            }
+        }
+    }
+
+    // Class which represents the reorder hint animations. These animations show that an item is
+    // in a temporary state, and hint at where the item will return to.
+    class ReorderHintAnimation {
+        View child;
+        float finalDeltaX;
+        float finalDeltaY;
+        float initDeltaX;
+        float initDeltaY;
+        float finalScale;
+        float initScale;
+        private static final int DURATION = 300;
+        Animator a;
+
+        public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1,
+                int spanX, int spanY) {
+            regionToCenterPoint(cellX0, cellY0, spanX, spanY, mTmpPoint);
+            final int x0 = mTmpPoint[0];
+            final int y0 = mTmpPoint[1];
+            regionToCenterPoint(cellX1, cellY1, spanX, spanY, mTmpPoint);
+            final int x1 = mTmpPoint[0];
+            final int y1 = mTmpPoint[1];
+            final int dX = x1 - x0;
+            final int dY = y1 - y0;
+            finalDeltaX = 0;
+            finalDeltaY = 0;
+            if (dX == dY && dX == 0) {
+            } else {
+                if (dY == 0) {
+                    finalDeltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude;
+                } else if (dX == 0) {
+                    finalDeltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude;
+                } else {
+                    double angle = Math.atan( (float) (dY) / dX);
+                    finalDeltaX = (int) (- Math.signum(dX) *
+                            Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude));
+                    finalDeltaY = (int) (- Math.signum(dY) *
+                            Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude));
+                }
+            }
+            initDeltaX = child.getTranslationX();
+            initDeltaY = child.getTranslationY();
+            finalScale = getChildrenScale() - 4.0f / child.getWidth();
+            initScale = child.getScaleX();
+            this.child = child;
+        }
+
+        void animate() {
+            if (mShakeAnimators.containsKey(child)) {
+                ReorderHintAnimation oldAnimation = mShakeAnimators.get(child);
+                oldAnimation.cancel();
+                mShakeAnimators.remove(child);
+                if (finalDeltaX == 0 && finalDeltaY == 0) {
+                    completeAnimationImmediately();
+                    return;
+                }
+            }
+            if (finalDeltaX == 0 && finalDeltaY == 0) {
+                return;
+            }
+            ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
+            a = va;
+            va.setRepeatMode(ValueAnimator.REVERSE);
+            va.setRepeatCount(ValueAnimator.INFINITE);
+            va.setDuration(DURATION);
+            va.setStartDelay((int) (Math.random() * 60));
+            va.addUpdateListener(new AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    float r = ((Float) animation.getAnimatedValue()).floatValue();
+                    float x = r * finalDeltaX + (1 - r) * initDeltaX;
+                    float y = r * finalDeltaY + (1 - r) * initDeltaY;
+                    child.setTranslationX(x);
+                    child.setTranslationY(y);
+                    float s = r * finalScale + (1 - r) * initScale;
+                    child.setScaleX(s);
+                    child.setScaleY(s);
+                }
+            });
+            va.addListener(new AnimatorListenerAdapter() {
+                public void onAnimationRepeat(Animator animation) {
+                    // We make sure to end only after a full period
+                    initDeltaX = 0;
+                    initDeltaY = 0;
+                    initScale = getChildrenScale();
+                }
+            });
+            mShakeAnimators.put(child, this);
+            va.start();
+        }
+
+        private void cancel() {
+            if (a != null) {
+                a.cancel();
+            }
+        }
+
+        private void completeAnimationImmediately() {
+            if (a != null) {
+                a.cancel();
+            }
+
+            AnimatorSet s = LauncherAnimUtils.createAnimatorSet();
+            a = s;
+            s.playTogether(
+                LauncherAnimUtils.ofFloat(child, "scaleX", getChildrenScale()),
+                LauncherAnimUtils.ofFloat(child, "scaleY", getChildrenScale()),
+                LauncherAnimUtils.ofFloat(child, "translationX", 0f),
+                LauncherAnimUtils.ofFloat(child, "translationY", 0f)
+            );
+            s.setDuration(REORDER_ANIMATION_DURATION);
+            s.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f));
+            s.start();
+        }
+    }
+
+    private void completeAndClearReorderHintAnimations() {
+        for (ReorderHintAnimation a: mShakeAnimators.values()) {
+            a.completeAnimationImmediately();
+        }
+        mShakeAnimators.clear();
+    }
+
+    private void commitTempPlacement() {
+        for (int i = 0; i < mCountX; i++) {
+            for (int j = 0; j < mCountY; j++) {
+                mOccupied[i][j] = mTmpOccupied[i][j];
+            }
+        }
+        int childCount = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            ItemInfo info = (ItemInfo) child.getTag();
+            // We do a null check here because the item info can be null in the case of the
+            // AllApps button in the hotseat.
+            if (info != null) {
+                if (info.cellX != lp.tmpCellX || info.cellY != lp.tmpCellY ||
+                        info.spanX != lp.cellHSpan || info.spanY != lp.cellVSpan) {
+                    info.requiresDbUpdate = true;
+                }
+                info.cellX = lp.cellX = lp.tmpCellX;
+                info.cellY = lp.cellY = lp.tmpCellY;
+                info.spanX = lp.cellHSpan;
+                info.spanY = lp.cellVSpan;
+            }
+        }
+        mLauncher.getWorkspace().updateItemLocationsInDatabase(this);
+    }
+
+    public void setUseTempCoords(boolean useTempCoords) {
+        int childCount = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            LayoutParams lp = (LayoutParams) mShortcutsAndWidgets.getChildAt(i).getLayoutParams();
+            lp.useTmpCoords = useTempCoords;
+        }
+    }
+
+    ItemConfiguration findConfigurationNoShuffle(int pixelX, int pixelY, int minSpanX, int minSpanY,
+            int spanX, int spanY, View dragView, ItemConfiguration solution) {
+        int[] result = new int[2];
+        int[] resultSpan = new int[2];
+        findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, null, result,
+                resultSpan);
+        if (result[0] >= 0 && result[1] >= 0) {
+            copyCurrentStateToSolution(solution, false);
+            solution.dragViewX = result[0];
+            solution.dragViewY = result[1];
+            solution.dragViewSpanX = resultSpan[0];
+            solution.dragViewSpanY = resultSpan[1];
+            solution.isSolution = true;
+        } else {
+            solution.isSolution = false;
+        }
+        return solution;
+    }
+
+    public void prepareChildForDrag(View child) {
+        markCellsAsUnoccupiedForView(child);
+    }
+
+    /* This seems like it should be obvious and straight-forward, but when the direction vector
+    needs to match with the notion of the dragView pushing other views, we have to employ
+    a slightly more subtle notion of the direction vector. The question is what two points is
+    the vector between? The center of the dragView and its desired destination? Not quite, as
+    this doesn't necessarily coincide with the interaction of the dragView and items occupying
+    those cells. Instead we use some heuristics to often lock the vector to up, down, left
+    or right, which helps make pushing feel right.
+    */
+    private void getDirectionVectorForDrop(int dragViewCenterX, int dragViewCenterY, int spanX,
+            int spanY, View dragView, int[] resultDirection) {
+        int[] targetDestination = new int[2];
+
+        findNearestArea(dragViewCenterX, dragViewCenterY, spanX, spanY, targetDestination);
+        Rect dragRect = new Rect();
+        regionToRect(targetDestination[0], targetDestination[1], spanX, spanY, dragRect);
+        dragRect.offset(dragViewCenterX - dragRect.centerX(), dragViewCenterY - dragRect.centerY());
+
+        Rect dropRegionRect = new Rect();
+        getViewsIntersectingRegion(targetDestination[0], targetDestination[1], spanX, spanY,
+                dragView, dropRegionRect, mIntersectingViews);
+
+        int dropRegionSpanX = dropRegionRect.width();
+        int dropRegionSpanY = dropRegionRect.height();
+
+        regionToRect(dropRegionRect.left, dropRegionRect.top, dropRegionRect.width(),
+                dropRegionRect.height(), dropRegionRect);
+
+        int deltaX = (dropRegionRect.centerX() - dragViewCenterX) / spanX;
+        int deltaY = (dropRegionRect.centerY() - dragViewCenterY) / spanY;
+
+        if (dropRegionSpanX == mCountX || spanX == mCountX) {
+            deltaX = 0;
+        }
+        if (dropRegionSpanY == mCountY || spanY == mCountY) {
+            deltaY = 0;
+        }
+
+        if (deltaX == 0 && deltaY == 0) {
+            // No idea what to do, give a random direction.
+            resultDirection[0] = 1;
+            resultDirection[1] = 0;
+        } else {
+            computeDirectionVector(deltaX, deltaY, resultDirection);
+        }
+    }
+
+    // For a given cell and span, fetch the set of views intersecting the region.
+    private void getViewsIntersectingRegion(int cellX, int cellY, int spanX, int spanY,
+            View dragView, Rect boundingRect, ArrayList<View> intersectingViews) {
+        if (boundingRect != null) {
+            boundingRect.set(cellX, cellY, cellX + spanX, cellY + spanY);
+        }
+        intersectingViews.clear();
+        Rect r0 = new Rect(cellX, cellY, cellX + spanX, cellY + spanY);
+        Rect r1 = new Rect();
+        final int count = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            if (child == dragView) continue;
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            r1.set(lp.cellX, lp.cellY, lp.cellX + lp.cellHSpan, lp.cellY + lp.cellVSpan);
+            if (Rect.intersects(r0, r1)) {
+                mIntersectingViews.add(child);
+                if (boundingRect != null) {
+                    boundingRect.union(r1);
+                }
+            }
+        }
+    }
+
+    boolean isNearestDropLocationOccupied(int pixelX, int pixelY, int spanX, int spanY,
+            View dragView, int[] result) {
+        result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
+        getViewsIntersectingRegion(result[0], result[1], spanX, spanY, dragView, null,
+                mIntersectingViews);
+        return !mIntersectingViews.isEmpty();
+    }
+
+    void revertTempState() {
+        if (!isItemPlacementDirty() || DESTRUCTIVE_REORDER) return;
+        final int count = mShortcutsAndWidgets.getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = mShortcutsAndWidgets.getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) {
+                lp.tmpCellX = lp.cellX;
+                lp.tmpCellY = lp.cellY;
+                animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION,
+                        0, false, false);
+            }
+        }
+        completeAndClearReorderHintAnimations();
+        setItemPlacementDirty(false);
+    }
+
+    boolean createAreaForResize(int cellX, int cellY, int spanX, int spanY,
+            View dragView, int[] direction, boolean commit) {
+        int[] pixelXY = new int[2];
+        regionToCenterPoint(cellX, cellY, spanX, spanY, pixelXY);
+
+        // First we determine if things have moved enough to cause a different layout
+        ItemConfiguration swapSolution = simpleSwap(pixelXY[0], pixelXY[1], spanX, spanY,
+                 spanX,  spanY, direction, dragView,  true,  new ItemConfiguration());
+
+        setUseTempCoords(true);
+        if (swapSolution != null && swapSolution.isSolution) {
+            // If we're just testing for a possible location (MODE_ACCEPT_DROP), we don't bother
+            // committing anything or animating anything as we just want to determine if a solution
+            // exists
+            copySolutionToTempState(swapSolution, dragView);
+            setItemPlacementDirty(true);
+            animateItemsToSolution(swapSolution, dragView, commit);
+
+            if (commit) {
+                commitTempPlacement();
+                completeAndClearReorderHintAnimations();
+                setItemPlacementDirty(false);
+            } else {
+                beginOrAdjustHintAnimations(swapSolution, dragView,
+                        REORDER_ANIMATION_DURATION);
+            }
+            mShortcutsAndWidgets.requestLayout();
+        }
+        return swapSolution.isSolution;
+    }
+
+    int[] createArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
+            View dragView, int[] result, int resultSpan[], int mode) {
+        // First we determine if things have moved enough to cause a different layout
+        result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
+
+        if (resultSpan == null) {
+            resultSpan = new int[2];
+        }
+
+        // When we are checking drop validity or actually dropping, we don't recompute the
+        // direction vector, since we want the solution to match the preview, and it's possible
+        // that the exact position of the item has changed to result in a new reordering outcome.
+        if ((mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL || mode == MODE_ACCEPT_DROP)
+               && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
+            mDirectionVector[0] = mPreviousReorderDirection[0];
+            mDirectionVector[1] = mPreviousReorderDirection[1];
+            // We reset this vector after drop
+            if (mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL) {
+                mPreviousReorderDirection[0] = INVALID_DIRECTION;
+                mPreviousReorderDirection[1] = INVALID_DIRECTION;
+            }
+        } else {
+            getDirectionVectorForDrop(pixelX, pixelY, spanX, spanY, dragView, mDirectionVector);
+            mPreviousReorderDirection[0] = mDirectionVector[0];
+            mPreviousReorderDirection[1] = mDirectionVector[1];
+        }
+
+        ItemConfiguration swapSolution = simpleSwap(pixelX, pixelY, minSpanX, minSpanY,
+                 spanX,  spanY, mDirectionVector, dragView,  true,  new ItemConfiguration());
+
+        // We attempt the approach which doesn't shuffle views at all
+        ItemConfiguration noShuffleSolution = findConfigurationNoShuffle(pixelX, pixelY, minSpanX,
+                minSpanY, spanX, spanY, dragView, new ItemConfiguration());
+
+        ItemConfiguration finalSolution = null;
+        if (swapSolution.isSolution && swapSolution.area() >= noShuffleSolution.area()) {
+            finalSolution = swapSolution;
+        } else if (noShuffleSolution.isSolution) {
+            finalSolution = noShuffleSolution;
+        }
+
+        boolean foundSolution = true;
+        if (!DESTRUCTIVE_REORDER) {
+            setUseTempCoords(true);
+        }
+
+        if (finalSolution != null) {
+            result[0] = finalSolution.dragViewX;
+            result[1] = finalSolution.dragViewY;
+            resultSpan[0] = finalSolution.dragViewSpanX;
+            resultSpan[1] = finalSolution.dragViewSpanY;
+
+            // If we're just testing for a possible location (MODE_ACCEPT_DROP), we don't bother
+            // committing anything or animating anything as we just want to determine if a solution
+            // exists
+            if (mode == MODE_DRAG_OVER || mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL) {
+                if (!DESTRUCTIVE_REORDER) {
+                    copySolutionToTempState(finalSolution, dragView);
+                }
+                setItemPlacementDirty(true);
+                animateItemsToSolution(finalSolution, dragView, mode == MODE_ON_DROP);
+
+                if (!DESTRUCTIVE_REORDER &&
+                        (mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL)) {
+                    commitTempPlacement();
+                    completeAndClearReorderHintAnimations();
+                    setItemPlacementDirty(false);
+                } else {
+                    beginOrAdjustHintAnimations(finalSolution, dragView,
+                            REORDER_ANIMATION_DURATION);
+                }
+            }
+        } else {
+            foundSolution = false;
+            result[0] = result[1] = resultSpan[0] = resultSpan[1] = -1;
+        }
+
+        if ((mode == MODE_ON_DROP || !foundSolution) && !DESTRUCTIVE_REORDER) {
+            setUseTempCoords(false);
+        }
+
+        mShortcutsAndWidgets.requestLayout();
+        return result;
+    }
+
+    void setItemPlacementDirty(boolean dirty) {
+        mItemPlacementDirty = dirty;
+    }
+    boolean isItemPlacementDirty() {
+        return mItemPlacementDirty;
+    }
+
+    private class ItemConfiguration {
+        HashMap<View, CellAndSpan> map = new HashMap<View, CellAndSpan>();
+        private HashMap<View, CellAndSpan> savedMap = new HashMap<View, CellAndSpan>();
+        ArrayList<View> sortedViews = new ArrayList<View>();
+        boolean isSolution = false;
+        int dragViewX, dragViewY, dragViewSpanX, dragViewSpanY;
+
+        void save() {
+            // Copy current state into savedMap
+            for (View v: map.keySet()) {
+                map.get(v).copy(savedMap.get(v));
+            }
+        }
+
+        void restore() {
+            // Restore current state from savedMap
+            for (View v: savedMap.keySet()) {
+                savedMap.get(v).copy(map.get(v));
+            }
+        }
+
+        void add(View v, CellAndSpan cs) {
+            map.put(v, cs);
+            savedMap.put(v, new CellAndSpan());
+            sortedViews.add(v);
+        }
+
+        int area() {
+            return dragViewSpanX * dragViewSpanY;
+        }
+    }
+
+    private class CellAndSpan {
+        int x, y;
+        int spanX, spanY;
+
+        public CellAndSpan() {
+        }
+
+        public void copy(CellAndSpan copy) {
+            copy.x = x;
+            copy.y = y;
+            copy.spanX = spanX;
+            copy.spanY = spanY;
+        }
+
+        public CellAndSpan(int x, int y, int spanX, int spanY) {
+            this.x = x;
+            this.y = y;
+            this.spanX = spanX;
+            this.spanY = spanY;
+        }
+
+        public String toString() {
+            return "(" + x + ", " + y + ": " + spanX + ", " + spanY + ")";
+        }
+
+    }
+
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreView Considers space occupied by this view as unoccupied
+     * @param result Previously returned value to possibly recycle.
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestVacantArea(
+            int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+        return findNearestArea(pixelX, pixelY, spanX, spanY, ignoreView, true, result);
+    }
+
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param minSpanX The minimum horizontal span required
+     * @param minSpanY The minimum vertical span required
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreView Considers space occupied by this view as unoccupied
+     * @param result Previously returned value to possibly recycle.
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY,
+            int spanX, int spanY, View ignoreView, int[] result, int[] resultSpan) {
+        return findNearestArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, ignoreView, true,
+                result, resultSpan, mOccupied);
+    }
+
+    /**
+     * Find a starting cell position that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreView Considers space occupied by this view as unoccupied
+     * @param result Previously returned value to possibly recycle.
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestArea(
+            int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+        return findNearestArea(pixelX, pixelY, spanX, spanY, null, false, result);
+    }
+
+    boolean existsEmptyCell() {
+        return findCellForSpan(null, 1, 1);
+    }
+
+    /**
+     * Finds the upper-left coordinate of the first rectangle in the grid that can
+     * hold a cell of the specified dimensions. If intersectX and intersectY are not -1,
+     * then this method will only return coordinates for rectangles that contain the cell
+     * (intersectX, intersectY)
+     *
+     * @param cellXY The array that will contain the position of a vacant cell if such a cell
+     *               can be found.
+     * @param spanX The horizontal span of the cell we want to find.
+     * @param spanY The vertical span of the cell we want to find.
+     *
+     * @return True if a vacant cell of the specified dimension was found, false otherwise.
+     */
+    boolean findCellForSpan(int[] cellXY, int spanX, int spanY) {
+        return findCellForSpanThatIntersectsIgnoring(cellXY, spanX, spanY, -1, -1, null, mOccupied);
+    }
+
+    /**
+     * Like above, but ignores any cells occupied by the item "ignoreView"
+     *
+     * @param cellXY The array that will contain the position of a vacant cell if such a cell
+     *               can be found.
+     * @param spanX The horizontal span of the cell we want to find.
+     * @param spanY The vertical span of the cell we want to find.
+     * @param ignoreView The home screen item we should treat as not occupying any space
+     * @return
+     */
+    boolean findCellForSpanIgnoring(int[] cellXY, int spanX, int spanY, View ignoreView) {
+        return findCellForSpanThatIntersectsIgnoring(cellXY, spanX, spanY, -1, -1,
+                ignoreView, mOccupied);
+    }
+
+    /**
+     * Like above, but if intersectX and intersectY are not -1, then this method will try to
+     * return coordinates for rectangles that contain the cell [intersectX, intersectY]
+     *
+     * @param spanX The horizontal span of the cell we want to find.
+     * @param spanY The vertical span of the cell we want to find.
+     * @param ignoreView The home screen item we should treat as not occupying any space
+     * @param intersectX The X coordinate of the cell that we should try to overlap
+     * @param intersectX The Y coordinate of the cell that we should try to overlap
+     *
+     * @return True if a vacant cell of the specified dimension was found, false otherwise.
+     */
+    boolean findCellForSpanThatIntersects(int[] cellXY, int spanX, int spanY,
+            int intersectX, int intersectY) {
+        return findCellForSpanThatIntersectsIgnoring(
+                cellXY, spanX, spanY, intersectX, intersectY, null, mOccupied);
+    }
+
+    /**
+     * The superset of the above two methods
+     */
+    boolean findCellForSpanThatIntersectsIgnoring(int[] cellXY, int spanX, int spanY,
+            int intersectX, int intersectY, View ignoreView, boolean occupied[][]) {
+        // mark space take by ignoreView as available (method checks if ignoreView is null)
+        markCellsAsUnoccupiedForView(ignoreView, occupied);
+
+        boolean foundCell = false;
+        while (true) {
+            int startX = 0;
+            if (intersectX >= 0) {
+                startX = Math.max(startX, intersectX - (spanX - 1));
+            }
+            int endX = mCountX - (spanX - 1);
+            if (intersectX >= 0) {
+                endX = Math.min(endX, intersectX + (spanX - 1) + (spanX == 1 ? 1 : 0));
+            }
+            int startY = 0;
+            if (intersectY >= 0) {
+                startY = Math.max(startY, intersectY - (spanY - 1));
+            }
+            int endY = mCountY - (spanY - 1);
+            if (intersectY >= 0) {
+                endY = Math.min(endY, intersectY + (spanY - 1) + (spanY == 1 ? 1 : 0));
+            }
+
+            for (int y = startY; y < endY && !foundCell; y++) {
+                inner:
+                for (int x = startX; x < endX; x++) {
+                    for (int i = 0; i < spanX; i++) {
+                        for (int j = 0; j < spanY; j++) {
+                            if (occupied[x + i][y + j]) {
+                                // small optimization: we can skip to after the column we just found
+                                // an occupied cell
+                                x += i;
+                                continue inner;
+                            }
+                        }
+                    }
+                    if (cellXY != null) {
+                        cellXY[0] = x;
+                        cellXY[1] = y;
+                    }
+                    foundCell = true;
+                    break;
+                }
+            }
+            if (intersectX == -1 && intersectY == -1) {
+                break;
+            } else {
+                // if we failed to find anything, try again but without any requirements of
+                // intersecting
+                intersectX = -1;
+                intersectY = -1;
+                continue;
+            }
+        }
+
+        // re-mark space taken by ignoreView as occupied
+        markCellsAsOccupiedForView(ignoreView, occupied);
+        return foundCell;
+    }
+
+    /**
+     * A drag event has begun over this layout.
+     * It may have begun over this layout (in which case onDragChild is called first),
+     * or it may have begun on another layout.
+     */
+    void onDragEnter() {
+        mDragEnforcer.onDragEnter();
+        mDragging = true;
+    }
+
+    /**
+     * Called when drag has left this CellLayout or has been completed (successfully or not)
+     */
+    void onDragExit() {
+        mDragEnforcer.onDragExit();
+        // This can actually be called when we aren't in a drag, e.g. when adding a new
+        // item to this layout via the customize drawer.
+        // Guard against that case.
+        if (mDragging) {
+            mDragging = false;
+        }
+
+        // Invalidate the drag data
+        mDragCell[0] = mDragCell[1] = -1;
+        mDragOutlineAnims[mDragOutlineCurrent].animateOut();
+        mDragOutlineCurrent = (mDragOutlineCurrent + 1) % mDragOutlineAnims.length;
+        revertTempState();
+        setIsDragOverlapping(false);
+    }
+
+    /**
+     * Mark a child as having been dropped.
+     * At the beginning of the drag operation, the child may have been on another
+     * screen, but it is re-parented before this method is called.
+     *
+     * @param child The child that is being dropped
+     */
+    void onDropChild(View child) {
+        if (child != null) {
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            lp.dropped = true;
+            child.requestLayout();
+        }
+    }
+
+    /**
+     * Computes a bounding rectangle for a range of cells
+     *
+     * @param cellX X coordinate of upper left corner expressed as a cell position
+     * @param cellY Y coordinate of upper left corner expressed as a cell position
+     * @param cellHSpan Width in cells
+     * @param cellVSpan Height in cells
+     * @param resultRect Rect into which to put the results
+     */
+    public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, Rect resultRect) {
+        final int cellWidth = mCellWidth;
+        final int cellHeight = mCellHeight;
+        final int widthGap = mWidthGap;
+        final int heightGap = mHeightGap;
+
+        final int hStartPadding = getPaddingLeft();
+        final int vStartPadding = getPaddingTop();
+
+        int width = cellHSpan * cellWidth + ((cellHSpan - 1) * widthGap);
+        int height = cellVSpan * cellHeight + ((cellVSpan - 1) * heightGap);
+
+        int x = hStartPadding + cellX * (cellWidth + widthGap);
+        int y = vStartPadding + cellY * (cellHeight + heightGap);
+
+        resultRect.set(x, y, x + width, y + height);
+    }
+
+    /**
+     * Computes the required horizontal and vertical cell spans to always
+     * fit the given rectangle.
+     *
+     * @param width Width in pixels
+     * @param height Height in pixels
+     * @param result An array of length 2 in which to store the result (may be null).
+     */
+    public int[] rectToCell(int width, int height, int[] result) {
+        return rectToCell(getResources(), width, height, result);
+    }
+
+    public static int[] rectToCell(Resources resources, int width, int height, int[] result) {
+        // Always assume we're working with the smallest span to make sure we
+        // reserve enough space in both orientations.
+        int actualWidth = resources.getDimensionPixelSize(R.dimen.workspace_cell_width);
+        int actualHeight = resources.getDimensionPixelSize(R.dimen.workspace_cell_height);
+        int smallerSize = Math.min(actualWidth, actualHeight);
+
+        // Always round up to next largest cell
+        int spanX = (int) Math.ceil(width / (float) smallerSize);
+        int spanY = (int) Math.ceil(height / (float) smallerSize);
+
+        if (result == null) {
+            return new int[] { spanX, spanY };
+        }
+        result[0] = spanX;
+        result[1] = spanY;
+        return result;
+    }
+
+    public int[] cellSpansToSize(int hSpans, int vSpans) {
+        int[] size = new int[2];
+        size[0] = hSpans * mCellWidth + (hSpans - 1) * mWidthGap;
+        size[1] = vSpans * mCellHeight + (vSpans - 1) * mHeightGap;
+        return size;
+    }
+
+    /**
+     * Calculate the grid spans needed to fit given item
+     */
+    public void calculateSpans(ItemInfo info) {
+        final int minWidth;
+        final int minHeight;
+
+        if (info instanceof LauncherAppWidgetInfo) {
+            minWidth = ((LauncherAppWidgetInfo) info).minWidth;
+            minHeight = ((LauncherAppWidgetInfo) info).minHeight;
+        } else if (info instanceof PendingAddWidgetInfo) {
+            minWidth = ((PendingAddWidgetInfo) info).minWidth;
+            minHeight = ((PendingAddWidgetInfo) info).minHeight;
+        } else {
+            // It's not a widget, so it must be 1x1
+            info.spanX = info.spanY = 1;
+            return;
+        }
+        int[] spans = rectToCell(minWidth, minHeight, null);
+        info.spanX = spans[0];
+        info.spanY = spans[1];
+    }
+
+    /**
+     * Find the first vacant cell, if there is one.
+     *
+     * @param vacant Holds the x and y coordinate of the vacant cell
+     * @param spanX Horizontal cell span.
+     * @param spanY Vertical cell span.
+     *
+     * @return True if a vacant cell was found
+     */
+    public boolean getVacantCell(int[] vacant, int spanX, int spanY) {
+
+        return findVacantCell(vacant, spanX, spanY, mCountX, mCountY, mOccupied);
+    }
+
+    static boolean findVacantCell(int[] vacant, int spanX, int spanY,
+            int xCount, int yCount, boolean[][] occupied) {
+
+        for (int y = 0; y < yCount; y++) {
+            for (int x = 0; x < xCount; x++) {
+                boolean available = !occupied[x][y];
+out:            for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
+                    for (int j = y; j < y + spanY - 1 && y < yCount; j++) {
+                        available = available && !occupied[i][j];
+                        if (!available) break out;
+                    }
+                }
+
+                if (available) {
+                    vacant[0] = x;
+                    vacant[1] = y;
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private void clearOccupiedCells() {
+        for (int x = 0; x < mCountX; x++) {
+            for (int y = 0; y < mCountY; y++) {
+                mOccupied[x][y] = false;
+            }
+        }
+    }
+
+    public void onMove(View view, int newCellX, int newCellY, int newSpanX, int newSpanY) {
+        markCellsAsUnoccupiedForView(view);
+        markCellsForView(newCellX, newCellY, newSpanX, newSpanY, mOccupied, true);
+    }
+
+    public void markCellsAsOccupiedForView(View view) {
+        markCellsAsOccupiedForView(view, mOccupied);
+    }
+    public void markCellsAsOccupiedForView(View view, boolean[][] occupied) {
+        if (view == null || view.getParent() != mShortcutsAndWidgets) return;
+        LayoutParams lp = (LayoutParams) view.getLayoutParams();
+        markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, occupied, true);
+    }
+
+    public void markCellsAsUnoccupiedForView(View view) {
+        markCellsAsUnoccupiedForView(view, mOccupied);
+    }
+    public void markCellsAsUnoccupiedForView(View view, boolean occupied[][]) {
+        if (view == null || view.getParent() != mShortcutsAndWidgets) return;
+        LayoutParams lp = (LayoutParams) view.getLayoutParams();
+        markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, occupied, false);
+    }
+
+    private void markCellsForView(int cellX, int cellY, int spanX, int spanY, boolean[][] occupied,
+            boolean value) {
+        if (cellX < 0 || cellY < 0) return;
+        for (int x = cellX; x < cellX + spanX && x < mCountX; x++) {
+            for (int y = cellY; y < cellY + spanY && y < mCountY; y++) {
+                occupied[x][y] = value;
+            }
+        }
+    }
+
+    public int getDesiredWidth() {
+        return getPaddingLeft() + getPaddingRight() + (mCountX * mCellWidth) +
+                (Math.max((mCountX - 1), 0) * mWidthGap);
+    }
+
+    public int getDesiredHeight()  {
+        return getPaddingTop() + getPaddingBottom() + (mCountY * mCellHeight) +
+                (Math.max((mCountY - 1), 0) * mHeightGap);
+    }
+
+    public boolean isOccupied(int x, int y) {
+        if (x < mCountX && y < mCountY) {
+            return mOccupied[x][y];
+        } else {
+            throw new RuntimeException("Position exceeds the bound of this CellLayout");
+        }
+    }
+
+    @Override
+    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new CellLayout.LayoutParams(getContext(), attrs);
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof CellLayout.LayoutParams;
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return new CellLayout.LayoutParams(p);
+    }
+
+    public static class CellLayoutAnimationController extends LayoutAnimationController {
+        public CellLayoutAnimationController(Animation animation, float delay) {
+            super(animation, delay);
+        }
+
+        @Override
+        protected long getDelayForView(View view) {
+            return (int) (Math.random() * 150);
+        }
+    }
+
+    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
+        /**
+         * Horizontal location of the item in the grid.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellX;
+
+        /**
+         * Vertical location of the item in the grid.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellY;
+
+        /**
+         * Temporary horizontal location of the item in the grid during reorder
+         */
+        public int tmpCellX;
+
+        /**
+         * Temporary vertical location of the item in the grid during reorder
+         */
+        public int tmpCellY;
+
+        /**
+         * Indicates that the temporary coordinates should be used to layout the items
+         */
+        public boolean useTmpCoords;
+
+        /**
+         * Number of cells spanned horizontally by the item.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellHSpan;
+
+        /**
+         * Number of cells spanned vertically by the item.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellVSpan;
+
+        /**
+         * Indicates whether the item will set its x, y, width and height parameters freely,
+         * or whether these will be computed based on cellX, cellY, cellHSpan and cellVSpan.
+         */
+        public boolean isLockedToGrid = true;
+
+        /**
+         * Indicates whether this item can be reordered. Always true except in the case of the
+         * the AllApps button.
+         */
+        public boolean canReorder = true;
+
+        // X coordinate of the view in the layout.
+        @ViewDebug.ExportedProperty
+        int x;
+        // Y coordinate of the view in the layout.
+        @ViewDebug.ExportedProperty
+        int y;
+
+        boolean dropped;
+
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+            cellHSpan = 1;
+            cellVSpan = 1;
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+            cellHSpan = 1;
+            cellVSpan = 1;
+        }
+
+        public LayoutParams(LayoutParams source) {
+            super(source);
+            this.cellX = source.cellX;
+            this.cellY = source.cellY;
+            this.cellHSpan = source.cellHSpan;
+            this.cellVSpan = source.cellVSpan;
+        }
+
+        public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
+            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+            this.cellX = cellX;
+            this.cellY = cellY;
+            this.cellHSpan = cellHSpan;
+            this.cellVSpan = cellVSpan;
+        }
+
+        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap) {
+            if (isLockedToGrid) {
+                final int myCellHSpan = cellHSpan;
+                final int myCellVSpan = cellVSpan;
+                final int myCellX = useTmpCoords ? tmpCellX : cellX;
+                final int myCellY = useTmpCoords ? tmpCellY : cellY;
+
+                width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
+                        leftMargin - rightMargin;
+                height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
+                        topMargin - bottomMargin;
+                x = (int) (myCellX * (cellWidth + widthGap) + leftMargin);
+                y = (int) (myCellY * (cellHeight + heightGap) + topMargin);
+            }
+        }
+
+        public String toString() {
+            return "(" + this.cellX + ", " + this.cellY + ")";
+        }
+
+        public void setWidth(int width) {
+            this.width = width;
+        }
+
+        public int getWidth() {
+            return width;
+        }
+
+        public void setHeight(int height) {
+            this.height = height;
+        }
+
+        public int getHeight() {
+            return height;
+        }
+
+        public void setX(int x) {
+            this.x = x;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public void setY(int y) {
+            this.y = y;
+        }
+
+        public int getY() {
+            return y;
+        }
+    }
+
+    // This class stores info for two purposes:
+    // 1. When dragging items (mDragInfo in Workspace), we store the View, its cellX & cellY,
+    //    its spanX, spanY, and the screen it is on
+    // 2. When long clicking on an empty cell in a CellLayout, we save information about the
+    //    cellX and cellY coordinates and which page was clicked. We then set this as a tag on
+    //    the CellLayout that was long clicked
+    static final class CellInfo {
+        View cell;
+        int cellX = -1;
+        int cellY = -1;
+        int spanX;
+        int spanY;
+        int screen;
+        long container;
+
+        @Override
+        public String toString() {
+            return "Cell[view=" + (cell == null ? "null" : cell.getClass())
+                    + ", x=" + cellX + ", y=" + cellY + "]";
+        }
+    }
+
+    public boolean lastDownOnOccupiedCell() {
+        return mLastDownOnOccupiedCell;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/CheckLongPressHelper.java b/FairphoneHome/src/org/fairphone/launcher/CheckLongPressHelper.java
new file mode 100644
index 0000000..f6bea83
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/CheckLongPressHelper.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.view.View;
+
+public class CheckLongPressHelper {
+    private View mView;
+    private boolean mHasPerformedLongPress;
+    private CheckForLongPress mPendingCheckForLongPress;
+
+    class CheckForLongPress implements Runnable {
+        public void run() {
+            if ((mView.getParent() != null) && mView.hasWindowFocus()
+                    && !mHasPerformedLongPress) {
+                if (mView.performLongClick()) {
+                    mView.setPressed(false);
+                    mHasPerformedLongPress = true;
+                }
+            }
+        }
+    }
+
+    public CheckLongPressHelper(View v) {
+        mView = v;
+    }
+
+    public void postCheckForLongPress() {
+        mHasPerformedLongPress = false;
+
+        if (mPendingCheckForLongPress == null) {
+            mPendingCheckForLongPress = new CheckForLongPress();
+        }
+        mView.postDelayed(mPendingCheckForLongPress, LauncherApplication.getLongPressTimeout());
+    }
+
+    public void cancelLongPress() {
+        mHasPerformedLongPress = false;
+        if (mPendingCheckForLongPress != null) {
+            mView.removeCallbacks(mPendingCheckForLongPress);
+            mPendingCheckForLongPress = null;
+        }
+    }
+
+    public boolean hasPerformedLongPress() {
+        return mHasPerformedLongPress;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Cling.java b/FairphoneHome/src/org/fairphone/launcher/Cling.java
new file mode 100644
index 0000000..90b977b
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Cling.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.FocusFinder;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import org.fairphone.launcher.R;
+
+public class Cling extends FrameLayout {
+
+    static final String WORKSPACE_CLING_DISMISSED_KEY = "cling.workspace.dismissed";
+    static final String ALLAPPS_CLING_DISMISSED_KEY = "cling.allapps.dismissed";
+    static final String FOLDER_CLING_DISMISSED_KEY = "cling.folder.dismissed";
+
+    private static String WORKSPACE_PORTRAIT = "workspace_portrait";
+    private static String WORKSPACE_LANDSCAPE = "workspace_landscape";
+    private static String WORKSPACE_LARGE = "workspace_large";
+    private static String WORKSPACE_CUSTOM = "workspace_custom";
+
+    private static String ALLAPPS_PORTRAIT = "all_apps_portrait";
+    private static String ALLAPPS_LANDSCAPE = "all_apps_landscape";
+    private static String ALLAPPS_LARGE = "all_apps_large";
+
+    private static String FOLDER_PORTRAIT = "folder_portrait";
+    private static String FOLDER_LANDSCAPE = "folder_landscape";
+    private static String FOLDER_LARGE = "folder_large";
+
+    private Launcher mLauncher;
+    private boolean mIsInitialized;
+    private String mDrawIdentifier;
+    private Drawable mBackground;
+    private Drawable mPunchThroughGraphic;
+    private Drawable mHandTouchGraphic;
+    private int mPunchThroughGraphicCenterRadius;
+    private int mAppIconSize;
+    private int mButtonBarHeight;
+    private float mRevealRadius;
+    private int[] mPositionData;
+
+    private Paint mErasePaint;
+
+    public Cling(Context context) {
+        this(context, null, 0);
+    }
+
+    public Cling(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public Cling(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Cling, defStyle, 0);
+        mDrawIdentifier = a.getString(R.styleable.Cling_drawIdentifier);
+        a.recycle();
+
+        setClickable(true);
+    }
+
+    void init(Launcher l, int[] positionData) {
+        if (!mIsInitialized) {
+            mLauncher = l;
+            mPositionData = positionData;
+
+            Resources r = getContext().getResources();
+
+            mPunchThroughGraphic = r.getDrawable(R.drawable.cling);
+            mPunchThroughGraphicCenterRadius =
+                r.getDimensionPixelSize(R.dimen.clingPunchThroughGraphicCenterRadius);
+            mAppIconSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
+            mRevealRadius = r.getDimensionPixelSize(R.dimen.reveal_radius) * 1f;
+            mButtonBarHeight = r.getDimensionPixelSize(R.dimen.button_bar_height);
+
+            mErasePaint = new Paint();
+            mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
+            mErasePaint.setColor(0xFFFFFF);
+            mErasePaint.setAlpha(0);
+
+            mIsInitialized = true;
+        }
+    }
+
+    void cleanup() {
+        mBackground = null;
+        mPunchThroughGraphic = null;
+        mHandTouchGraphic = null;
+        mIsInitialized = false;
+    }
+
+    public String getDrawIdentifier() {
+        return mDrawIdentifier;
+    }
+
+    private int[] getPunchThroughPositions() {
+        if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT)) {
+            return new int[]{getMeasuredWidth() / 2, getMeasuredHeight() - (mButtonBarHeight / 2)};
+        } else if (mDrawIdentifier.equals(WORKSPACE_LANDSCAPE)) {
+            return new int[]{getMeasuredWidth() - (mButtonBarHeight / 2), getMeasuredHeight() / 2};
+        } else if (mDrawIdentifier.equals(WORKSPACE_LARGE)) {
+            final float scale = LauncherApplication.getScreenDensity();
+            final int cornerXOffset = (int) (scale * 15);
+            final int cornerYOffset = (int) (scale * 10);
+            return new int[]{getMeasuredWidth() - cornerXOffset, cornerYOffset};
+        } else if (mDrawIdentifier.equals(ALLAPPS_PORTRAIT) ||
+                   mDrawIdentifier.equals(ALLAPPS_LANDSCAPE) ||
+                   mDrawIdentifier.equals(ALLAPPS_LARGE)) {
+            return mPositionData;
+        }
+        return new int[]{-1, -1};
+    }
+
+    @Override
+    public View focusSearch(int direction) {
+        return this.focusSearch(this, direction);
+    }
+
+    @Override
+    public View focusSearch(View focused, int direction) {
+        return FocusFinder.getInstance().findNextFocus(this, focused, direction);
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        return (mDrawIdentifier.equals(WORKSPACE_PORTRAIT)
+                || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE)
+                || mDrawIdentifier.equals(WORKSPACE_LARGE)
+                || mDrawIdentifier.equals(ALLAPPS_PORTRAIT)
+                || mDrawIdentifier.equals(ALLAPPS_LANDSCAPE)
+                || mDrawIdentifier.equals(ALLAPPS_LARGE)
+                || mDrawIdentifier.equals(WORKSPACE_CUSTOM));
+    }
+
+    @Override
+    public boolean onTouchEvent(android.view.MotionEvent event) {
+        if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
+            mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
+            mDrawIdentifier.equals(WORKSPACE_LARGE) ||
+            mDrawIdentifier.equals(ALLAPPS_PORTRAIT) ||
+            mDrawIdentifier.equals(ALLAPPS_LANDSCAPE) ||
+            mDrawIdentifier.equals(ALLAPPS_LARGE)) {
+
+            int[] positions = getPunchThroughPositions();
+            for (int i = 0; i < positions.length; i += 2) {
+                double diff = Math.sqrt(Math.pow(event.getX() - positions[i], 2) +
+                        Math.pow(event.getY() - positions[i + 1], 2));
+                if (diff < mRevealRadius) {
+                    return false;
+                }
+            }
+        } else if (mDrawIdentifier.equals(FOLDER_PORTRAIT) ||
+                   mDrawIdentifier.equals(FOLDER_LANDSCAPE) ||
+                   mDrawIdentifier.equals(FOLDER_LARGE)) {
+            Folder f = mLauncher.getWorkspace().getOpenFolder();
+            if (f != null) {
+                Rect r = new Rect();
+                f.getHitRect(r);
+                if (r.contains((int) event.getX(), (int) event.getY())) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    };
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        if (mIsInitialized) {
+            DisplayMetrics metrics = new DisplayMetrics();
+            mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+            // Initialize the draw buffer (to allow punching through)
+            Bitmap b = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
+                    Bitmap.Config.ARGB_8888);
+            Canvas c = new Canvas(b);
+
+            // Draw the background
+            if (mBackground == null) {
+                if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
+                        mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
+                        mDrawIdentifier.equals(WORKSPACE_LARGE)) {
+                    mBackground = getResources().getDrawable(R.drawable.bg_cling1);
+                } else if (mDrawIdentifier.equals(ALLAPPS_PORTRAIT) ||
+                        mDrawIdentifier.equals(ALLAPPS_LANDSCAPE) ||
+                        mDrawIdentifier.equals(ALLAPPS_LARGE)) {
+                    mBackground = getResources().getDrawable(R.drawable.bg_cling2);
+                } else if (mDrawIdentifier.equals(FOLDER_PORTRAIT) ||
+                        mDrawIdentifier.equals(FOLDER_LANDSCAPE)) {
+                    mBackground = getResources().getDrawable(R.drawable.bg_cling3);
+                } else if (mDrawIdentifier.equals(FOLDER_LARGE)) {
+                    mBackground = getResources().getDrawable(R.drawable.bg_cling4);
+                } else if (mDrawIdentifier.equals(WORKSPACE_CUSTOM)) {
+                    mBackground = getResources().getDrawable(R.drawable.bg_cling5);
+                }
+            }
+            if (mBackground != null) {
+                mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
+                mBackground.draw(c);
+            } else {
+                c.drawColor(0x99000000);
+            }
+
+            int cx = -1;
+            int cy = -1;
+            float scale = mRevealRadius / mPunchThroughGraphicCenterRadius;
+            int dw = (int) (scale * mPunchThroughGraphic.getIntrinsicWidth());
+            int dh = (int) (scale * mPunchThroughGraphic.getIntrinsicHeight());
+
+            // Determine where to draw the punch through graphic
+            int[] positions = getPunchThroughPositions();
+            for (int i = 0; i < positions.length; i += 2) {
+                cx = positions[i];
+                cy = positions[i + 1];
+                if (cx > -1 && cy > -1) {
+                    c.drawCircle(cx, cy, mRevealRadius, mErasePaint);
+                    mPunchThroughGraphic.setBounds(cx - dw/2, cy - dh/2, cx + dw/2, cy + dh/2);
+                    mPunchThroughGraphic.draw(c);
+                }
+            }
+
+            // Draw the hand graphic in All Apps
+            if (mDrawIdentifier.equals(ALLAPPS_PORTRAIT) ||
+                mDrawIdentifier.equals(ALLAPPS_LANDSCAPE) ||
+                mDrawIdentifier.equals(ALLAPPS_LARGE)) {
+                if (mHandTouchGraphic == null) {
+                    mHandTouchGraphic = getResources().getDrawable(R.drawable.hand);
+                }
+                int offset = mAppIconSize / 4;
+                mHandTouchGraphic.setBounds(cx + offset, cy + offset,
+                        cx + mHandTouchGraphic.getIntrinsicWidth() + offset,
+                        cy + mHandTouchGraphic.getIntrinsicHeight() + offset);
+                mHandTouchGraphic.draw(c);
+            }
+
+            canvas.drawBitmap(b, 0, 0, null);
+            c.setBitmap(null);
+            b = null;
+        }
+
+        // Draw the rest of the cling
+        super.dispatchDraw(canvas);
+    };
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DeferredHandler.java b/FairphoneHome/src/org/fairphone/launcher/DeferredHandler.java
new file mode 100644
index 0000000..bd8d0b8
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DeferredHandler.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+import android.util.Pair;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * Queue of things to run on a looper thread.  Items posted with {@link #post} will not
+ * be actually enqued on the handler until after the last one has run, to keep from
+ * starving the thread.
+ *
+ * This class is fifo.
+ */
+public class DeferredHandler {
+    private LinkedList<Pair<Runnable, Integer>> mQueue = new LinkedList<Pair<Runnable, Integer>>();
+    private MessageQueue mMessageQueue = Looper.myQueue();
+    private Impl mHandler = new Impl();
+
+    private class Impl extends Handler implements MessageQueue.IdleHandler {
+        public void handleMessage(Message msg) {
+            Pair<Runnable, Integer> p;
+            Runnable r;
+            synchronized (mQueue) {
+                if (mQueue.size() == 0) {
+                    return;
+                }
+                p = mQueue.removeFirst();
+                r = p.first;
+            }
+            r.run();
+            synchronized (mQueue) {
+                scheduleNextLocked();
+            }
+        }
+
+        public boolean queueIdle() {
+            handleMessage(null);
+            return false;
+        }
+    }
+
+    private class IdleRunnable implements Runnable {
+        Runnable mRunnable;
+
+        IdleRunnable(Runnable r) {
+            mRunnable = r;
+        }
+
+        public void run() {
+            mRunnable.run();
+        }
+    }
+
+    public DeferredHandler() {
+    }
+
+    /** Schedule runnable to run after everything that's on the queue right now. */
+    public void post(Runnable runnable) {
+        post(runnable, 0);
+    }
+    public void post(Runnable runnable, int type) {
+        synchronized (mQueue) {
+            mQueue.add(new Pair<Runnable, Integer>(runnable, type));
+            if (mQueue.size() == 1) {
+                scheduleNextLocked();
+            }
+        }
+    }
+
+    /** Schedule runnable to run when the queue goes idle. */
+    public void postIdle(final Runnable runnable) {
+        postIdle(runnable, 0);
+    }
+    public void postIdle(final Runnable runnable, int type) {
+        post(new IdleRunnable(runnable), type);
+    }
+
+    public void cancelRunnable(Runnable runnable) {
+        synchronized (mQueue) {
+            while (mQueue.remove(runnable)) { }
+        }
+    }
+    public void cancelAllRunnablesOfType(int type) {
+        synchronized (mQueue) {
+            ListIterator<Pair<Runnable, Integer>> iter = mQueue.listIterator();
+            Pair<Runnable, Integer> p;
+            while (iter.hasNext()) {
+                p = iter.next();
+                if (p.second == type) {
+                    iter.remove();
+                }
+            }
+        }
+    }
+
+    public void cancel() {
+        synchronized (mQueue) {
+            mQueue.clear();
+        }
+    }
+
+    /** Runs all queued Runnables from the calling thread. */
+    public void flush() {
+        LinkedList<Pair<Runnable, Integer>> queue = new LinkedList<Pair<Runnable, Integer>>();
+        synchronized (mQueue) {
+            queue.addAll(mQueue);
+            mQueue.clear();
+        }
+        for (Pair<Runnable, Integer> p : queue) {
+            p.first.run();
+        }
+    }
+
+    void scheduleNextLocked() {
+        if (mQueue.size() > 0) {
+            Pair<Runnable, Integer> p = mQueue.getFirst();
+            Runnable peek = p.first;
+            if (peek instanceof IdleRunnable) {
+                mMessageQueue.addIdleHandler(mHandler);
+            } else {
+                mHandler.sendEmptyMessage(1);
+            }
+        }
+    }
+}
+
diff --git a/FairphoneHome/src/org/fairphone/launcher/DeleteDropTarget.java b/FairphoneHome/src/org/fairphone/launcher/DeleteDropTarget.java
new file mode 100644
index 0000000..2124526
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DeleteDropTarget.java
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.drawable.TransitionDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+
+import org.fairphone.launcher.R;
+
+public class DeleteDropTarget extends ButtonDropTarget {
+    private static int DELETE_ANIMATION_DURATION = 285;
+    private static int FLING_DELETE_ANIMATION_DURATION = 350;
+    private static float FLING_TO_DELETE_FRICTION = 0.035f;
+    private static int MODE_FLING_DELETE_TO_TRASH = 0;
+    private static int MODE_FLING_DELETE_ALONG_VECTOR = 1;
+
+    private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR;
+
+    private ColorStateList mOriginalTextColor;
+    private TransitionDrawable mUninstallDrawable;
+    private TransitionDrawable mRemoveDrawable;
+    private TransitionDrawable mCurrentDrawable;
+
+    public DeleteDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the drawable
+        mOriginalTextColor = getTextColors();
+
+        // Get the hover color
+        Resources r = getResources();
+        mHoverColor = r.getColor(R.color.delete_target_hover_tint);
+        mUninstallDrawable = (TransitionDrawable) 
+                r.getDrawable(R.drawable.uninstall_target_selector);
+        mRemoveDrawable = (TransitionDrawable) r.getDrawable(R.drawable.remove_target_selector);
+
+        mRemoveDrawable.setCrossFadeEnabled(true);
+        mUninstallDrawable.setCrossFadeEnabled(true);
+
+        // The current drawable is set to either the remove drawable or the uninstall drawable 
+        // and is initially set to the remove drawable, as set in the layout xml.
+        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
+
+        // Remove the text in the Phone UI in landscape
+        int orientation = getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            if (!LauncherApplication.isScreenLarge()) {
+                setText("");
+            }
+        }
+    }
+
+    private boolean isAllAppsApplication(DragSource source, Object info) {
+        return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
+    }
+    private boolean isAllAppsWidget(DragSource source, Object info) {
+        if (source instanceof AppsCustomizePagedView) {
+            if (info instanceof PendingAddItemInfo) {
+                PendingAddItemInfo addInfo = (PendingAddItemInfo) info;
+                switch (addInfo.itemType) {
+                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                    case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                        return true;
+                }
+            }
+        }
+        return false;
+    }
+    private boolean isDragSourceWorkspaceOrFolder(DragObject d) {
+        return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder);
+    }
+    private boolean isWorkspaceOrFolderApplication(DragObject d) {
+        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo);
+    }
+    private boolean isWorkspaceOrFolderWidget(DragObject d) {
+        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo);
+    }
+    private boolean isWorkspaceFolder(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
+    }
+
+    private void setHoverColor() {
+        mCurrentDrawable.startTransition(mTransitionDuration);
+        setTextColor(mHoverColor);
+    }
+    private void resetHoverColor() {
+        mCurrentDrawable.resetTransition();
+        setTextColor(mOriginalTextColor);
+    }
+
+    @Override
+    public boolean acceptDrop(DragObject d) {
+        // We can remove everything including App shortcuts, folders, widgets, etc.
+        return true;
+    }
+
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        boolean isVisible = true;
+        boolean isUninstall = false;
+
+        // If we are dragging a widget from AppsCustomize, hide the delete target
+        if (isAllAppsWidget(source, info)) {
+            isVisible = false;
+        }
+
+        // If we are dragging an application from AppsCustomize, only show the control if we can
+        // delete the app (it was downloaded), and rename the string to "uninstall" in such a case
+        if (isAllAppsApplication(source, info)) {
+            ApplicationInfo appInfo = (ApplicationInfo) info;
+            if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+                isUninstall = true;
+            } else {
+                isVisible = false;
+            }
+        }
+
+        if (isUninstall) {
+            setCompoundDrawablesWithIntrinsicBounds(mUninstallDrawable, null, null, null);
+        } else {
+            setCompoundDrawablesWithIntrinsicBounds(mRemoveDrawable, null, null, null);
+        }
+        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
+
+        mActive = isVisible;
+        resetHoverColor();
+        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
+        if (getText().length() > 0) {
+            setText(isUninstall ? R.string.delete_target_uninstall_label
+                : R.string.delete_target_label);
+        }
+    }
+
+    @Override
+    public void onDragEnd() {
+        super.onDragEnd();
+        mActive = false;
+    }
+
+    public void onDragEnter(DragObject d) {
+        super.onDragEnter(d);
+
+        setHoverColor();
+    }
+
+    public void onDragExit(DragObject d) {
+        super.onDragExit(d);
+
+        if (!d.dragComplete) {
+            resetHoverColor();
+        } else {
+            // Restore the hover color if we are deleting
+            d.dragView.setColor(mHoverColor);
+        }
+    }
+
+    private void animateToTrashAndCompleteDrop(final DragObject d) {
+        DragLayer dragLayer = mLauncher.getDragLayer();
+        Rect from = new Rect();
+        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
+        Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
+                mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight());
+        float scale = (float) to.width() / from.width();
+
+        mSearchDropTargetBar.deferOnDragEnd();
+        Runnable onAnimationEndRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mSearchDropTargetBar.onDragEnd();
+                mLauncher.exitSpringLoadedDragMode();
+                completeDrop(d);
+            }
+        };
+        dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
+                DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2),
+                new LinearInterpolator(), onAnimationEndRunnable,
+                DragLayer.ANIMATION_END_DISAPPEAR, null);
+    }
+
+    private void completeDrop(DragObject d) {
+        ItemInfo item = (ItemInfo) d.dragInfo;
+
+        if (isAllAppsApplication(d.dragSource, item)) {
+            // Uninstall the application if it is being dragged from AppsCustomize
+            mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
+        } else if (isWorkspaceOrFolderApplication(d)) {
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+        } else if (isWorkspaceFolder(d)) {
+            // Remove the folder from the workspace and delete the contents from launcher model
+            FolderInfo folderInfo = (FolderInfo) item;
+            mLauncher.removeFolder(folderInfo);
+            LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
+        } else if (isWorkspaceOrFolderWidget(d)) {
+            // Remove the widget from the workspace
+            mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+
+            final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
+            final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
+            if (appWidgetHost != null) {
+                // Deleting an app widget ID is a void call but writes to disk before returning
+                // to the caller...
+                new Thread("deleteAppWidgetId") {
+                    public void run() {
+                        appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+                    }
+                }.start();
+            }
+        }
+    }
+
+    public void onDrop(DragObject d) {
+        animateToTrashAndCompleteDrop(d);
+    }
+
+    /**
+     * Creates an animation from the current drag view to the delete trash icon.
+     */
+    private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer,
+            DragObject d, PointF vel, ViewConfiguration config) {
+        final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
+                mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight());
+        final Rect from = new Rect();
+        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
+
+        // Calculate how far along the velocity vector we should put the intermediate point on
+        // the bezier curve
+        float velocity = Math.abs(vel.length());
+        float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f));
+        int offsetY = (int) (-from.top * vp);
+        int offsetX = (int) (offsetY / (vel.y / vel.x));
+        final float y2 = from.top + offsetY;                        // intermediate t/l
+        final float x2 = from.left + offsetX;
+        final float x1 = from.left;                                 // drag view t/l
+        final float y1 = from.top;
+        final float x3 = to.left;                                   // delete target t/l
+        final float y3 = to.top;
+
+        final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() {
+            @Override
+            public float getInterpolation(float t) {
+                return t * t * t * t * t * t * t * t;
+            }
+        };
+        return new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final DragView dragView = (DragView) dragLayer.getAnimatedView();
+                float t = ((Float) animation.getAnimatedValue()).floatValue();
+                float tp = scaleAlphaInterpolator.getInterpolation(t);
+                float initialScale = dragView.getInitialScale();
+                float finalAlpha = 0.5f;
+                float scale = dragView.getScaleX();
+                float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f;
+                float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f;
+                float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) +
+                        (t * t) * x3;
+                float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) +
+                        (t * t) * y3;
+
+                dragView.setTranslationX(x);
+                dragView.setTranslationY(y);
+                dragView.setScaleX(initialScale * (1f - tp));
+                dragView.setScaleY(initialScale * (1f - tp));
+                dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp));
+            }
+        };
+    }
+
+    /**
+     * Creates an animation from the current drag view along its current velocity vector.
+     * For this animation, the alpha runs for a fixed duration and we update the position
+     * progressively.
+     */
+    private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
+        private DragLayer mDragLayer;
+        private PointF mVelocity;
+        private Rect mFrom;
+        private long mPrevTime;
+        private boolean mHasOffsetForScale;
+        private float mFriction;
+
+        private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
+
+        public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from,
+                long startTime, float friction) {
+            mDragLayer = dragLayer;
+            mVelocity = vel;
+            mFrom = from;
+            mPrevTime = startTime;
+            mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction);
+        }
+
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            final DragView dragView = (DragView) mDragLayer.getAnimatedView();
+            float t = ((Float) animation.getAnimatedValue()).floatValue();
+            long curTime = AnimationUtils.currentAnimationTimeMillis();
+
+            if (!mHasOffsetForScale) {
+                mHasOffsetForScale = true;
+                float scale = dragView.getScaleX();
+                float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f;
+                float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f;
+
+                mFrom.left += xOffset;
+                mFrom.top += yOffset;
+            }
+
+            mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
+            mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
+
+            dragView.setTranslationX(mFrom.left);
+            dragView.setTranslationY(mFrom.top);
+            dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
+
+            mVelocity.x *= mFriction;
+            mVelocity.y *= mFriction;
+            mPrevTime = curTime;
+        }
+    };
+    private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer,
+            DragObject d, PointF vel, final long startTime, final int duration,
+            ViewConfiguration config) {
+        final Rect from = new Rect();
+        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
+
+        return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime,
+                FLING_TO_DELETE_FRICTION);
+    }
+
+    public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) {
+        final boolean isAllApps = d.dragSource instanceof AppsCustomizePagedView;
+
+        // Don't highlight the icon as it's animating
+        d.dragView.setColor(0);
+        d.dragView.updateInitialScaleToCurrentScale();
+        // Don't highlight the target if we are flinging from AllApps
+        if (isAllApps) {
+            resetHoverColor();
+        }
+
+        if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
+            // Defer animating out the drop target if we are animating to it
+            mSearchDropTargetBar.deferOnDragEnd();
+            mSearchDropTargetBar.finishAnimations();
+        }
+
+        final ViewConfiguration config = ViewConfiguration.get(mLauncher);
+        final DragLayer dragLayer = mLauncher.getDragLayer();
+        final int duration = FLING_DELETE_ANIMATION_DURATION;
+        final long startTime = AnimationUtils.currentAnimationTimeMillis();
+
+        // NOTE: Because it takes time for the first frame of animation to actually be
+        // called and we expect the animation to be a continuation of the fling, we have
+        // to account for the time that has elapsed since the fling finished.  And since
+        // we don't have a startDelay, we will always get call to update when we call
+        // start() (which we want to ignore).
+        final TimeInterpolator tInterpolator = new TimeInterpolator() {
+            private int mCount = -1;
+            private float mOffset = 0f;
+
+            @Override
+            public float getInterpolation(float t) {
+                if (mCount < 0) {
+                    mCount++;
+                } else if (mCount == 0) {
+                    mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
+                            startTime) / duration);
+                    mCount++;
+                }
+                return Math.min(1f, mOffset + t);
+            }
+        };
+        AnimatorUpdateListener updateCb = null;
+        if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
+            updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config);
+        } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) {
+            updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime,
+                    duration, config);
+        }
+        Runnable onAnimationEndRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mSearchDropTargetBar.onDragEnd();
+
+                // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up
+                // itself, otherwise, complete the drop to initiate the deletion process
+                if (!isAllApps) {
+                    mLauncher.exitSpringLoadedDragMode();
+                    completeDrop(d);
+                }
+                mLauncher.getDragController().onDeferredEndFling(d);
+            }
+        };
+        dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable,
+                DragLayer.ANIMATION_END_DISAPPEAR, null);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DragController.java b/FairphoneHome/src/org/fairphone/launcher/DragController.java
new file mode 100644
index 0000000..bfbf5f8
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DragController.java
@@ -0,0 +1,1058 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.edgeswipe.ui.EdgeSwipeInterceptorViewListener;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Vibrator;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.inputmethod.InputMethodManager;
+
+/**
+ * Class for initiating a drag within a view or across multiple views.
+ */
+public class DragController {
+	private static final double EDGE_SWIPE_SWIPE_SPEED_LIMIT = 1.5;
+
+	private static final String TAG = "Launcher.DragController";
+
+	// Two states, the normal where the drag controller works as intended by
+	// google,
+	// the menu show where it shows the menu and does not scrolling
+	private static enum MovementState {
+		NORMAL, MENU_SHOW
+	};
+
+	/** Indicates the drag is a move. */
+	public static int DRAG_ACTION_MOVE = 0;
+
+	/** Indicates the drag is a copy. */
+	public static int DRAG_ACTION_COPY = 1;
+
+	private static final int SCROLL_DELAY = 500;
+	private static final int RESCROLL_DELAY = 750;
+	private static final int VIBRATE_DURATION = 15;
+
+	private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
+
+	private static final int SCROLL_OUTSIDE_ZONE = 0;
+	private static final int SCROLL_WAITING_IN_ZONE = 1;
+
+	static final int SCROLL_NONE = -1;
+	static final int SCROLL_LEFT = 0;
+	static final int SCROLL_RIGHT = 1;
+
+	private static final float MAX_FLING_DEGREES = 35f;
+
+	private Launcher mLauncher;
+	private Handler mHandler;
+	private final Vibrator mVibrator;
+
+	// temporaries to avoid gc thrash
+	private Rect mRectTemp = new Rect();
+	private final int[] mCoordinatesTemp = new int[2];
+
+	/** Whether or not we're dragging. */
+	private boolean mDragging = false;
+
+	/** X coordinate of the down event. */
+	private int mMotionDownX;
+
+	/** Y coordinate of the down event. */
+	private int mMotionDownY;
+
+	/**
+	 * the area at the edge of the screen that makes the workspace go left or
+	 * right while you're dragging.
+	 */
+	private int mScrollZone;
+
+	private DropTarget.DragObject mDragObject;
+
+	/** Who can receive drop events */
+	private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
+	private ArrayList<DragListener> mListeners = new ArrayList<DragListener>();
+	private DropTarget mFlingToDeleteDropTarget;
+
+	/** The window token used as the parent for the DragView. */
+	private IBinder mWindowToken;
+
+	/**
+	 * The view that will be scrolled when dragging to the left and right edges
+	 * of the screen.
+	 */
+	private View mScrollView;
+
+	private View mMoveTarget;
+
+	private DragScroller mDragScroller;
+	private int mScrollState = SCROLL_OUTSIDE_ZONE;
+	private ScrollRunnable mScrollRunnable = new ScrollRunnable();
+
+	private DropTarget mLastDropTarget;
+
+	private InputMethodManager mInputMethodManager;
+
+	private int mLastTouch[] = new int[2];
+	private long mLastTouchUpTime = -1;
+	private int mDistanceSinceScroll = 0;
+
+	private int mTmpPoint[] = new int[2];
+	private Rect mDragLayerRect = new Rect();
+
+	protected int mFlingToDeleteThresholdVelocity;
+	private VelocityTracker mVelocityTracker;
+
+	// Fairphone start menu
+	protected EdgeSwipeInterceptorViewListener mEdgeListerner;
+
+	// the state regarding the menu
+	protected MovementState mCurrentState;
+
+	// edge swipe limits
+	protected int mUpEdgeSwipePixelLimits;
+	protected int mDownEdgeSwipePixelLimits;
+	protected int mEdgeSwipePixelEdgeLimit;
+
+	//
+
+	/**
+	 * Interface to receive notifications when a drag starts or stops
+	 */
+	interface DragListener {
+
+		/**
+		 * A drag has begun
+		 * 
+		 * @param source
+		 *            An object representing where the drag originated
+		 * @param info
+		 *            The data associated with the object that is being dragged
+		 * @param dragAction
+		 *            The drag action: either
+		 *            {@link DragController#DRAG_ACTION_MOVE} or
+		 *            {@link DragController#DRAG_ACTION_COPY}
+		 */
+		void onDragStart(DragSource source, Object info, int dragAction);
+
+		/**
+		 * The drag has ended
+		 */
+		void onDragEnd();
+	}
+
+	/**
+	 * Used to create a new DragLayer from XML.
+	 * 
+	 * @param context
+	 *            The application's context.
+	 */
+	public DragController(Launcher launcher) {
+		// this is the normal state
+		mCurrentState = MovementState.NORMAL;
+
+		Resources r = launcher.getResources();
+		mLauncher = launcher;
+		mHandler = new Handler();
+		mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone); // the area
+																	// at the
+																	// edge of
+																	// the
+																	// screen
+																	// that
+																	// makes the
+																	// workspace
+																	// go left
+																	// or right
+																	// while
+																	// you're
+																	// dragging.
+		// Helper for tracking the velocity of touch events, for implementing
+		// flinging and other such gestures.
+		// http://developer.android.com/reference/android/view/VelocityTracker.html
+		mVelocityTracker = VelocityTracker.obtain();
+		mVibrator = (Vibrator) launcher
+				.getSystemService(Context.VIBRATOR_SERVICE);
+
+		mUpEdgeSwipePixelLimits = 0;//r.getDimensionPixelSize(R.dimen.edge_swipe_up_limit);
+		mDownEdgeSwipePixelLimits = 0;//r.getDimensionPixelSize(R.dimen.edge_swipe_down_limit);
+		mEdgeSwipePixelEdgeLimit = r
+				.getDimensionPixelSize(R.dimen.edge_swipe_show_limit);
+
+		float density = r.getDisplayMetrics().density;
+		mFlingToDeleteThresholdVelocity = (int) (r
+				.getInteger(R.integer.config_flingToDeleteMinVelocity) * density);
+
+		mEdgeListerner = launcher.getEdgeSwipeListener();
+
+	}
+
+	private ArrayList<EdgeSwipeInterceptorViewListener> mEdgeSwipeListeners = new ArrayList<EdgeSwipeInterceptorViewListener>();
+
+	public void addOnSelectionListener(EdgeSwipeInterceptorViewListener listener) {
+		mEdgeSwipeListeners.add(listener);
+	}
+
+	public void removeOnSelectionListener(
+			EdgeSwipeInterceptorViewListener listener) {
+		mEdgeSwipeListeners.remove(listener);
+	}
+
+	private void startMenuSelection(MotionEvent ev) {
+		for (EdgeSwipeInterceptorViewListener listener : mEdgeSwipeListeners) {
+			listener.onSelectionStarted(ev.getX(), ev.getY());
+		}
+	}
+
+	private void updateMenuSelection(MotionEvent ev) {
+		for (EdgeSwipeInterceptorViewListener listener : mEdgeSwipeListeners) {
+			listener.onSelectionUpdate(ev.getX(), ev.getY());
+		}
+	}
+
+	private void stopMenuSelection(MotionEvent ev) {
+		for (EdgeSwipeInterceptorViewListener listener : mEdgeSwipeListeners) {
+			listener.onSelectionFinished(ev.getX(), ev.getY());
+		}
+
+		mCurrentState = MovementState.NORMAL;
+	}
+
+	public boolean dragging() {
+		return mDragging;
+	}
+
+	/**
+	 * Starts a drag.
+	 * 
+	 * @param v
+	 *            The view that is being dragged
+	 * @param bmp
+	 *            The bitmap that represents the view being dragged
+	 * @param source
+	 *            An object representing where the drag originated
+	 * @param dragInfo
+	 *            The data associated with the object that is being dragged
+	 * @param dragAction
+	 *            The drag action: either {@link #DRAG_ACTION_MOVE} or
+	 *            {@link #DRAG_ACTION_COPY}
+	 * @param dragRegion
+	 *            Coordinates within the bitmap b for the position of item being
+	 *            dragged. Makes dragging feel more precise, e.g. you can clip
+	 *            out a transparent border
+	 */
+	public void startDrag(View v, Bitmap bmp, DragSource source,
+			Object dragInfo, int dragAction, Rect dragRegion,
+			float initialDragViewScale) {
+		int[] loc = mCoordinatesTemp;
+		mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
+		int dragLayerX = loc[0]
+				+ v.getPaddingLeft()
+				+ (int) ((initialDragViewScale * bmp.getWidth() - bmp
+						.getWidth()) / 2);
+		int dragLayerY = loc[1]
+				+ v.getPaddingTop()
+				+ (int) ((initialDragViewScale * bmp.getHeight() - bmp
+						.getHeight()) / 2);
+
+		startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction,
+				null, dragRegion, initialDragViewScale);
+
+		if (dragAction == DRAG_ACTION_MOVE) {
+			v.setVisibility(View.GONE);
+		}
+	}
+
+	/**
+	 * Starts a drag.
+	 * 
+	 * @param b
+	 *            The bitmap to display as the drag image. It will be re-scaled
+	 *            to the enlarged size.
+	 * @param dragLayerX
+	 *            The x position in the DragLayer of the left-top of the bitmap.
+	 * @param dragLayerY
+	 *            The y position in the DragLayer of the left-top of the bitmap.
+	 * @param source
+	 *            An object representing where the drag originated
+	 * @param dragInfo
+	 *            The data associated with the object that is being dragged
+	 * @param dragAction
+	 *            The drag action: either {@link #DRAG_ACTION_MOVE} or
+	 *            {@link #DRAG_ACTION_COPY}
+	 * @param dragRegion
+	 *            Coordinates within the bitmap b for the position of item being
+	 *            dragged. Makes dragging feel more precise, e.g. you can clip
+	 *            out a transparent border
+	 */
+	public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
+			DragSource source, Object dragInfo, int dragAction,
+			Point dragOffset, Rect dragRegion, float initialDragViewScale) {
+		if (PROFILE_DRAWING_DURING_DRAG) {
+			android.os.Debug.startMethodTracing("Launcher");
+		}
+
+		// Hide soft keyboard, if visible
+		if (mInputMethodManager == null) {
+			mInputMethodManager = (InputMethodManager) mLauncher
+					.getSystemService(Context.INPUT_METHOD_SERVICE);
+		}
+		mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
+
+		for (DragListener listener : mListeners) {
+			listener.onDragStart(source, dragInfo, dragAction);
+		}
+
+		final int registrationX = mMotionDownX - dragLayerX;
+		final int registrationY = mMotionDownY - dragLayerY;
+
+		final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
+		final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
+
+		mDragging = true;
+
+		mDragObject = new DropTarget.DragObject();
+
+		mDragObject.dragComplete = false;
+		mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
+		mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
+		mDragObject.dragSource = source;
+		mDragObject.dragInfo = dragInfo;
+
+		mVibrator.vibrate(VIBRATE_DURATION);
+
+		final DragView dragView = mDragObject.dragView = new DragView(
+				mLauncher, b, registrationX, registrationY, 0, 0, b.getWidth(),
+				b.getHeight(), initialDragViewScale);
+
+		if (dragOffset != null) {
+			dragView.setDragVisualizeOffset(new Point(dragOffset));
+		}
+		if (dragRegion != null) {
+			dragView.setDragRegion(new Rect(dragRegion));
+		}
+
+		dragView.show(mMotionDownX, mMotionDownY);
+		handleMoveEvent(mMotionDownX, mMotionDownY);
+	}
+
+	/**
+	 * Draw the view into a bitmap.
+	 */
+	Bitmap getViewBitmap(View v) {
+		v.clearFocus();
+		v.setPressed(false);
+
+		boolean willNotCache = v.willNotCacheDrawing();
+		v.setWillNotCacheDrawing(false);
+
+		// Reset the drawing cache background color to fully transparent
+		// for the duration of this operation
+		int color = v.getDrawingCacheBackgroundColor();
+		v.setDrawingCacheBackgroundColor(0);
+		float alpha = v.getAlpha();
+		v.setAlpha(1.0f);
+
+		if (color != 0) {
+			v.destroyDrawingCache();
+		}
+		v.buildDrawingCache();
+		Bitmap cacheBitmap = v.getDrawingCache();
+		if (cacheBitmap == null) {
+			Log.e(TAG, "failed getViewBitmap(" + v + ")",
+					new RuntimeException());
+			return null;
+		}
+
+		Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
+
+		// Restore the view
+		v.destroyDrawingCache();
+		v.setAlpha(alpha);
+		v.setWillNotCacheDrawing(willNotCache);
+		v.setDrawingCacheBackgroundColor(color);
+
+		return bitmap;
+	}
+
+	/**
+	 * Call this from a drag source view like this:
+	 * 
+	 * <pre>
+	 *  @Override
+	 *  public boolean dispatchKeyEvent(KeyEvent event) {
+	 *      return mDragController.dispatchKeyEvent(this, event)
+	 *              || super.dispatchKeyEvent(event);
+	 * </pre>
+	 */
+	public boolean dispatchKeyEvent(KeyEvent event) {
+		return mDragging;
+	}
+
+	public boolean isDragging() {
+		return mDragging;
+	}
+
+	/**
+	 * Stop dragging without dropping.
+	 */
+	public void cancelDrag() {
+		if (mDragging) {
+			if (mLastDropTarget != null) {
+				mLastDropTarget.onDragExit(mDragObject);
+			}
+			if (mDragObject != null) {
+				mDragObject.deferDragViewCleanupPostAnimation = false;
+				mDragObject.cancelled = true;
+				mDragObject.dragComplete = true;
+				mDragObject.dragSource.onDropCompleted(null, mDragObject,
+						false, false);
+			}
+		}
+		endDrag();
+	}
+
+	public void onAppsRemoved(ArrayList<String> packageNames, Context context) {
+		// Cancel the current drag if we are removing an app that we are
+		// dragging
+		if (mDragObject != null) {
+			Object rawDragInfo = mDragObject.dragInfo;
+			if (rawDragInfo instanceof ShortcutInfo) {
+				ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
+				for (String pn : packageNames) {
+					// Added null checks to prevent NPE we've seen in the wild
+					if (dragInfo != null && dragInfo.intent != null) {
+						boolean isSamePackage = dragInfo.getPackageName()
+								.equals(pn);
+						if (isSamePackage) {
+							cancelDrag();
+							return;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private void endDrag() {
+		if (mDragging) {
+			mDragging = false;
+			clearScrollRunnable();
+			boolean isDeferred = false;
+			if (mDragObject != null && mDragObject.dragView != null) {
+				isDeferred = mDragObject.deferDragViewCleanupPostAnimation;
+				if (!isDeferred) {
+					mDragObject.dragView.remove();
+				}
+				mDragObject.dragView = null;
+			}
+
+			// Only end the drag if we are not deferred
+			if (!isDeferred) {
+				for (DragListener listener : mListeners) {
+					listener.onDragEnd();
+				}
+			}
+		}
+
+		releaseVelocityTracker();
+	}
+
+	/**
+	 * This only gets called as a result of drag view cleanup being deferred in
+	 * endDrag();
+	 */
+	void onDeferredEndDrag(DragView dragView) {
+		dragView.remove();
+
+		// If we skipped calling onDragEnd() before, do it now
+		for (DragListener listener : mListeners) {
+			listener.onDragEnd();
+		}
+	}
+
+	void onDeferredEndFling(DropTarget.DragObject d) {
+		d.dragSource.onFlingToDeleteCompleted();
+	}
+
+	/**
+	 * Clamps the position to the drag layer bounds.
+	 */
+	private int[] getClampedDragLayerPos(float x, float y) {
+		mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect);
+		mTmpPoint[0] = (int) Math.max(mDragLayerRect.left,
+				Math.min(x, mDragLayerRect.right - 1));
+		mTmpPoint[1] = (int) Math.max(mDragLayerRect.top,
+				Math.min(y, mDragLayerRect.bottom - 1));
+		return mTmpPoint;
+	}
+
+	long getLastGestureUpTime() {
+		if (mDragging) {
+			return System.currentTimeMillis();
+		} else {
+			return mLastTouchUpTime;
+		}
+	}
+
+	void resetLastGestureUpTime() {
+		mLastTouchUpTime = -1;
+	}
+
+	int count = 0;
+	int limit = 20;
+	int pointerId;
+
+	boolean canShowMenuInThisMovement = true;
+	boolean startMenu = false;
+
+	/**
+	 * Call this from a drag source view.
+	 */
+	public boolean onInterceptTouchEvent(MotionEvent ev) {
+
+		@SuppressWarnings("all")
+		// suppress dead code warning
+		final boolean debug = false;
+		if (debug) {
+			Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev
+					+ " mDragging=" + mDragging);
+		}
+
+		// Update the velocity tracker
+		acquireVelocityTrackerAndAddMovement(ev);
+
+		// verify the edgeswipe menu
+		calculateShowMenuInThisMovement(ev);
+
+		final int action = ev.getAction();
+		final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
+		final int dragLayerX = dragLayerPos[0];
+		final int dragLayerY = dragLayerPos[1];
+
+		boolean returnDragging = false;
+
+		switch (action) {
+		case MotionEvent.ACTION_MOVE:
+			if (mCurrentState == MovementState.MENU_SHOW) {
+				returnDragging = true;
+				updateMenuSelection(ev);
+
+				pointerId = ev.getPointerId(ev.getActionIndex());
+			}
+			break;
+		case MotionEvent.ACTION_DOWN:
+			if (mCurrentState == MovementState.NORMAL) {
+				// Remember location of down touch
+				mMotionDownX = dragLayerX;
+				mMotionDownY = dragLayerY;
+				mLastDropTarget = null;
+			} else if (mCurrentState == MovementState.MENU_SHOW) {
+				returnDragging = true;
+				if (startMenu) {
+					startMenuSelection(ev);
+					startMenu = false;
+				}
+				pointerId = ev.getPointerId(ev.getActionIndex());
+			}
+			break;
+		case MotionEvent.ACTION_UP:
+			if (mCurrentState == MovementState.NORMAL) {
+				count = 0;
+
+				mLastTouchUpTime = System.currentTimeMillis();
+				if (mDragging) {
+					PointF vec = isFlingingToDelete(mDragObject.dragSource);
+					if (vec != null) {
+						dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
+					} else {
+						drop(dragLayerX, dragLayerY);
+					}
+				}
+				endDrag();
+			} else if (mCurrentState == MovementState.MENU_SHOW) {
+				stopMenuSelection(ev);
+
+				// mDragging = false;
+				returnDragging = false;
+				pointerId = ev.getPointerId(ev.getActionIndex());
+			}
+
+			mCurrentState = MovementState.NORMAL;
+			canShowMenuInThisMovement = true;
+
+			break;
+		case MotionEvent.ACTION_CANCEL:
+			if (mCurrentState == MovementState.NORMAL) {
+				cancelDrag();
+			} else {
+				stopMenuSelection(ev);
+				returnDragging = false;
+				pointerId = ev.getPointerId(ev.getActionIndex());
+			}
+
+			mCurrentState = MovementState.NORMAL;
+			canShowMenuInThisMovement = true;
+
+			break;
+		}
+
+		if (mCurrentState == MovementState.NORMAL) {
+			returnDragging = mDragging;
+		}
+
+		return returnDragging;
+	}
+
+	private void calculateShowMenuInThisMovement(MotionEvent ev) {
+		// ignore menu if dragging
+		if (isDragging()) {
+			canShowMenuInThisMovement = false;
+		}
+
+		// if from the edges and in limits
+		if (fromTheEdges(ev) && inEdgeSwipeLimits(ev)) {
+			mCurrentState = MovementState.MENU_SHOW;
+
+			startMenu = true;
+		}
+	}
+
+	private boolean fromTheEdges(MotionEvent ev) {
+
+		boolean isFromEdges = (ev.getX() < mEdgeSwipePixelEdgeLimit || ev
+				.getX() > mLauncher.getResources().getDisplayMetrics().widthPixels
+				- mEdgeSwipePixelEdgeLimit);
+
+		return isFromEdges;
+	}
+
+	private boolean inEdgeSwipeLimits(MotionEvent ev) {
+		return (ev.getY() > mUpEdgeSwipePixelLimits && ev.getY() < (mLauncher
+				.getResources().getDisplayMetrics().heightPixels - mDownEdgeSwipePixelLimits));
+	}
+
+	/**
+	 * Sets the view that should handle move events.
+	 */
+	void setMoveTarget(View view) {
+		mMoveTarget = view;
+	}
+
+	public boolean dispatchUnhandledMove(View focused, int direction) {
+		return mMoveTarget != null
+				&& mMoveTarget.dispatchUnhandledMove(focused, direction);
+	}
+
+	private void clearScrollRunnable() {
+		mHandler.removeCallbacks(mScrollRunnable);
+		if (mScrollState == SCROLL_WAITING_IN_ZONE) {
+			mScrollState = SCROLL_OUTSIDE_ZONE;
+			mScrollRunnable.setDirection(SCROLL_RIGHT);
+			mDragScroller.onExitScrollArea();
+			mLauncher.getDragLayer().onExitScrollArea();
+		}
+	}
+
+	private void handleMoveEvent(int x, int y) {
+		mDragObject.dragView.move(x, y);
+
+		// Drop on someone?
+		final int[] coordinates = mCoordinatesTemp;
+		DropTarget dropTarget = findDropTarget(x, y, coordinates);
+		mDragObject.x = coordinates[0];
+		mDragObject.y = coordinates[1];
+		if (dropTarget != null) {
+			DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
+			if (delegate != null) {
+				dropTarget = delegate;
+			}
+
+			if (mLastDropTarget != dropTarget) {
+				if (mLastDropTarget != null) {
+					mLastDropTarget.onDragExit(mDragObject);
+				}
+				dropTarget.onDragEnter(mDragObject);
+			}
+			dropTarget.onDragOver(mDragObject);
+		} else {
+			if (mLastDropTarget != null) {
+				mLastDropTarget.onDragExit(mDragObject);
+			}
+		}
+		mLastDropTarget = dropTarget;
+
+		// After a scroll, the touch point will still be in the scroll region.
+		// Rather than scrolling immediately, require a bit of twiddling to
+		// scroll again
+		final int slop = ViewConfiguration.get(mLauncher)
+				.getScaledWindowTouchSlop();
+		mDistanceSinceScroll += Math.sqrt(Math.pow(mLastTouch[0] - x, 2)
+				+ Math.pow(mLastTouch[1] - y, 2));
+		mLastTouch[0] = x;
+		mLastTouch[1] = y;
+		final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY
+				: SCROLL_DELAY;
+
+		if (x < mScrollZone) {
+			if (mScrollState == SCROLL_OUTSIDE_ZONE) {
+				mScrollState = SCROLL_WAITING_IN_ZONE;
+				if (mDragScroller.onEnterScrollArea(x, y, SCROLL_LEFT)) {
+					mLauncher.getDragLayer().onEnterScrollArea(SCROLL_LEFT);
+					mScrollRunnable.setDirection(SCROLL_LEFT);
+					mHandler.postDelayed(mScrollRunnable, delay);
+				}
+			}
+		} else if (x > mScrollView.getWidth() - mScrollZone) {
+			if (mScrollState == SCROLL_OUTSIDE_ZONE) {
+				mScrollState = SCROLL_WAITING_IN_ZONE;
+				if (mDragScroller.onEnterScrollArea(x, y, SCROLL_RIGHT)) {
+					mLauncher.getDragLayer().onEnterScrollArea(SCROLL_RIGHT);
+					mScrollRunnable.setDirection(SCROLL_RIGHT);
+					mHandler.postDelayed(mScrollRunnable, delay);
+				}
+			}
+		} else {
+			clearScrollRunnable();
+		}
+	}
+
+	public void forceMoveEvent() {
+		if (mDragging) {
+			handleMoveEvent(mDragObject.x, mDragObject.y);
+		}
+	}
+
+	/**
+	 * Call this from a drag source view.
+	 */
+	public boolean onTouchEvent(MotionEvent ev) {
+
+		if (!mDragging && mCurrentState == MovementState.NORMAL) {
+			return false;
+		}
+
+		// Update the velocity tracker
+		acquireVelocityTrackerAndAddMovement(ev);
+
+		final int action = ev.getAction();
+		final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
+		final int dragLayerX = dragLayerPos[0];
+		final int dragLayerY = dragLayerPos[1];
+
+		switch (action) {
+		case MotionEvent.ACTION_DOWN:
+			if (mCurrentState == MovementState.NORMAL) {
+				// Remember where the motion event started
+				mMotionDownX = dragLayerX;
+				mMotionDownY = dragLayerY;
+
+				if ((dragLayerX < mScrollZone)
+						|| (dragLayerX > mScrollView.getWidth() - mScrollZone)) {
+					mScrollState = SCROLL_WAITING_IN_ZONE;
+					mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
+				} else {
+					mScrollState = SCROLL_OUTSIDE_ZONE;
+				}
+			}
+			break;
+		case MotionEvent.ACTION_MOVE:
+			if (mCurrentState == MovementState.NORMAL) {
+				handleMoveEvent(dragLayerX, dragLayerY);
+			} else {
+				updateMenuSelection(ev);
+			}
+			break;
+		case MotionEvent.ACTION_UP:
+			// Ensure that we've processed a move event at the current pointer
+			// location.
+
+			if (mCurrentState == MovementState.NORMAL) {
+				handleMoveEvent(dragLayerX, dragLayerY);
+				mHandler.removeCallbacks(mScrollRunnable);
+
+				if (mDragging) {
+					PointF vec = isFlingingToDelete(mDragObject.dragSource);
+					if (vec != null) {
+						dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
+					} else {
+						drop(dragLayerX, dragLayerY);
+					}
+				}
+				endDrag();
+			} else {
+				stopMenuSelection(ev);
+			}
+
+			mCurrentState = MovementState.NORMAL;
+			canShowMenuInThisMovement = true;
+
+			break;
+		case MotionEvent.ACTION_CANCEL:
+			if (mCurrentState == MovementState.NORMAL) {
+				mHandler.removeCallbacks(mScrollRunnable);
+				cancelDrag();
+			} else {
+				stopMenuSelection(ev);
+			}
+
+			mCurrentState = MovementState.NORMAL;
+			canShowMenuInThisMovement = true;
+
+			break;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Determines whether the user flung the current item to delete it.
+	 * 
+	 * @return the vector at which the item was flung, or null if no fling was
+	 *         detected.
+	 */
+	private PointF isFlingingToDelete(DragSource source) {
+		if (mFlingToDeleteDropTarget == null)
+			return null;
+		if (!source.supportsFlingToDelete())
+			return null;
+
+		ViewConfiguration config = ViewConfiguration.get(mLauncher);
+		mVelocityTracker.computeCurrentVelocity(1000,
+				config.getScaledMaximumFlingVelocity());
+
+		if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
+			// Do a quick dot product test to ensure that we are flinging
+			// upwards
+			PointF vel = new PointF(mVelocityTracker.getXVelocity(),
+					mVelocityTracker.getYVelocity());
+			PointF upVec = new PointF(0f, -1f);
+			float theta = (float) Math
+					.acos(((vel.x * upVec.x) + (vel.y * upVec.y))
+							/ (vel.length() * upVec.length()));
+			if (theta <= Math.toRadians(MAX_FLING_DEGREES)) {
+				return vel;
+			}
+		}
+		return null;
+	}
+
+	private void dropOnFlingToDeleteTarget(float x, float y, PointF vel) {
+		final int[] coordinates = mCoordinatesTemp;
+
+		mDragObject.x = coordinates[0];
+		mDragObject.y = coordinates[1];
+
+		// Clean up dragging on the target if it's not the current fling delete
+		// target otherwise,
+		// start dragging to it.
+		if (mLastDropTarget != null
+				&& mFlingToDeleteDropTarget != mLastDropTarget) {
+			mLastDropTarget.onDragExit(mDragObject);
+		}
+
+		// Drop onto the fling-to-delete target
+		boolean accepted = false;
+		mFlingToDeleteDropTarget.onDragEnter(mDragObject);
+		// We must set dragComplete to true _only_ after we "enter" the
+		// fling-to-delete target for
+		// "drop"
+		mDragObject.dragComplete = true;
+		mFlingToDeleteDropTarget.onDragExit(mDragObject);
+		if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) {
+			mFlingToDeleteDropTarget.onFlingToDelete(mDragObject,
+					mDragObject.x, mDragObject.y, vel);
+			accepted = true;
+		}
+		mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget,
+				mDragObject, true, accepted);
+	}
+
+	private void drop(float x, float y) {
+		final int[] coordinates = mCoordinatesTemp;
+		final DropTarget dropTarget = findDropTarget((int) x, (int) y,
+				coordinates);
+
+		mDragObject.x = coordinates[0];
+		mDragObject.y = coordinates[1];
+		boolean accepted = false;
+		if (dropTarget != null) {
+			mDragObject.dragComplete = true;
+			dropTarget.onDragExit(mDragObject);
+			if (dropTarget.acceptDrop(mDragObject)) {
+				dropTarget.onDrop(mDragObject);
+				accepted = true;
+			}
+		}
+		mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject,
+				false, accepted);
+	}
+
+	private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
+		final Rect r = mRectTemp;
+
+		final ArrayList<DropTarget> dropTargets = mDropTargets;
+		final int count = dropTargets.size();
+		for (int i = count - 1; i >= 0; i--) {
+			DropTarget target = dropTargets.get(i);
+			if (!target.isDropEnabled())
+				continue;
+
+			target.getHitRect(r);
+
+			// Convert the hit rect to DragLayer coordinates
+			target.getLocationInDragLayer(dropCoordinates);
+			r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1]
+					- target.getTop());
+
+			mDragObject.x = x;
+			mDragObject.y = y;
+			if (r.contains(x, y)) {
+				DropTarget delegate = target.getDropTargetDelegate(mDragObject);
+				if (delegate != null) {
+					target = delegate;
+					target.getLocationInDragLayer(dropCoordinates);
+				}
+
+				// Make dropCoordinates relative to the DropTarget
+				dropCoordinates[0] = x - dropCoordinates[0];
+				dropCoordinates[1] = y - dropCoordinates[1];
+
+				return target;
+			}
+		}
+		return null;
+	}
+
+	public void setDragScoller(DragScroller scroller) {
+		mDragScroller = scroller;
+	}
+
+	public void setWindowToken(IBinder token) {
+		mWindowToken = token;
+	}
+
+	/**
+	 * Sets the drag listner which will be notified when a drag starts or ends.
+	 */
+	public void addDragListener(DragListener l) {
+		mListeners.add(l);
+	}
+
+	/**
+	 * Remove a previously installed drag listener.
+	 */
+	public void removeDragListener(DragListener l) {
+		mListeners.remove(l);
+	}
+
+	/**
+	 * Add a DropTarget to the list of potential places to receive drop events.
+	 */
+	public void addDropTarget(DropTarget target) {
+		mDropTargets.add(target);
+	}
+
+	/**
+	 * Don't send drop events to <em>target</em> any more.
+	 */
+	public void removeDropTarget(DropTarget target) {
+		mDropTargets.remove(target);
+	}
+
+	/**
+	 * Sets the current fling-to-delete drop target.
+	 */
+	public void setFlingToDeleteDropTarget(DropTarget target) {
+		mFlingToDeleteDropTarget = target;
+	}
+
+	private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
+		if (mVelocityTracker == null) {
+			mVelocityTracker = VelocityTracker.obtain();
+		}
+		mVelocityTracker.addMovement(ev);
+
+		mVelocityTracker.computeCurrentVelocity(1, 100);
+	}
+
+	private void releaseVelocityTracker() {
+		if (mVelocityTracker != null) {
+			mVelocityTracker.recycle();
+			mVelocityTracker = null;
+		}
+	}
+
+	/**
+	 * Set which view scrolls for touch events near the edge of the screen.
+	 */
+	public void setScrollView(View v) {
+		mScrollView = v;
+	}
+
+	DragView getDragView() {
+		return mDragObject.dragView;
+	}
+
+	private class ScrollRunnable implements Runnable {
+		private int mDirection;
+
+		ScrollRunnable() {
+		}
+
+		public void run() {
+			if (mDragScroller != null) {
+				if (mDirection == SCROLL_LEFT) {
+					mDragScroller.scrollLeft();
+				} else {
+					mDragScroller.scrollRight();
+				}
+				mScrollState = SCROLL_OUTSIDE_ZONE;
+				mDistanceSinceScroll = 0;
+				mDragScroller.onExitScrollArea();
+				mLauncher.getDragLayer().onExitScrollArea();
+
+				if (isDragging()) {
+					// Force an update so that we can requeue the scroller if
+					// necessary
+					forceMoveEvent();
+				}
+			}
+		}
+
+		void setDirection(int direction) {
+			mDirection = direction;
+		}
+	}
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DragLayer.java b/FairphoneHome/src/org/fairphone/launcher/DragLayer.java
new file mode 100644
index 0000000..5a28dc7
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DragLayer.java
@@ -0,0 +1,773 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+
+/**
+ * A ViewGroup that coordinates dragging across its descendants
+ */
+public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
+    private DragController mDragController;
+    private int[] mTmpXY = new int[2];
+
+    private int mXDown, mYDown;
+    private Launcher mLauncher;
+
+    // Variables relating to resizing widgets
+    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
+            new ArrayList<AppWidgetResizeFrame>();
+    private AppWidgetResizeFrame mCurrentResizeFrame;
+
+    // Variables relating to animation of views after drop
+    private ValueAnimator mDropAnim = null;
+    private ValueAnimator mFadeOutAnim = null;
+    private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
+    private DragView mDropView = null;
+    private int mAnchorViewInitialScrollX = 0;
+    private View mAnchorView = null;
+
+    private boolean mHoverPointClosesFolder = false;
+    private Rect mHitRect = new Rect();
+    private int mWorkspaceIndex = -1;
+    private int mQsbIndex = -1;
+    public static final int ANIMATION_END_DISAPPEAR = 0;
+    public static final int ANIMATION_END_FADE_OUT = 1;
+    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
+	private static final String TAG = null;
+
+    /**
+     * Used to create a new DragLayer from XML.
+     *
+     * @param context The application's context.
+     * @param attrs The attributes set containing the Workspace's customization values.
+     */
+    public DragLayer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        // Disable multitouch across the workspace/all apps/customize tray
+        setMotionEventSplittingEnabled(false);
+        setChildrenDrawingOrderEnabled(true);
+        setOnHierarchyChangeListener(this);
+
+        mLeftHoverDrawable = getResources().getDrawable(R.drawable.page_hover_left_holo);
+        mRightHoverDrawable = getResources().getDrawable(R.drawable.page_hover_right_holo);
+    }
+
+    public void setup(Launcher launcher, DragController controller) {
+        mLauncher = launcher;
+        mDragController = controller;
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
+    }
+
+    private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
+        getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
+        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
+        getDescendantRectRelativeToSelf(folder, mHitRect);
+        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
+        Rect hitRect = new Rect();
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        for (AppWidgetResizeFrame child: mResizeFrames) {
+            child.getHitRect(hitRect);
+            if (hitRect.contains(x, y)) {
+                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
+                    mCurrentResizeFrame = child;
+                    mXDown = x;
+                    mYDown = y;
+                    requestDisallowInterceptTouchEvent(true);
+                    return true;
+                }
+            }
+        }
+
+        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
+        if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
+            if (currentFolder.isEditingName()) {
+                if (!isEventOverFolderTextRegion(currentFolder, ev)) {
+                    currentFolder.dismissEditingName();
+                    return true;
+                }
+            }
+
+            getDescendantRectRelativeToSelf(currentFolder, hitRect);
+            if (!isEventOverFolder(currentFolder, ev)) {
+                mLauncher.closeFolder();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (handleTouchDown(ev, true)) {
+                return true;
+            }
+        }
+        clearAllResizeFrames();
+        return mDragController.onInterceptTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onInterceptHoverEvent(MotionEvent ev) {
+        if (mLauncher == null || mLauncher.getWorkspace() == null) {
+            return false;
+        }
+        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
+        if (currentFolder == null) {
+            return false;
+        } else {
+                AccessibilityManager accessibilityManager = (AccessibilityManager)
+                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+            if (accessibilityManager.isTouchExplorationEnabled()) {
+                final int action = ev.getAction();
+                boolean isOverFolder;
+                switch (action) {
+                    case MotionEvent.ACTION_HOVER_ENTER:
+                        isOverFolder = isEventOverFolder(currentFolder, ev);
+                        if (!isOverFolder) {
+                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
+                            mHoverPointClosesFolder = true;
+                            return true;
+                        } else if (isOverFolder) {
+                            mHoverPointClosesFolder = false;
+                        } else {
+                            return true;
+                        }
+                    case MotionEvent.ACTION_HOVER_MOVE:
+                        isOverFolder = isEventOverFolder(currentFolder, ev);
+                        if (!isOverFolder && !mHoverPointClosesFolder) {
+                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
+                            mHoverPointClosesFolder = true;
+                            return true;
+                        } else if (isOverFolder) {
+                            mHoverPointClosesFolder = false;
+                        } else {
+                            return true;
+                        }
+                }
+            }
+        }
+        return false;
+    }
+
+    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
+        AccessibilityManager accessibilityManager = (AccessibilityManager)
+                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (accessibilityManager.isEnabled()) {
+            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
+            AccessibilityEvent event = AccessibilityEvent.obtain(
+                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
+            onInitializeAccessibilityEvent(event);
+            event.getText().add(getContext().getString(stringId));
+            accessibilityManager.sendAccessibilityEvent(event);
+        }
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent ev) {
+        // If we've received this, we've already done the necessary handling
+        // in onInterceptHoverEvent. Return true to consume the event.
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        boolean handled = false;
+        int action = ev.getAction();
+
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                if (handleTouchDown(ev, false)) {
+                    return true;
+                }
+            }
+        }
+
+        if (mCurrentResizeFrame != null) {
+            handled = true;
+            switch (action) {
+                case MotionEvent.ACTION_MOVE:
+                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                case MotionEvent.ACTION_UP:
+                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
+                    mCurrentResizeFrame.onTouchUp();
+                    mCurrentResizeFrame = null;
+            }
+        }
+        if (handled) return true;
+        return mDragController.onTouchEvent(ev);
+    }
+
+    /**
+     * Determine the rect of the descendant in this DragLayer's coordinates
+     *
+     * @param descendant The descendant whose coordinates we want to find.
+     * @param r The rect into which to place the results.
+     * @return The factor by which this descendant is scaled relative to this DragLayer.
+     */
+    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
+        mTmpXY[0] = 0;
+        mTmpXY[1] = 0;
+        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
+        r.set(mTmpXY[0], mTmpXY[1],
+                mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight());
+        return scale;
+    }
+
+    public float getLocationInDragLayer(View child, int[] loc) {
+        loc[0] = 0;
+        loc[1] = 0;
+        return getDescendantCoordRelativeToSelf(child, loc);
+    }
+
+    /**
+     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
+     * coordinates.
+     *
+     * @param descendant The descendant to which the passed coordinate is relative.
+     * @param coord The coordinate that we want mapped.
+     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
+     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
+     *         assumption fails, we will need to return a pair of scale factors.
+     */
+    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
+        float scale = 1.0f;
+        float[] pt = {coord[0], coord[1]};
+        descendant.getMatrix().mapPoints(pt);
+        scale *= descendant.getScaleX();
+        pt[0] += descendant.getLeft();
+        pt[1] += descendant.getTop();
+        ViewParent viewParent = descendant.getParent();
+        while (viewParent instanceof View && viewParent != this) {
+            final View view = (View)viewParent;
+            view.getMatrix().mapPoints(pt);
+            scale *= view.getScaleX();
+            pt[0] += view.getLeft() - view.getScrollX();
+            pt[1] += view.getTop() - view.getScrollY();
+            viewParent = view.getParent();
+        }
+        coord[0] = (int) Math.round(pt[0]);
+        coord[1] = (int) Math.round(pt[1]);
+        return scale;
+    }
+
+    public void getViewRectRelativeToSelf(View v, Rect r) {
+        int[] loc = new int[2];
+        getLocationInWindow(loc);
+        int x = loc[0];
+        int y = loc[1];
+
+        v.getLocationInWindow(loc);
+        int vX = loc[0];
+        int vY = loc[1];
+
+        int left = vX - x;
+        int top = vY - y;
+        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
+    }
+
+    @Override
+    public boolean dispatchUnhandledMove(View focused, int direction) {
+        return mDragController.dispatchUnhandledMove(focused, direction);
+    }
+
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+        public int x, y;
+        public boolean customPosition = false;
+
+        /**
+         * {@inheritDoc}
+         */
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public void setWidth(int width) {
+            this.width = width;
+        }
+
+        public int getWidth() {
+            return width;
+        }
+
+        public void setHeight(int height) {
+            this.height = height;
+        }
+
+        public int getHeight() {
+            return height;
+        }
+
+        public void setX(int x) {
+            this.x = x;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public void setY(int y) {
+            this.y = y;
+        }
+
+        public int getY() {
+            return y;
+        }
+    }
+
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
+            if (flp instanceof LayoutParams) {
+                final LayoutParams lp = (LayoutParams) flp;
+                if (lp.customPosition) {
+                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
+                }
+            }
+        }
+    }
+
+    public void clearAllResizeFrames() {
+        if (mResizeFrames.size() > 0) {
+            for (AppWidgetResizeFrame frame: mResizeFrames) {
+                frame.commitResize();
+                removeView(frame);
+            }
+            mResizeFrames.clear();
+        }
+    }
+
+    public boolean hasResizeFrames() {
+        return mResizeFrames.size() > 0;
+    }
+
+    public boolean isWidgetBeingResized() {
+        return mCurrentResizeFrame != null;
+    }
+
+    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
+            CellLayout cellLayout) {
+        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
+                widget, cellLayout, this);
+
+        LayoutParams lp = new LayoutParams(-1, -1);
+        lp.customPosition = true;
+
+        addView(resizeFrame, lp);
+        mResizeFrames.add(resizeFrame);
+
+        resizeFrame.snapToWidget(false);
+    }
+
+    public void animateViewIntoPosition(DragView dragView, final View child) {
+        animateViewIntoPosition(dragView, child, null);
+    }
+
+    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
+            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
+            int duration) {
+        Rect r = new Rect();
+        getViewRectRelativeToSelf(dragView, r);
+        final int fromX = r.left;
+        final int fromY = r.top;
+
+        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
+                onFinishRunnable, animationEndStyle, duration, null);
+    }
+
+    public void animateViewIntoPosition(DragView dragView, final View child,
+            final Runnable onFinishAnimationRunnable) {
+        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
+    }
+
+    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
+            final Runnable onFinishAnimationRunnable, View anchorView) {
+        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
+        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
+        parentChildren.measureChild(child);
+
+        Rect r = new Rect();
+        getViewRectRelativeToSelf(dragView, r);
+
+        int coord[] = new int[2];
+        float childScale = child.getScaleX();
+        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
+        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
+
+        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
+        // the correct coordinates (above) and use these to determine the final location
+        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
+        // We need to account for the scale of the child itself, as the above only accounts for
+        // for the scale in parents.
+        scale *= childScale;
+        int toX = coord[0];
+        int toY = coord[1];
+        if (child instanceof TextView) {
+            TextView tv = (TextView) child;
+
+            // The child may be scaled (always about the center of the view) so to account for it,
+            // we have to offset the position by the scaled size.  Once we do that, we can center
+            // the drag view about the scaled child view.
+            toY += Math.round(scale * tv.getPaddingTop());
+            toY -= dragView.getMeasuredHeight() * (1 - scale) / 2;
+            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
+        } else if (child instanceof FolderIcon) {
+            // Account for holographic blur padding on the drag view
+            toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2;
+            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
+            // Center in the x coordinate about the target's drawable
+            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
+        } else {
+            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
+            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
+                    - child.getMeasuredWidth()))) / 2;
+        }
+
+        final int fromX = r.left;
+        final int fromY = r.top;
+        child.setVisibility(INVISIBLE);
+        Runnable onCompleteRunnable = new Runnable() {
+            public void run() {
+                child.setVisibility(VISIBLE);
+                if (onFinishAnimationRunnable != null) {
+                    onFinishAnimationRunnable.run();
+                }
+            }
+        };
+        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
+                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
+    }
+
+    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
+            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
+            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
+            int animationEndStyle, int duration, View anchorView) {
+        Rect from = new Rect(fromX, fromY, fromX +
+                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
+        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
+        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
+                null, null, onCompleteRunnable, animationEndStyle, anchorView);
+    }
+
+    /**
+     * This method animates a view at the end of a drag and drop animation.
+     *
+     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
+     *        doesn't need to be a child of DragLayer.
+     * @param from The initial location of the view. Only the left and top parameters are used.
+     * @param to The final location of the view. Only the left and top parameters are used. This
+     *        location doesn't account for scaling, and so should be centered about the desired
+     *        final location (including scaling).
+     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
+     * @param finalScale The final scale of the view. The view is scaled about its center.
+     * @param duration The duration of the animation.
+     * @param motionInterpolator The interpolator to use for the location of the view.
+     * @param alphaInterpolator The interpolator to use for the alpha of the view.
+     * @param onCompleteRunnable Optional runnable to run on animation completion.
+     * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
+     *        the runnable will execute after the view is faded out.
+     * @param anchorView If not null, this represents the view which the animated view stays
+     *        anchored to in case scrolling is currently taking place. Note: currently this is
+     *        only used for the X dimension for the case of the workspace.
+     */
+    public void animateView(final DragView view, final Rect from, final Rect to,
+            final float finalAlpha, final float initScaleX, final float initScaleY,
+            final float finalScaleX, final float finalScaleY, int duration,
+            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
+            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
+
+        // Calculate the duration of the animation based on the object's distance
+        final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
+                Math.pow(to.top - from.top, 2));
+        final Resources res = getResources();
+        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
+
+        // If duration < 0, this is a cue to compute the duration based on the distance
+        if (duration < 0) {
+            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
+            if (dist < maxDist) {
+                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
+            }
+            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
+        }
+
+        // Fall back to cubic ease out interpolator for the animation if none is specified
+        TimeInterpolator interpolator = null;
+        if (alphaInterpolator == null || motionInterpolator == null) {
+            interpolator = mCubicEaseOutInterpolator;
+        }
+
+        // Animate the view
+        final float initAlpha = view.getAlpha();
+        final float dropViewScale = view.getScaleX();
+        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float percent = (Float) animation.getAnimatedValue();
+                final int width = view.getMeasuredWidth();
+                final int height = view.getMeasuredHeight();
+
+                float alphaPercent = alphaInterpolator == null ? percent :
+                        alphaInterpolator.getInterpolation(percent);
+                float motionPercent = motionInterpolator == null ? percent :
+                        motionInterpolator.getInterpolation(percent);
+
+                float initialScaleX = initScaleX * dropViewScale;
+                float initialScaleY = initScaleY * dropViewScale;
+                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
+                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
+                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
+
+                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
+                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
+
+                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
+                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
+
+                int xPos = x - mDropView.getScrollX() + (mAnchorView != null
+                        ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
+                int yPos = y - mDropView.getScrollY();
+
+                mDropView.setTranslationX(xPos);
+                mDropView.setTranslationY(yPos);
+                mDropView.setScaleX(scaleX);
+                mDropView.setScaleY(scaleY);
+                mDropView.setAlpha(alpha);
+            }
+        };
+        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
+                anchorView);
+    }
+
+    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
+            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
+            final int animationEndStyle, View anchorView) {
+        // Clean up the previous animations
+        if (mDropAnim != null) mDropAnim.cancel();
+        if (mFadeOutAnim != null) mFadeOutAnim.cancel();
+
+        // Show the drop view if it was previously hidden
+        mDropView = view;
+        mDropView.cancelAnimation();
+        mDropView.resetLayoutParams();
+
+        // Set the anchor view if the page is scrolling
+        if (anchorView != null) {
+            mAnchorViewInitialScrollX = anchorView.getScrollX();
+        }
+        mAnchorView = anchorView;
+
+        // Create and start the animation
+        mDropAnim = new ValueAnimator();
+        mDropAnim.setInterpolator(interpolator);
+        mDropAnim.setDuration(duration);
+        mDropAnim.setFloatValues(0f, 1f);
+        mDropAnim.addUpdateListener(updateCb);
+        mDropAnim.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                if (onCompleteRunnable != null) {
+                    onCompleteRunnable.run();
+                }
+                switch (animationEndStyle) {
+                case ANIMATION_END_DISAPPEAR:
+                    clearAnimatedView();
+                    break;
+                case ANIMATION_END_FADE_OUT:
+                    fadeOutDragView();
+                    break;
+                case ANIMATION_END_REMAIN_VISIBLE:
+                    break;
+                }
+            }
+        });
+        mDropAnim.start();
+    }
+
+    public void clearAnimatedView() {
+        if (mDropAnim != null) {
+            mDropAnim.cancel();
+        }
+        if (mDropView != null) {
+            mDragController.onDeferredEndDrag(mDropView);
+        }
+        mDropView = null;
+        invalidate();
+    }
+
+    public View getAnimatedView() {
+        return mDropView;
+    }
+
+    private void fadeOutDragView() {
+        mFadeOutAnim = new ValueAnimator();
+        mFadeOutAnim.setDuration(150);
+        mFadeOutAnim.setFloatValues(0f, 1f);
+        mFadeOutAnim.removeAllUpdateListeners();
+        mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float percent = (Float) animation.getAnimatedValue();
+
+                float alpha = 1 - percent;
+                mDropView.setAlpha(alpha);
+            }
+        });
+        mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                if (mDropView != null) {
+                    mDragController.onDeferredEndDrag(mDropView);
+                }
+                mDropView = null;
+                invalidate();
+            }
+        });
+        mFadeOutAnim.start();
+    }
+
+    @Override
+    public void onChildViewAdded(View parent, View child) {
+        updateChildIndices();
+    }
+
+    @Override
+    public void onChildViewRemoved(View parent, View child) {
+        updateChildIndices();
+    }
+
+    private void updateChildIndices() {
+        if (mLauncher != null) {
+            mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
+            mQsbIndex = indexOfChild(mLauncher.getSearchBar());
+        }
+    }
+
+    @Override
+    protected int getChildDrawingOrder(int childCount, int i) {
+        // TODO: We have turned off this custom drawing order because it now effects touch
+        // dispatch order. We need to sort that issue out and then decide how to go about this.
+        if (true || LauncherApplication.isScreenLandscape(getContext()) ||
+                mWorkspaceIndex == -1 || mQsbIndex == -1 ||
+                mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
+            return i;
+        }
+
+        // This ensures that the workspace is drawn above the hotseat and qsb,
+        // except when the workspace is drawing a background gradient, in which
+        // case we want the workspace to stay behind these elements.
+        if (i == mQsbIndex) {
+            return mWorkspaceIndex;
+        } else if (i == mWorkspaceIndex) {
+            return mQsbIndex;
+        } else {
+            return i;
+        }
+    }
+
+    private boolean mInScrollArea;
+    private Drawable mLeftHoverDrawable;
+    private Drawable mRightHoverDrawable;
+
+    void onEnterScrollArea(int direction) {
+        mInScrollArea = true;
+        invalidate();
+    }
+
+    void onExitScrollArea() {
+        mInScrollArea = false;
+        invalidate();
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+
+        if (mInScrollArea && !LauncherApplication.isScreenLarge()) {
+            Workspace workspace = mLauncher.getWorkspace();
+            int width = workspace.getWidth();
+            Rect childRect = new Rect();
+            getDescendantRectRelativeToSelf(workspace.getChildAt(0), childRect);
+
+            int page = workspace.getNextPage();
+            CellLayout leftPage = (CellLayout) workspace.getChildAt(page - 1);
+            CellLayout rightPage = (CellLayout) workspace.getChildAt(page + 1);
+
+            if (leftPage != null && leftPage.getIsDragOverlapping()) {
+                mLeftHoverDrawable.setBounds(0, childRect.top,
+                        mLeftHoverDrawable.getIntrinsicWidth(), childRect.bottom);
+                mLeftHoverDrawable.draw(canvas);
+            } else if (rightPage != null && rightPage.getIsDragOverlapping()) {
+                mRightHoverDrawable.setBounds(width - mRightHoverDrawable.getIntrinsicWidth(),
+                        childRect.top, width, childRect.bottom);
+                mRightHoverDrawable.draw(canvas);
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DragScroller.java b/FairphoneHome/src/org/fairphone/launcher/DragScroller.java
new file mode 100644
index 0000000..08635a0
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DragScroller.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+/**
+ * Handles scrolling while dragging
+ *
+ */
+public interface DragScroller {
+    void scrollLeft();
+    void scrollRight();
+
+    /**
+     * The touch point has entered the scroll area; a scroll is imminent.
+     * This event will only occur while a drag is active.
+     *
+     * @param direction The scroll direction
+     */
+    boolean onEnterScrollArea(int x, int y, int direction);
+
+    /**
+     * The touch point has left the scroll area.
+     * NOTE: This may not be called, if a drop occurs inside the scroll area.
+     */
+    boolean onExitScrollArea();
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DragSource.java b/FairphoneHome/src/org/fairphone/launcher/DragSource.java
new file mode 100644
index 0000000..8649b0c
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DragSource.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import org.fairphone.launcher.DropTarget.DragObject;
+
+import android.view.View;
+
+
+/**
+ * Interface defining an object that can originate a drag.
+ *
+ */
+public interface DragSource {
+    /**
+     * @return whether items dragged from this source supports
+     */
+    boolean supportsFlingToDelete();
+
+    /**
+     * A callback specifically made back to the source after an item from this source has been flung
+     * to be deleted on a DropTarget.  In such a situation, this method will be called after
+     * onDropCompleted, and more importantly, after the fling animation has completed.
+     */
+    void onFlingToDeleteCompleted();
+
+    /**
+     * A callback made back to the source after an item from this source has been dropped on a
+     * DropTarget.
+     */
+    void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, boolean success);
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DragView.java b/FairphoneHome/src/org/fairphone/launcher/DragView.java
new file mode 100644
index 0000000..d26ff94
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DragView.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+
+import org.fairphone.launcher.R;
+
+public class DragView extends View {
+    private static float sDragAlpha = 1f;
+
+    private Bitmap mBitmap;
+    private Bitmap mCrossFadeBitmap;
+    private Paint mPaint;
+    private int mRegistrationX;
+    private int mRegistrationY;
+
+    private Point mDragVisualizeOffset = null;
+    private Rect mDragRegion = null;
+    private DragLayer mDragLayer = null;
+    private boolean mHasDrawn = false;
+    private float mCrossFadeProgress = 0f;
+
+    ValueAnimator mAnim;
+    private float mOffsetX = 0.0f;
+    private float mOffsetY = 0.0f;
+    private float mInitialScale = 1f;
+
+    /**
+     * Construct the drag view.
+     * <p>
+     * The registration point is the point inside our view that the touch events should
+     * be centered upon.
+     *
+     * @param launcher The Launcher instance
+     * @param bitmap The view that we're dragging around.  We scale it up when we draw it.
+     * @param registrationX The x coordinate of the registration point.
+     * @param registrationY The y coordinate of the registration point.
+     */
+    public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
+            int left, int top, int width, int height, final float initialScale) {
+        super(launcher);
+        mDragLayer = launcher.getDragLayer();
+        mInitialScale = initialScale;
+
+        final Resources res = getResources();
+        final float offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
+        final float offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
+        final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
+        final float scale = (width + scaleDps) / width;
+
+        // Set the initial scale to avoid any jumps
+        setScaleX(initialScale);
+        setScaleY(initialScale);
+
+        // Animate the view into the correct position
+        mAnim = LauncherAnimUtils.ofFloat(0.0f, 1.0f);
+        mAnim.setDuration(150);
+        mAnim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float value = (Float) animation.getAnimatedValue();
+
+                final int deltaX = (int) ((value * offsetX) - mOffsetX);
+                final int deltaY = (int) ((value * offsetY) - mOffsetY);
+
+                mOffsetX += deltaX;
+                mOffsetY += deltaY;
+                setScaleX(initialScale + (value * (scale - initialScale)));
+                setScaleY(initialScale + (value * (scale - initialScale)));
+                if (sDragAlpha != 1f) {
+                    setAlpha(sDragAlpha * value + (1f - value));
+                }
+
+                if (getParent() == null) {
+                    animation.cancel();
+                } else {
+                    setTranslationX(getTranslationX() + deltaX);
+                    setTranslationY(getTranslationY() + deltaY);
+                }
+            }
+        });
+
+        mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height);
+        setDragRegion(new Rect(0, 0, width, height));
+
+        // The point in our scaled bitmap that the touch events are located
+        mRegistrationX = registrationX;
+        mRegistrationY = registrationY;
+
+        // Force a measure, because Workspace uses getMeasuredHeight() before the layout pass
+        int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+        measure(ms, ms);
+        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+    }
+
+    public float getOffsetY() {
+        return mOffsetY;
+    }
+
+    public int getDragRegionLeft() {
+        return mDragRegion.left;
+    }
+
+    public int getDragRegionTop() {
+        return mDragRegion.top;
+    }
+
+    public int getDragRegionWidth() {
+        return mDragRegion.width();
+    }
+
+    public int getDragRegionHeight() {
+        return mDragRegion.height();
+    }
+
+    public void setDragVisualizeOffset(Point p) {
+        mDragVisualizeOffset = p;
+    }
+
+    public Point getDragVisualizeOffset() {
+        return mDragVisualizeOffset;
+    }
+
+    public void setDragRegion(Rect r) {
+        mDragRegion = r;
+    }
+
+    public Rect getDragRegion() {
+        return mDragRegion;
+    }
+
+    public float getInitialScale() {
+        return mInitialScale;
+    }
+
+    public void updateInitialScaleToCurrentScale() {
+        mInitialScale = getScaleX();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight());
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        @SuppressWarnings("all") // suppress dead code warning
+        final boolean debug = false;
+        if (debug) {
+            Paint p = new Paint();
+            p.setStyle(Paint.Style.FILL);
+            p.setColor(0x66ffffff);
+            canvas.drawRect(0, 0, getWidth(), getHeight(), p);
+        }
+
+        mHasDrawn = true;
+        boolean crossFade = mCrossFadeProgress > 0 && mCrossFadeBitmap != null;
+        if (crossFade) {
+            int alpha = crossFade ? (int) (255 * (1 - mCrossFadeProgress)) : 255;
+            mPaint.setAlpha(alpha);
+        }
+        canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
+        if (crossFade) {
+            mPaint.setAlpha((int) (255 * mCrossFadeProgress));
+            canvas.save();
+            float sX = (mBitmap.getWidth() * 1.0f) / mCrossFadeBitmap.getWidth();
+            float sY = (mBitmap.getHeight() * 1.0f) / mCrossFadeBitmap.getHeight();
+            canvas.scale(sX, sY);
+            canvas.drawBitmap(mCrossFadeBitmap, 0.0f, 0.0f, mPaint);
+            canvas.restore();
+        }
+    }
+
+    public void setCrossFadeBitmap(Bitmap crossFadeBitmap) {
+        mCrossFadeBitmap = crossFadeBitmap;
+    }
+
+    public void crossFade(int duration) {
+        ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
+        va.setDuration(duration);
+        va.setInterpolator(new DecelerateInterpolator(1.5f));
+        va.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                mCrossFadeProgress = animation.getAnimatedFraction();
+            }
+        });
+        va.start();
+    }
+
+    public void setColor(int color) {
+        if (mPaint == null) {
+            mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+        }
+        if (color != 0) {
+            mPaint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
+        } else {
+            mPaint.setColorFilter(null);
+        }
+        invalidate();
+    }
+
+    public boolean hasDrawn() {
+        return mHasDrawn;
+    }
+
+    @Override
+    public void setAlpha(float alpha) {
+        super.setAlpha(alpha);
+        mPaint.setAlpha((int) (255 * alpha));
+        invalidate();
+    }
+
+    /**
+     * Create a window containing this view and show it.
+     *
+     * @param windowToken obtained from v.getWindowToken() from one of your views
+     * @param touchX the x coordinate the user touched in DragLayer coordinates
+     * @param touchY the y coordinate the user touched in DragLayer coordinates
+     */
+    public void show(int touchX, int touchY) {
+        mDragLayer.addView(this);
+
+        // Start the pick-up animation
+        DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
+        lp.width = mBitmap.getWidth();
+        lp.height = mBitmap.getHeight();
+        lp.customPosition = true;
+        setLayoutParams(lp);
+        setTranslationX(touchX - mRegistrationX);
+        setTranslationY(touchY - mRegistrationY);
+        // Post the animation to skip other expensive work happening on the first frame
+        post(new Runnable() {
+                public void run() {
+                    mAnim.start();
+                }
+            });
+    }
+
+    public void cancelAnimation() {
+        if (mAnim != null && mAnim.isRunning()) {
+            mAnim.cancel();
+        }
+    }
+
+    public void resetLayoutParams() {
+        mOffsetX = mOffsetY = 0;
+        requestLayout();
+    }
+
+    /**
+     * Move the window containing this view.
+     *
+     * @param touchX the x coordinate the user touched in DragLayer coordinates
+     * @param touchY the y coordinate the user touched in DragLayer coordinates
+     */
+    void move(int touchX, int touchY) {
+        setTranslationX(touchX - mRegistrationX + (int) mOffsetX);
+        setTranslationY(touchY - mRegistrationY + (int) mOffsetY);
+    }
+
+    void remove() {
+        if (getParent() != null) {
+            mDragLayer.removeView(DragView.this);
+        }
+    }
+}
+
diff --git a/FairphoneHome/src/org/fairphone/launcher/DrawableStateProxyView.java b/FairphoneHome/src/org/fairphone/launcher/DrawableStateProxyView.java
new file mode 100644
index 0000000..79fa871
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DrawableStateProxyView.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import org.fairphone.launcher.R;
+
+public class DrawableStateProxyView extends LinearLayout {
+
+    private View mView;
+    private int mViewId;
+
+    public DrawableStateProxyView(Context context) {
+        this(context, null);
+    }
+
+    public DrawableStateProxyView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+
+    public DrawableStateProxyView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableStateProxyView,
+                defStyle, 0);
+        mViewId = a.getResourceId(R.styleable.DrawableStateProxyView_sourceViewId, -1);
+        a.recycle();
+
+        setFocusable(false);
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+
+        if (mView == null) {
+            View parent = (View) getParent();
+            mView = parent.findViewById(mViewId);
+        }
+        
+        if(mView != null){
+        	mView.setPressed(isPressed());
+        	mView.setHovered(isHovered());
+        }
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        return false;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/DropTarget.java b/FairphoneHome/src/org/fairphone/launcher/DropTarget.java
new file mode 100644
index 0000000..34ee4f4
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/DropTarget.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.util.Log;
+
+/**
+ * Interface defining an object that can receive a drag.
+ *
+ */
+public interface DropTarget {
+
+    public static final String TAG = "DropTarget";
+
+    class DragObject {
+        public int x = -1;
+        public int y = -1;
+
+        /** X offset from the upper-left corner of the cell to where we touched.  */
+        public int xOffset = -1;
+
+        /** Y offset from the upper-left corner of the cell to where we touched.  */
+        public int yOffset = -1;
+
+        /** This indicates whether a drag is in final stages, either drop or cancel. It
+         * differentiates onDragExit, since this is called when the drag is ending, above
+         * the current drag target, or when the drag moves off the current drag object.
+         */
+        public boolean dragComplete = false;
+
+        /** The view that moves around while you drag.  */
+        public DragView dragView = null;
+
+        /** The data associated with the object being dragged */
+        public Object dragInfo = null;
+
+        /** Where the drag originated */
+        public DragSource dragSource = null;
+
+        /** Post drag animation runnable */
+        public Runnable postAnimationRunnable = null;
+
+        /** Indicates that the drag operation was cancelled */
+        public boolean cancelled = false;
+
+        /** Defers removing the DragView from the DragLayer until after the drop animation. */
+        public boolean deferDragViewCleanupPostAnimation = true;
+
+        public DragObject() {
+        }
+    }
+
+    public static class DragEnforcer implements DragController.DragListener {
+        int dragParity = 0;
+
+        public DragEnforcer(Context context) {
+            Launcher launcher = (Launcher) context;
+            launcher.getDragController().addDragListener(this);
+        }
+
+        void onDragEnter() {
+            dragParity++;
+            if (dragParity != 1) {
+                Log.e(TAG, "onDragEnter: Drag contract violated: " + dragParity);
+            }
+        }
+
+        void onDragExit() {
+            dragParity--;
+            if (dragParity != 0) {
+                Log.e(TAG, "onDragExit: Drag contract violated: " + dragParity);
+            }
+        }
+
+        @Override
+        public void onDragStart(DragSource source, Object info, int dragAction) {
+            if (dragParity != 0) {
+                Log.e(TAG, "onDragEnter: Drag contract violated: " + dragParity);
+            }
+        }
+
+        @Override
+        public void onDragEnd() {
+            if (dragParity != 0) {
+                Log.e(TAG, "onDragExit: Drag contract violated: " + dragParity);
+            }
+        }
+    }
+
+    /**
+     * Used to temporarily disable certain drop targets
+     *
+     * @return boolean specifying whether this drop target is currently enabled
+     */
+    boolean isDropEnabled();
+
+    /**
+     * Handle an object being dropped on the DropTarget
+     * 
+     * @param source DragSource where the drag started
+     * @param x X coordinate of the drop location
+     * @param y Y coordinate of the drop location
+     * @param xOffset Horizontal offset with the object being dragged where the original
+     *          touch happened
+     * @param yOffset Vertical offset with the object being dragged where the original
+     *          touch happened
+     * @param dragView The DragView that's being dragged around on screen.
+     * @param dragInfo Data associated with the object being dragged
+     * 
+     */
+    void onDrop(DragObject dragObject);
+
+    void onDragEnter(DragObject dragObject);
+
+    void onDragOver(DragObject dragObject);
+
+    void onDragExit(DragObject dragObject);
+
+    /**
+     * Handle an object being dropped as a result of flinging to delete and will be called in place
+     * of onDrop().  (This is only called on objects that are set as the DragController's
+     * fling-to-delete target.
+     */
+    void onFlingToDelete(DragObject dragObject, int x, int y, PointF vec);
+
+    /**
+     * Allows a DropTarget to delegate drag and drop events to another object.
+     *
+     * Most subclasses will should just return null from this method.
+     *
+     * @param source DragSource where the drag started
+     * @param x X coordinate of the drop location
+     * @param y Y coordinate of the drop location
+     * @param xOffset Horizontal offset with the object being dragged where the original
+     *          touch happened
+     * @param yOffset Vertical offset with the object being dragged where the original
+     *          touch happened
+     * @param dragView The DragView that's being dragged around on screen.
+     * @param dragInfo Data associated with the object being dragged
+     *
+     * @return The DropTarget to delegate to, or null to not delegate to another object.
+     */
+    DropTarget getDropTargetDelegate(DragObject dragObject);
+
+    /**
+     * Check if a drop action can occur at, or near, the requested location.
+     * This will be called just before onDrop.
+     * 
+     * @param source DragSource where the drag started
+     * @param x X coordinate of the drop location
+     * @param y Y coordinate of the drop location
+     * @param xOffset Horizontal offset with the object being dragged where the
+     *            original touch happened
+     * @param yOffset Vertical offset with the object being dragged where the
+     *            original touch happened
+     * @param dragView The DragView that's being dragged around on screen.
+     * @param dragInfo Data associated with the object being dragged
+     * @return True if the drop will be accepted, false otherwise.
+     */
+    boolean acceptDrop(DragObject dragObject);
+
+    // These methods are implemented in Views
+    void getHitRect(Rect outRect);
+    void getLocationInDragLayer(int[] loc);
+    int getLeft();
+    int getTop();
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FairphoneApplication.java b/FairphoneHome/src/org/fairphone/launcher/FairphoneApplication.java
new file mode 100644
index 0000000..60b42bc
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FairphoneApplication.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.fairphone.launcher;
+
+import org.acra.ACRA;
+import org.acra.ReportField;
+import org.acra.annotation.ReportsCrashes;
+
+@ReportsCrashes(formKey = "dDFyQmdEbmtvU0UwZUNRVDY1WEc3WWc6MQ", logcatFilterByPid = true, logcatArguments = {
+        "-t", "500"
+}, customReportContent = {
+        ReportField.REPORT_ID, ReportField.APP_VERSION_CODE, ReportField.APP_VERSION_NAME, ReportField.PACKAGE_NAME, ReportField.FILE_PATH,
+        ReportField.PHONE_MODEL, ReportField.BRAND, ReportField.PRODUCT, ReportField.ANDROID_VERSION, ReportField.BUILD, ReportField.TOTAL_MEM_SIZE,
+        ReportField.AVAILABLE_MEM_SIZE, ReportField.CUSTOM_DATA, ReportField.IS_SILENT, ReportField.STACK_TRACE, ReportField.INITIAL_CONFIGURATION,
+        ReportField.CRASH_CONFIGURATION, ReportField.DISPLAY, ReportField.USER_COMMENT, ReportField.USER_EMAIL, ReportField.USER_APP_START_DATE,
+        ReportField.USER_CRASH_DATE, ReportField.DUMPSYS_MEMINFO, ReportField.LOGCAT, ReportField.INSTALLATION_ID, ReportField.DEVICE_FEATURES,
+        ReportField.ENVIRONMENT, ReportField.SHARED_PREFERENCES, ReportField.SETTINGS_SYSTEM, ReportField.SETTINGS_SECURE, ReportField.EVENTSLOG,
+        ReportField.RADIOLOG
+})
+public class FairphoneApplication extends LauncherApplication
+{
+    @Override
+    public void onCreate()
+    {
+        ACRA.init(this);
+
+        super.onCreate();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FastBitmapDrawable.java b/FairphoneHome/src/org/fairphone/launcher/FastBitmapDrawable.java
new file mode 100644
index 0000000..49a2e19
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FastBitmapDrawable.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+class FastBitmapDrawable extends Drawable {
+    private Bitmap mBitmap;
+    private int mAlpha;
+    private int mWidth;
+    private int mHeight;
+    private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+
+    FastBitmapDrawable(Bitmap b) {
+	mAlpha = 255;
+        mBitmap = b;
+        if (b != null) {
+            mWidth = mBitmap.getWidth();
+            mHeight = mBitmap.getHeight();
+        } else {
+            mWidth = mHeight = 0;
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final Rect r = getBounds();
+        canvas.drawBitmap(mBitmap, r.left, r.top, mPaint);
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+        mPaint.setColorFilter(cf);
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mAlpha = alpha;
+        mPaint.setAlpha(alpha);
+    }
+
+    public void setFilterBitmap(boolean filterBitmap) {
+        mPaint.setFilterBitmap(filterBitmap);
+    }
+
+    public int getAlpha() {
+        return mAlpha;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mWidth;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mHeight;
+    }
+
+    @Override
+    public int getMinimumWidth() {
+        return mWidth;
+    }
+
+    @Override
+    public int getMinimumHeight() {
+        return mHeight;
+    }
+
+    public void setBitmap(Bitmap b) {
+        mBitmap = b;
+        if (b != null) {
+            mWidth = mBitmap.getWidth();
+            mHeight = mBitmap.getHeight();
+        } else {
+            mWidth = mHeight = 0;
+        }
+    }
+
+    public Bitmap getBitmap() {
+        return mBitmap;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FocusHelper.java b/FairphoneHome/src/org/fairphone/launcher/FocusHelper.java
new file mode 100644
index 0000000..6ead468
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FocusHelper.java
@@ -0,0 +1,896 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.res.Configuration;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * A keyboard listener we set on all the workspace icons.
+ */
+class IconKeyEventListener implements View.OnKeyListener {
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleIconKeyEvent(v, keyCode, event);
+    }
+}
+
+/**
+ * A keyboard listener we set on all the workspace icons.
+ */
+class FolderKeyEventListener implements View.OnKeyListener {
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleFolderKeyEvent(v, keyCode, event);
+    }
+}
+
+/**
+ * A keyboard listener we set on all the hotseat buttons.
+ */
+class HotseatIconKeyEventListener implements View.OnKeyListener {
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        final Configuration configuration = v.getResources().getConfiguration();
+        return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event, configuration.orientation);
+    }
+}
+
+/**
+ * A keyboard listener we set on the last tab button in AppsCustomize to jump to then
+ * market icon and vice versa.
+ */
+class AppsCustomizeTabKeyEventListener implements View.OnKeyListener {
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleAppsCustomizeTabKeyEvent(v, keyCode, event);
+    }
+}
+
+public class FocusHelper {
+    /**
+     * Private helper to get the parent TabHost in the view hiearchy.
+     */
+    private static TabHost findTabHostParent(View v) {
+        ViewParent p = v.getParent();
+        while (p != null && !(p instanceof TabHost)) {
+            p = p.getParent();
+        }
+        return (TabHost) p;
+    }
+
+    /**
+     * Handles key events in a AppsCustomize tab between the last tab view and the shop button.
+     */
+    static boolean handleAppsCustomizeTabKeyEvent(View v, int keyCode, KeyEvent e) {
+        final TabHost tabHost = findTabHostParent(v);
+        final ViewGroup contents = tabHost.getTabContentView();
+        final View shop = tabHost.findViewById(R.id.market_button);
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the shop button if we aren't on it
+                    if (v != shop) {
+                        shop.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the content view (down is handled by the tab key handler otherwise)
+                    if (v == shop) {
+                        contents.requestFocus();
+                        wasHandled = true;
+                    }
+                }
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Returns the Viewgroup containing page contents for the page at the index specified.
+     */
+    private static ViewGroup getAppsCustomizePage(ViewGroup container, int index) {
+        ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index);
+        if (page instanceof PagedViewCellLayout) {
+            // There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren
+            page = (ViewGroup) page.getChildAt(0);
+        }
+        return page;
+    }
+
+    /**
+     * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
+     */
+    static boolean handlePagedViewGridLayoutWidgetKeyEvent(PagedViewWidget w, int keyCode,
+            KeyEvent e) {
+
+        final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent();
+        final PagedView container = (PagedView) parent.getParent();
+        final TabHost tabHost = findTabHostParent(container);
+        final TabWidget tabs = tabHost.getTabWidget();
+        final int widgetIndex = parent.indexOfChild(w);
+        final int widgetCount = parent.getChildCount();
+        final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent));
+        final int pageCount = container.getChildCount();
+        final int cellCountX = parent.getCellCountX();
+        final int cellCountY = parent.getCellCountY();
+        final int x = widgetIndex % cellCountX;
+        final int y = widgetIndex / cellCountX;
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        ViewGroup newParent = null;
+        // Now that we load items in the bg asynchronously, we can't just focus
+        // child siblings willy-nilly
+        View child = null;
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous widget or the last widget on the previous page
+                    if (widgetIndex > 0) {
+                        parent.getChildAt(widgetIndex - 1).requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            newParent = getAppsCustomizePage(container, pageIndex - 1);
+                            if (newParent != null) {
+                                child = newParent.getChildAt(newParent.getChildCount() - 1);
+                                if (child != null) child.requestFocus();
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next widget or the first widget on the next page
+                    if (widgetIndex < (widgetCount - 1)) {
+                        parent.getChildAt(widgetIndex + 1).requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            newParent = getAppsCustomizePage(container, pageIndex + 1);
+                            if (newParent != null) {
+                                child = newParent.getChildAt(0);
+                                if (child != null) child.requestFocus();
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise select the tab bar
+                    if (y > 0) {
+                        int newWidgetIndex = ((y - 1) * cellCountX) + x;
+                        child = parent.getChildAt(newWidgetIndex);
+                        if (child != null) child.requestFocus();
+                    } else {
+                        tabs.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise do nothing
+                    if (y < (cellCountY - 1)) {
+                        int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
+                        child = parent.getChildAt(newWidgetIndex);
+                        if (child != null) child.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+                if (handleKeyEvent) {
+                    // Simulate a click on the widget
+                    View.OnClickListener clickListener = (View.OnClickListener) container;
+                    clickListener.onClick(w);
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first item on the previous page, or the first item on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        newParent = getAppsCustomizePage(container, pageIndex - 1);
+                        if (newParent != null) {
+                            child = newParent.getChildAt(0);
+                        }
+                    } else {
+                        child = parent.getChildAt(0);
+                    }
+                    if (child != null) child.requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first item on the next page, or the last item on this page
+                    // if there is no next page
+                    if (pageIndex < (pageCount - 1)) {
+                        newParent = getAppsCustomizePage(container, pageIndex + 1);
+                        if (newParent != null) {
+                            child = newParent.getChildAt(0);
+                        }
+                    } else {
+                        child = parent.getChildAt(widgetCount - 1);
+                    }
+                    if (child != null) child.requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first item on this page
+                    child = parent.getChildAt(0);
+                    if (child != null) child.requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last item on this page
+                    parent.getChildAt(widgetCount - 1).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in a PageViewCellLayout containing PagedViewIcons.
+     */
+    static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) {
+        ViewGroup parentLayout;
+        ViewGroup itemContainer;
+        int countX;
+        int countY;
+        if (v.getParent() instanceof PagedViewCellLayoutChildren) {
+            itemContainer = (ViewGroup) v.getParent();
+            parentLayout = (ViewGroup) itemContainer.getParent();
+            countX = ((PagedViewCellLayout) parentLayout).getCellCountX();
+            countY = ((PagedViewCellLayout) parentLayout).getCellCountY();
+        } else {
+            itemContainer = parentLayout = (ViewGroup) v.getParent();
+            countX = ((PagedViewGridLayout) parentLayout).getCellCountX();
+            countY = ((PagedViewGridLayout) parentLayout).getCellCountY();
+        }
+
+        // Note we have an extra parent because of the
+        // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
+        final PagedView container = (PagedView) parentLayout.getParent();
+        final TabHost tabHost = findTabHostParent(container);
+        final TabWidget tabs = tabHost.getTabWidget();
+        final int iconIndex = itemContainer.indexOfChild(v);
+        final int itemCount = itemContainer.getChildCount();
+        final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout));
+        final int pageCount = container.getChildCount();
+
+        final int x = iconIndex % countX;
+        final int y = iconIndex / countX;
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        ViewGroup newParent = null;
+        // Side pages do not always load synchronously, so check before focusing child siblings
+        // willy-nilly
+        View child = null;
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous icon or the last icon on the previous page
+                    if (iconIndex > 0) {
+                        itemContainer.getChildAt(iconIndex - 1).requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            newParent = getAppsCustomizePage(container, pageIndex - 1);
+                            if (newParent != null) {
+                                container.snapToPage(pageIndex - 1);
+                                child = newParent.getChildAt(newParent.getChildCount() - 1);
+                                if (child != null) child.requestFocus();
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next icon or the first icon on the next page
+                    if (iconIndex < (itemCount - 1)) {
+                        itemContainer.getChildAt(iconIndex + 1).requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            newParent = getAppsCustomizePage(container, pageIndex + 1);
+                            if (newParent != null) {
+                                container.snapToPage(pageIndex + 1);
+                                child = newParent.getChildAt(0);
+                                if (child != null) child.requestFocus();
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise select the tab bar
+                    if (y > 0) {
+                        int newiconIndex = ((y - 1) * countX) + x;
+                        itemContainer.getChildAt(newiconIndex).requestFocus();
+                    } else {
+                        tabs.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise do nothing
+                    if (y < (countY - 1)) {
+                        int newiconIndex = Math.min(itemCount - 1, ((y + 1) * countX) + x);
+                        itemContainer.getChildAt(newiconIndex).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+                if (handleKeyEvent) {
+                    // Simulate a click on the icon
+                    View.OnClickListener clickListener = (View.OnClickListener) container;
+                    clickListener.onClick(v);
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first icon on the previous page, or the first icon on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        newParent = getAppsCustomizePage(container, pageIndex - 1);
+                        if (newParent != null) {
+                            container.snapToPage(pageIndex - 1);
+                            child = newParent.getChildAt(0);
+                            if (child != null) child.requestFocus();
+                        }
+                    } else {
+                        itemContainer.getChildAt(0).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first icon on the next page, or the last icon on this page
+                    // if there is no next page
+                    if (pageIndex < (pageCount - 1)) {
+                        newParent = getAppsCustomizePage(container, pageIndex + 1);
+                        if (newParent != null) {
+                            container.snapToPage(pageIndex + 1);
+                            child = newParent.getChildAt(0);
+                            if (child != null) child.requestFocus();
+                        }
+                    } else {
+                        itemContainer.getChildAt(itemCount - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first icon on this page
+                    itemContainer.getChildAt(0).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last icon on this page
+                    itemContainer.getChildAt(itemCount - 1).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in the tab widget.
+     */
+    static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) {
+        if (!LauncherApplication.isScreenLarge()) return false;
+
+        final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
+        final TabHost tabHost = findTabHostParent(parent);
+        final ViewGroup contents = tabHost.getTabContentView();
+        final int tabCount = parent.getTabCount();
+        final int tabIndex = parent.getChildTabIndex(v);
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous tab
+                    if (tabIndex > 0) {
+                        parent.getChildTabViewAt(tabIndex - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next tab, or if the last tab has a focus right id, select that
+                    if (tabIndex < (tabCount - 1)) {
+                        parent.getChildTabViewAt(tabIndex + 1).requestFocus();
+                    } else {
+                        if (v.getNextFocusRightId() != View.NO_ID) {
+                            tabHost.findViewById(v.getNextFocusRightId()).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                // Do nothing
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the content view
+                    contents.requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in the workspace hotseat (bottom of the screen).
+     */
+    static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
+        final ViewGroup parent = (ViewGroup) v.getParent();
+        final ViewGroup launcher = (ViewGroup) parent.getParent();
+        final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+        final int buttonIndex = parent.indexOfChild(v);
+        final int buttonCount = parent.getChildCount();
+        final int pageIndex = workspace.getCurrentPage();
+
+        // NOTE: currently we don't special case for the phone UI in different
+        // orientations, even though the hotseat is on the side in landscape mode.  This
+        // is to ensure that accessibility consistency is maintained across rotations.
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous button, otherwise snap to the previous page
+                    if (buttonIndex > 0) {
+                        parent.getChildAt(buttonIndex - 1).requestFocus();
+                    } else {
+                        workspace.snapToPage(pageIndex - 1);
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next button, otherwise snap to the next page
+                    if (buttonIndex < (buttonCount - 1)) {
+                        parent.getChildAt(buttonIndex + 1).requestFocus();
+                    } else {
+                        workspace.snapToPage(pageIndex + 1);
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the first bubble text view in the current page of the workspace
+                    final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+                    final ShortcutAndWidgetContainer children = layout.getShortcutsAndWidgets();
+                    final View newIcon = getIconInDirection(layout, children, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        workspace.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                // Do nothing
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Private helper method to get the CellLayoutChildren given a CellLayout index.
+     */
+    private static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex(
+            ViewGroup container, int i) {
+        ViewGroup parent = (ViewGroup) container.getChildAt(i);
+        return (ShortcutAndWidgetContainer) parent.getChildAt(0);
+    }
+
+    /**
+     * Private helper method to sort all the CellLayout children in order of their (x,y) spatially
+     * from top left to bottom right.
+     */
+    private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout,
+            ViewGroup parent) {
+        // First we order each the CellLayout children by their x,y coordinates
+        final int cellCountX = layout.getCountX();
+        final int count = parent.getChildCount();
+        ArrayList<View> views = new ArrayList<View>();
+        for (int j = 0; j < count; ++j) {
+            views.add(parent.getChildAt(j));
+        }
+        Collections.sort(views, new Comparator<View>() {
+            @Override
+            public int compare(View lhs, View rhs) {
+                CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams();
+                CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams();
+                int lvIndex = (llp.cellY * cellCountX) + llp.cellX;
+                int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX;
+                return lvIndex - rvIndex;
+            }
+        });
+        return views;
+    }
+    /**
+     * Private helper method to find the index of the next BubbleTextView or FolderIcon in the 
+     * direction delta.
+     * 
+     * @param delta either -1 or 1 depending on the direction we want to search
+     */
+    private static View findIndexOfIcon(ArrayList<View> views, int i, int delta) {
+        // Then we find the next BubbleTextView offset by delta from i
+        final int count = views.size();
+        int newI = i + delta;
+        while (0 <= newI && newI < count) {
+            View newV = views.get(newI);
+            if (newV instanceof BubbleTextView || newV instanceof FolderIcon) {
+                return newV;
+            }
+            newI += delta;
+        }
+        return null;
+    }
+    private static View getIconInDirection(CellLayout layout, ViewGroup parent, int i,
+            int delta) {
+        final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+        return findIndexOfIcon(views, i, delta);
+    }
+    private static View getIconInDirection(CellLayout layout, ViewGroup parent, View v,
+            int delta) {
+        final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+        return findIndexOfIcon(views, views.indexOf(v), delta);
+    }
+    /**
+     * Private helper method to find the next closest BubbleTextView or FolderIcon in the direction 
+     * delta on the next line.
+     * 
+     * @param delta either -1 or 1 depending on the line and direction we want to search
+     */
+    private static View getClosestIconOnLine(CellLayout layout, ViewGroup parent, View v,
+            int lineDelta) {
+        final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+        final int cellCountY = layout.getCountY();
+        final int row = lp.cellY;
+        final int newRow = row + lineDelta;
+        if (0 <= newRow && newRow < cellCountY) {
+            float closestDistance = Float.MAX_VALUE;
+            int closestIndex = -1;
+            int index = views.indexOf(v);
+            int endIndex = (lineDelta < 0) ? -1 : views.size();
+            while (index != endIndex) {
+                View newV = views.get(index);
+                CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams();
+                boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row);
+                if (satisfiesRow &&
+                        (newV instanceof BubbleTextView || newV instanceof FolderIcon)) {
+                    float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
+                            Math.pow(tmpLp.cellY - lp.cellY, 2));
+                    if (tmpDistance < closestDistance) {
+                        closestIndex = index;
+                        closestDistance = tmpDistance;
+                    }
+                }
+                if (index <= endIndex) {
+                    ++index;
+                } else {
+                    --index;
+                }
+            }
+            if (closestIndex > -1) {
+                return views.get(closestIndex);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Handles key events in a Workspace containing.
+     */
+    static boolean handleIconKeyEvent(View v, int keyCode, KeyEvent e) {
+        ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
+        final CellLayout layout = (CellLayout) parent.getParent();
+        final Workspace workspace = (Workspace) layout.getParent();
+        final ViewGroup launcher = (ViewGroup) workspace.getParent();
+        final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.qsb_bar);
+        int pageIndex = workspace.indexOfChild(layout);
+        int pageCount = workspace.getChildCount();
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous icon or the last icon on the previous page if possible
+                    View newIcon = getIconInDirection(layout, parent, v, -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+                            newIcon = getIconInDirection(layout, parent,
+                                    parent.getChildCount(), -1);
+                            if (newIcon != null) {
+                                newIcon.requestFocus();
+                            } else {
+                                // Snap to the previous page
+                                workspace.snapToPage(pageIndex - 1);
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next icon or the first icon on the next page if possible
+                    View newIcon = getIconInDirection(layout, parent, v, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+                            newIcon = getIconInDirection(layout, parent, -1, 1);
+                            if (newIcon != null) {
+                                newIcon.requestFocus();
+                            } else {
+                                // Snap to the next page
+                                workspace.snapToPage(pageIndex + 1);
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous line, otherwise select the tab bar
+                    View newIcon = getClosestIconOnLine(layout, parent, v, -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                        wasHandled = true;
+                    } else {
+                        tabs.requestFocus();
+                    }
+                }
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the next line, otherwise select the button bar
+                    View newIcon = getClosestIconOnLine(layout, parent, v, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                        wasHandled = true;
+                    } 
+                }
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first icon on the previous page or the first icon on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+                        View newIcon = getIconInDirection(layout, parent, -1, 1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        } else {
+                            // Snap to the previous page
+                            workspace.snapToPage(pageIndex - 1);
+                        }
+                    } else {
+                        View newIcon = getIconInDirection(layout, parent, -1, 1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first icon on the next page or the last icon on this page
+                    // if there is no previous page
+                    if (pageIndex < (pageCount - 1)) {
+                        parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+                        View newIcon = getIconInDirection(layout, parent, -1, 1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        } else {
+                            // Snap to the next page
+                            workspace.snapToPage(pageIndex + 1);
+                        }
+                    } else {
+                        View newIcon = getIconInDirection(layout, parent,
+                                parent.getChildCount(), -1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first icon on this page
+                    View newIcon = getIconInDirection(layout, parent, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last icon on this page
+                    View newIcon = getIconInDirection(layout, parent,
+                            parent.getChildCount(), -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events for items in a Folder.
+     */
+    static boolean handleFolderKeyEvent(View v, int keyCode, KeyEvent e) {
+        ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
+        final CellLayout layout = (CellLayout) parent.getParent();
+        final Folder folder = (Folder) layout.getParent();
+        View title = folder.mFolderName;
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous icon
+                    View newIcon = getIconInDirection(layout, parent, v, -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next icon
+                    View newIcon = getIconInDirection(layout, parent, v, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        title.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous line
+                    View newIcon = getClosestIconOnLine(layout, parent, v, -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the next line
+                    View newIcon = getClosestIconOnLine(layout, parent, v, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        title.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first icon on this page
+                    View newIcon = getIconInDirection(layout, parent, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last icon on this page
+                    View newIcon = getIconInDirection(layout, parent,
+                            parent.getChildCount(), -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FocusOnlyTabWidget.java b/FairphoneHome/src/org/fairphone/launcher/FocusOnlyTabWidget.java
new file mode 100644
index 0000000..4a07e97
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FocusOnlyTabWidget.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TabWidget;
+
+public class FocusOnlyTabWidget extends TabWidget {
+    public FocusOnlyTabWidget(Context context) {
+        super(context);
+    }
+
+    public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public View getSelectedTab() {
+        final int count = getTabCount();
+        for (int i = 0; i < count; ++i) {
+            View v = getChildTabViewAt(i);
+            if (v.isSelected()) {
+                return v;
+            }
+        }
+        return null;
+    }
+
+    public int getChildTabIndex(View v) {
+        final int tabCount = getTabCount();
+        for (int i = 0; i < tabCount; ++i) {
+            if (getChildTabViewAt(i) == v) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public void setCurrentTabToFocusedTab() {
+        View tab = null;
+        int index = -1;
+        final int count = getTabCount();
+        for (int i = 0; i < count; ++i) {
+            View v = getChildTabViewAt(i);
+            if (v.hasFocus()) {
+                tab = v;
+                index = i;
+                break;
+            }
+        }
+        if (index > -1) {
+            super.setCurrentTab(index);
+            super.onFocusChange(tab, true);
+        }
+    }
+    public void superOnFocusChange(View v, boolean hasFocus) {
+        super.onFocusChange(v, hasFocus);
+    }
+
+    @Override
+    public void onFocusChange(android.view.View v, boolean hasFocus) {
+        if (v == this && hasFocus && getTabCount() > 0) {
+            getSelectedTab().requestFocus();
+            return;
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Folder.java b/FairphoneHome/src/org/fairphone/launcher/Folder.java
new file mode 100644
index 0000000..63e8fc7
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Folder.java
@@ -0,0 +1,1120 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.InputType;
+import android.text.Selection;
+import android.text.Spannable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ActionMode;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.fairphone.launcher.FolderInfo.FolderListener;
+
+/**
+ * Represents a set of icons chosen by the user or generated by the system.
+ */
+public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
+        View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
+        View.OnFocusChangeListener {
+    private static final String TAG = "Launcher.Folder";
+
+    protected DragController mDragController;
+    protected Launcher mLauncher;
+    protected FolderInfo mInfo;
+
+    static final int STATE_NONE = -1;
+    static final int STATE_SMALL = 0;
+    static final int STATE_ANIMATING = 1;
+    static final int STATE_OPEN = 2;
+
+    private int mExpandDuration;
+    protected CellLayout mContent;
+    private final LayoutInflater mInflater;
+    private final IconCache mIconCache;
+    private int mState = STATE_NONE;
+    private static final int REORDER_ANIMATION_DURATION = 230;
+    private static final int ON_EXIT_CLOSE_DELAY = 800;
+    private boolean mRearrangeOnClose = false;
+    private FolderIcon mFolderIcon;
+    private int mMaxCountX;
+    private int mMaxCountY;
+    private int mMaxNumItems;
+    private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
+    private Drawable mIconDrawable;
+    boolean mItemsInvalidated = false;
+    private ShortcutInfo mCurrentDragInfo;
+    private View mCurrentDragView;
+    boolean mSuppressOnAdd = false;
+    private int[] mTargetCell = new int[2];
+    private int[] mPreviousTargetCell = new int[2];
+    private int[] mEmptyCell = new int[2];
+    private Alarm mReorderAlarm = new Alarm();
+    private Alarm mOnExitAlarm = new Alarm();
+    private int mFolderNameHeight;
+    private Rect mTempRect = new Rect();
+    private boolean mDragInProgress = false;
+    private boolean mDeleteFolderOnDropCompleted = false;
+    private boolean mSuppressFolderDeletion = false;
+    private boolean mItemAddedBackToSelfViaIcon = false;
+    FolderEditText mFolderName;
+    private float mFolderIconPivotX;
+    private float mFolderIconPivotY;
+
+    private boolean mIsEditingName = false;
+    private InputMethodManager mInputMethodManager;
+
+    private static String sDefaultFolderName;
+    private static String sHintText;
+    private ObjectAnimator mOpenCloseAnimator;
+
+    private boolean mDestroyed;
+
+    /**
+     * Used to inflate the Workspace from XML.
+     *
+     * @param context The application's context.
+     * @param attrs The attribtues set containing the Workspace's customization values.
+     */
+    public Folder(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setAlwaysDrawnWithCacheEnabled(false);
+        mInflater = LayoutInflater.from(context);
+        mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
+
+        Resources res = getResources();
+        mMaxCountX = res.getInteger(R.integer.folder_max_count_x);
+        mMaxCountY = res.getInteger(R.integer.folder_max_count_y);
+        mMaxNumItems = res.getInteger(R.integer.folder_max_num_items);
+        if (mMaxCountX < 0 || mMaxCountY < 0 || mMaxNumItems < 0) {
+            mMaxCountX = LauncherModel.getCellCountX();
+            mMaxCountY = LauncherModel.getCellCountY();
+            mMaxNumItems = mMaxCountX * mMaxCountY;
+        }
+
+        mInputMethodManager = (InputMethodManager)
+                getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration);
+
+        if (sDefaultFolderName == null) {
+            sDefaultFolderName = res.getString(R.string.folder_name);
+        }
+        if (sHintText == null) {
+            sHintText = res.getString(R.string.folder_hint_text);
+        }
+        mLauncher = (Launcher) context;
+        // We need this view to be focusable in touch mode so that when text editing of the folder
+        // name is complete, we have something to focus on, thus hiding the cursor and giving
+        // reliable behvior when clicking the text field (since it will always gain focus on click).
+        setFocusableInTouchMode(true);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mContent = (CellLayout) findViewById(R.id.folder_content);
+        mContent.setGridSize(0, 0);
+        mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
+        mFolderName = (FolderEditText) findViewById(R.id.folder_name);
+        mFolderName.setFolder(this);
+        mFolderName.setOnFocusChangeListener(this);
+
+        // We find out how tall the text view wants to be (it is set to wrap_content), so that
+        // we can allocate the appropriate amount of space for it.
+        int measureSpec = MeasureSpec.UNSPECIFIED;
+        mFolderName.measure(measureSpec, measureSpec);
+        mFolderNameHeight = mFolderName.getMeasuredHeight();
+
+        // We disable action mode for now since it messes up the view on phones
+        mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback);
+        mFolderName.setOnEditorActionListener(this);
+        mFolderName.setSelectAllOnFocus(true);
+        mFolderName.setInputType(mFolderName.getInputType() |
+                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+    }
+
+    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
+        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            return false;
+        }
+
+        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            return false;
+        }
+
+        public void onDestroyActionMode(ActionMode mode) {
+        }
+
+        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+            return false;
+        }
+    };
+
+    public void onClick(View v) {
+        Object tag = v.getTag();
+        if (tag instanceof ShortcutInfo) {
+            // refactor this code from Folder
+            ShortcutInfo item = (ShortcutInfo) tag;
+            int[] pos = new int[2];
+            v.getLocationOnScreen(pos);
+            item.intent.setSourceBounds(new Rect(pos[0], pos[1],
+                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+
+            mLauncher.startActivitySafely(v, item.intent, item);
+        }
+    }
+
+    public boolean onLongClick(View v) {
+        // Return if global dragging is not enabled
+        if (!mLauncher.isDraggingEnabled()) return true;
+
+        Object tag = v.getTag();
+        if (tag instanceof ShortcutInfo) {
+            ShortcutInfo item = (ShortcutInfo) tag;
+            if (!v.isInTouchMode()) {
+                return false;
+            }
+
+            mLauncher.dismissFolderCling(null);
+
+            mLauncher.getWorkspace().onDragStartedWithItem(v);
+            mLauncher.getWorkspace().beginDragShared(v, this);
+            mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
+
+            mCurrentDragInfo = item;
+            mEmptyCell[0] = item.cellX;
+            mEmptyCell[1] = item.cellY;
+            mCurrentDragView = v;
+
+            mContent.removeView(mCurrentDragView);
+            mInfo.remove(mCurrentDragInfo);
+            mDragInProgress = true;
+            mItemAddedBackToSelfViaIcon = false;
+        }
+        return true;
+    }
+
+    public boolean isEditingName() {
+        return mIsEditingName;
+    }
+
+    public void startEditingFolderName() {
+        mFolderName.setHint("");
+        mIsEditingName = true;
+    }
+
+    public void dismissEditingName() {
+        mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
+        doneEditingFolderName(true);
+    }
+
+    public void doneEditingFolderName(boolean commit) {
+        mFolderName.setHint(sHintText);
+        // Convert to a string here to ensure that no other state associated with the text field
+        // gets saved.
+        String newTitle = mFolderName.getText().toString();
+        mInfo.setTitle(newTitle);
+        LauncherModel.updateItemInDatabase(mLauncher, mInfo);
+
+        if (commit) {
+            sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+                    String.format(getContext().getString(R.string.folder_renamed), newTitle));
+        }
+        // In order to clear the focus from the text field, we set the focus on ourself. This
+        // ensures that every time the field is clicked, focus is gained, giving reliable behavior.
+        requestFocus();
+
+        Selection.setSelection((Spannable) mFolderName.getText(), 0, 0);
+        mIsEditingName = false;
+    }
+
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        if (actionId == EditorInfo.IME_ACTION_DONE) {
+            dismissEditingName();
+            return true;
+        }
+        return false;
+    }
+
+    public View getEditTextRegion() {
+        return mFolderName;
+    }
+
+    public Drawable getDragDrawable() {
+        return mIconDrawable;
+    }
+
+    /**
+     * We need to handle touch events to prevent them from falling through to the workspace below.
+     */
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return true;
+    }
+
+    public void setDragController(DragController dragController) {
+        mDragController = dragController;
+    }
+
+    void setFolderIcon(FolderIcon icon) {
+        mFolderIcon = icon;
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // When the folder gets focus, we don't want to announce the list of items.
+        return true;
+    }
+
+    /**
+     * @return the FolderInfo object associated with this folder
+     */
+    FolderInfo getInfo() {
+        return mInfo;
+    }
+
+    private class GridComparator implements Comparator<ShortcutInfo> {
+        int mNumCols;
+        public GridComparator(int numCols) {
+            mNumCols = numCols;
+        }
+
+        @Override
+        public int compare(ShortcutInfo lhs, ShortcutInfo rhs) {
+            int lhIndex = lhs.cellY * mNumCols + lhs.cellX;
+            int rhIndex = rhs.cellY * mNumCols + rhs.cellX;
+            return (lhIndex - rhIndex);
+        }
+    }
+
+    private void placeInReadingOrder(ArrayList<ShortcutInfo> items) {
+        int maxX = 0;
+        int count = items.size();
+        for (int i = 0; i < count; i++) {
+            ShortcutInfo item = items.get(i);
+            if (item.cellX > maxX) {
+                maxX = item.cellX;
+            }
+        }
+
+        GridComparator gridComparator = new GridComparator(maxX + 1);
+        Collections.sort(items, gridComparator);
+        final int countX = mContent.getCountX();
+        for (int i = 0; i < count; i++) {
+            int x = i % countX;
+            int y = i / countX;
+            ShortcutInfo item = items.get(i);
+            item.cellX = x;
+            item.cellY = y;
+        }
+    }
+
+    void bind(FolderInfo info) {
+        mInfo = info;
+        ArrayList<ShortcutInfo> children = info.contents;
+        ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>();
+        setupContentForNumItems(children.size());
+        placeInReadingOrder(children);
+        int count = 0;
+        for (int i = 0; i < children.size(); i++) {
+            ShortcutInfo child = (ShortcutInfo) children.get(i);
+            if (!createAndAddShortcut(child)) {
+                overflow.add(child);
+            } else {
+                count++;
+            }
+        }
+
+        // We rearrange the items in case there are any empty gaps
+        setupContentForNumItems(count);
+
+        // If our folder has too many items we prune them from the list. This is an issue 
+        // when upgrading from the old Folders implementation which could contain an unlimited
+        // number of items.
+        for (ShortcutInfo item: overflow) {
+            mInfo.remove(item);
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+        }
+
+        mItemsInvalidated = true;
+        updateTextViewFocus();
+        mInfo.addListener(this);
+
+        if (!sDefaultFolderName.contentEquals(mInfo.title)) {
+            mFolderName.setText(mInfo.title);
+        } else {
+            mFolderName.setText("");
+        }
+        updateItemLocationsInDatabase();
+    }
+
+    /**
+     * Creates a new UserFolder, inflated from R.layout.user_folder.
+     *
+     * @param context The application's context.
+     *
+     * @return A new UserFolder.
+     */
+    static Folder fromXml(Context context) {
+        return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
+    }
+
+    /**
+     * This method is intended to make the UserFolder to be visually identical in size and position
+     * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
+     */
+    private void positionAndSizeAsIcon() {
+        if (!(getParent() instanceof DragLayer)) return;
+        setScaleX(0.8f);
+        setScaleY(0.8f);
+        setAlpha(0f);
+        mState = STATE_SMALL;
+    }
+
+    public void animateOpen() {
+        positionAndSizeAsIcon();
+
+        if (!(getParent() instanceof DragLayer)) return;
+        centerAboutIcon();
+        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
+        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+        final ObjectAnimator oa = mOpenCloseAnimator =
+            LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+
+        oa.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+                        String.format(getContext().getString(R.string.folder_opened),
+                        mContent.getCountX(), mContent.getCountY()));
+                mState = STATE_ANIMATING;
+            }
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mState = STATE_OPEN;
+                setLayerType(LAYER_TYPE_NONE, null);
+                Cling cling = mLauncher.showFirstRunFoldersCling();
+                if (cling != null) {
+                    cling.bringToFront();
+                }
+                setFocusOnFirstChild();
+            }
+        });
+        oa.setDuration(mExpandDuration);
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+        buildLayer();
+        post(new Runnable() {
+            public void run() {
+                // Check if the animator changed in the meantime
+                if (oa != mOpenCloseAnimator)
+                    return;
+                oa.start();
+            }
+        });
+    }
+
+    private void sendCustomAccessibilityEvent(int type, String text) {
+        AccessibilityManager accessibilityManager = (AccessibilityManager)
+                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (accessibilityManager.isEnabled()) {
+            AccessibilityEvent event = AccessibilityEvent.obtain(type);
+            onInitializeAccessibilityEvent(event);
+            event.getText().add(text);
+            accessibilityManager.sendAccessibilityEvent(event);
+        }
+    }
+
+    private void setFocusOnFirstChild() {
+        View firstChild = mContent.getChildAt(0, 0);
+        if (firstChild != null) {
+            firstChild.requestFocus();
+        }
+    }
+
+    public void animateClosed() {
+        if (!(getParent() instanceof DragLayer)) return;
+        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
+        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
+        final ObjectAnimator oa = mOpenCloseAnimator =
+                LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+
+        oa.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                onCloseComplete();
+                setLayerType(LAYER_TYPE_NONE, null);
+                mState = STATE_SMALL;
+            }
+            @Override
+            public void onAnimationStart(Animator animation) {
+                sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
+                        getContext().getString(R.string.folder_closed));
+                mState = STATE_ANIMATING;
+            }
+        });
+        oa.setDuration(mExpandDuration);
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+        buildLayer();
+        post(new Runnable() {
+            public void run() {
+                // Check if the animator changed in the meantime
+                if (oa != mOpenCloseAnimator)
+                    return;
+                oa.start();
+            }
+        });
+    }
+
+    void notifyDataSetChanged() {
+        // recreate all the children if the data set changes under us. We may want to do this more
+        // intelligently (ie just removing the views that should no longer exist)
+        mContent.removeAllViewsInLayout();
+        bind(mInfo);
+    }
+
+    public boolean acceptDrop(DragObject d) {
+        final ItemInfo item = (ItemInfo) d.dragInfo;
+        final int itemType = item.itemType;
+        return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+                    itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
+                    !isFull());
+    }
+
+    protected boolean findAndSetEmptyCells(ShortcutInfo item) {
+        int[] emptyCell = new int[2];
+        if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
+            item.cellX = emptyCell[0];
+            item.cellY = emptyCell[1];
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean createAndAddShortcut(ShortcutInfo item) {
+        final TextView textView =
+            (TextView) mInflater.inflate(R.layout.application, this, false);
+        textView.setCompoundDrawablesWithIntrinsicBounds(null,
+                new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
+        textView.setText(item.title);
+        textView.setTag(item);
+
+        textView.setOnClickListener(this);
+        textView.setOnLongClickListener(this);
+
+        // We need to check here to verify that the given item's location isn't already occupied
+        // by another item.
+        if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0
+                || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) {
+            // This shouldn't happen, log it. 
+            Log.e(TAG, "Folder order not properly persisted during bind");
+            if (!findAndSetEmptyCells(item)) {
+                return false;
+            }
+        }
+
+        CellLayout.LayoutParams lp =
+            new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
+        boolean insert = false;
+        textView.setOnKeyListener(new FolderKeyEventListener());
+        mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
+        return true;
+    }
+
+    public void onDragEnter(DragObject d) {
+        mPreviousTargetCell[0] = -1;
+        mPreviousTargetCell[1] = -1;
+        mOnExitAlarm.cancelAlarm();
+    }
+
+    OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
+        public void onAlarm(Alarm alarm) {
+            realTimeReorder(mEmptyCell, mTargetCell);
+        }
+    };
+
+    boolean readingOrderGreaterThan(int[] v1, int[] v2) {
+        if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private void realTimeReorder(int[] empty, int[] target) {
+        boolean wrap;
+        int startX;
+        int endX;
+        int startY;
+        int delay = 0;
+        float delayAmount = 30;
+        if (readingOrderGreaterThan(target, empty)) {
+            wrap = empty[0] >= mContent.getCountX() - 1;
+            startY = wrap ? empty[1] + 1 : empty[1];
+            for (int y = startY; y <= target[1]; y++) {
+                startX = y == empty[1] ? empty[0] + 1 : 0;
+                endX = y < target[1] ? mContent.getCountX() - 1 : target[0];
+                for (int x = startX; x <= endX; x++) {
+                    View v = mContent.getChildAt(x,y);
+                    if (mContent.animateChildToPosition(v, empty[0], empty[1],
+                            REORDER_ANIMATION_DURATION, delay, true, true)) {
+                        empty[0] = x;
+                        empty[1] = y;
+                        delay += delayAmount;
+                        delayAmount *= 0.9;
+                    }
+                }
+            }
+        } else {
+            wrap = empty[0] == 0;
+            startY = wrap ? empty[1] - 1 : empty[1];
+            for (int y = startY; y >= target[1]; y--) {
+                startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1;
+                endX = y > target[1] ? 0 : target[0];
+                for (int x = startX; x >= endX; x--) {
+                    View v = mContent.getChildAt(x,y);
+                    if (mContent.animateChildToPosition(v, empty[0], empty[1],
+                            REORDER_ANIMATION_DURATION, delay, true, true)) {
+                        empty[0] = x;
+                        empty[1] = y;
+                        delay += delayAmount;
+                        delayAmount *= 0.9;
+                    }
+                }
+            }
+        }
+    }
+
+    public void onDragOver(DragObject d) {
+        float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null);
+        mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell);
+
+        if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) {
+            mReorderAlarm.cancelAlarm();
+            mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
+            mReorderAlarm.setAlarm(150);
+            mPreviousTargetCell[0] = mTargetCell[0];
+            mPreviousTargetCell[1] = mTargetCell[1];
+        }
+    }
+
+    // This is used to compute the visual center of the dragView. The idea is that
+    // the visual center represents the user's interpretation of where the item is, and hence
+    // is the appropriate point to use when determining drop location.
+    private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
+            DragView dragView, float[] recycle) {
+        float res[];
+        if (recycle == null) {
+            res = new float[2];
+        } else {
+            res = recycle;
+        }
+
+        // These represent the visual top and left of drag view if a dragRect was provided.
+        // If a dragRect was not provided, then they correspond to the actual view left and
+        // top, as the dragRect is in that case taken to be the entire dragView.
+        // R.dimen.dragViewOffsetY.
+        int left = x - xOffset;
+        int top = y - yOffset;
+
+        // In order to find the visual center, we shift by half the dragRect
+        res[0] = left + dragView.getDragRegion().width() / 2;
+        res[1] = top + dragView.getDragRegion().height() / 2;
+
+        return res;
+    }
+
+    OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() {
+        public void onAlarm(Alarm alarm) {
+            completeDragExit();
+        }
+    };
+
+    public void completeDragExit() {
+        mLauncher.closeFolder();
+        mCurrentDragInfo = null;
+        mCurrentDragView = null;
+        mSuppressOnAdd = false;
+        mRearrangeOnClose = true;
+    }
+
+    public void onDragExit(DragObject d) {
+        // We only close the folder if this is a true drag exit, ie. not because a drop
+        // has occurred above the folder.
+        if (!d.dragComplete) {
+            mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener);
+            mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY);
+        }
+        mReorderAlarm.cancelAlarm();
+    }
+
+    public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
+            boolean success) {
+        if (success) {
+            if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) {
+                replaceFolderWithFinalItem();
+            }
+        } else {
+            // The drag failed, we need to return the item to the folder
+            mFolderIcon.onDrop(d);
+
+            // We're going to trigger a "closeFolder" which may occur before this item has
+            // been added back to the folder -- this could cause the folder to be deleted
+            if (mOnExitAlarm.alarmPending()) {
+                mSuppressFolderDeletion = true;
+            }
+        }
+
+        if (target != this) {
+            if (mOnExitAlarm.alarmPending()) {
+                mOnExitAlarm.cancelAlarm();
+                completeDragExit();
+            }
+        }
+        mDeleteFolderOnDropCompleted = false;
+        mDragInProgress = false;
+        mItemAddedBackToSelfViaIcon = false;
+        mCurrentDragInfo = null;
+        mCurrentDragView = null;
+        mSuppressOnAdd = false;
+
+        // Reordering may have occured, and we need to save the new item locations. We do this once
+        // at the end to prevent unnecessary database operations.
+        updateItemLocationsInDatabase();
+    }
+
+    @Override
+    public boolean supportsFlingToDelete() {
+        return true;
+    }
+
+    public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+        // Do nothing
+    }
+
+    @Override
+    public void onFlingToDeleteCompleted() {
+        // Do nothing
+    }
+
+    private void updateItemLocationsInDatabase() {
+        ArrayList<View> list = getItemsInReadingOrder();
+        for (int i = 0; i < list.size(); i++) {
+            View v = list.get(i);
+            ItemInfo info = (ItemInfo) v.getTag();
+            LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0,
+                        info.cellX, info.cellY);
+        }
+    }
+
+    public void notifyDrop() {
+        if (mDragInProgress) {
+            mItemAddedBackToSelfViaIcon = true;
+        }
+    }
+
+    public boolean isDropEnabled() {
+        return true;
+    }
+
+    public DropTarget getDropTargetDelegate(DragObject d) {
+        return null;
+    }
+
+    private void setupContentDimensions(int count) {
+        ArrayList<View> list = getItemsInReadingOrder();
+
+        int countX = mContent.getCountX();
+        int countY = mContent.getCountY();
+        boolean done = false;
+
+        while (!done) {
+            int oldCountX = countX;
+            int oldCountY = countY;
+            if (countX * countY < count) {
+                // Current grid is too small, expand it
+                if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) {
+                    countX++;
+                } else if (countY < mMaxCountY) {
+                    countY++;
+                }
+                if (countY == 0) countY++;
+            } else if ((countY - 1) * countX >= count && countY >= countX) {
+                countY = Math.max(0, countY - 1);
+            } else if ((countX - 1) * countY >= count) {
+                countX = Math.max(0, countX - 1);
+            }
+            done = countX == oldCountX && countY == oldCountY;
+        }
+        mContent.setGridSize(countX, countY);
+        arrangeChildren(list);
+    }
+
+    public boolean isFull() {
+        return getItemCount() >= mMaxNumItems;
+    }
+
+    private void centerAboutIcon() {
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+
+        int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+        int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight()
+                + mFolderNameHeight;
+        DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+
+        float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect);
+
+        int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2);
+        int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2);
+        int centeredLeft = centerX - width / 2;
+        int centeredTop = centerY - height / 2;
+
+        int currentPage = mLauncher.getWorkspace().getCurrentPage();
+        // In case the workspace is scrolling, we need to use the final scroll to compute
+        // the folders bounds.
+        mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage);
+        // We first fetch the currently visible CellLayoutChildren
+        CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage);
+        ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets();
+        Rect bounds = new Rect();
+        parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
+        // We reset the workspaces scroll
+        mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage);
+
+        // We need to bound the folder to the currently visible CellLayoutChildren
+        int left = Math.min(Math.max(bounds.left, centeredLeft),
+                bounds.left + bounds.width() - width);
+        int top = Math.min(Math.max(bounds.top, centeredTop),
+                bounds.top + bounds.height() - height);
+        // If the folder doesn't fit within the bounds, center it about the desired bounds
+        if (width >= bounds.width()) {
+            left = bounds.left + (bounds.width() - width) / 2;
+        }
+        if (height >= bounds.height()) {
+            top = bounds.top + (bounds.height() - height) / 2;
+        }
+
+        int folderPivotX = width / 2 + (centeredLeft - left);
+        int folderPivotY = height / 2 + (centeredTop - top);
+        setPivotX(folderPivotX);
+        setPivotY(folderPivotY);
+        mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
+                (1.0f * folderPivotX / width));
+        mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
+                (1.0f * folderPivotY / height));
+
+        lp.width = width;
+        lp.height = height;
+        lp.x = left;
+        lp.y = top;
+    }
+
+    float getPivotXForIconAnimation() {
+        return mFolderIconPivotX;
+    }
+    float getPivotYForIconAnimation() {
+        return mFolderIconPivotY;
+    }
+
+    private void setupContentForNumItems(int count) {
+        setupContentDimensions(count);
+
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+        if (lp == null) {
+            lp = new DragLayer.LayoutParams(0, 0);
+            lp.customPosition = true;
+            setLayoutParams(lp);
+        }
+        centerAboutIcon();
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+        int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight()
+                + mFolderNameHeight;
+
+        int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(),
+                MeasureSpec.EXACTLY);
+        int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(),
+                MeasureSpec.EXACTLY);
+        mContent.measure(contentWidthSpec, contentHeightSpec);
+
+        mFolderName.measure(contentWidthSpec,
+                MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
+        setMeasuredDimension(width, height);
+    }
+
+    private void arrangeChildren(ArrayList<View> list) {
+        int[] vacant = new int[2];
+        if (list == null) {
+            list = getItemsInReadingOrder();
+        }
+        mContent.removeAllViews();
+
+        for (int i = 0; i < list.size(); i++) {
+            View v = list.get(i);
+            mContent.getVacantCell(vacant, 1, 1);
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+            lp.cellX = vacant[0];
+            lp.cellY = vacant[1];
+            ItemInfo info = (ItemInfo) v.getTag();
+            if (info.cellX != vacant[0] || info.cellY != vacant[1]) {
+                info.cellX = vacant[0];
+                info.cellY = vacant[1];
+                LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
+                        info.cellX, info.cellY);
+            }
+            boolean insert = false;
+            mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
+        }
+        mItemsInvalidated = true;
+    }
+
+    public int getItemCount() {
+        return mContent.getShortcutsAndWidgets().getChildCount();
+    }
+
+    public View getItemAt(int index) {
+        return mContent.getShortcutsAndWidgets().getChildAt(index);
+    }
+
+    private void onCloseComplete() {
+        DragLayer parent = (DragLayer) getParent();
+        if (parent != null) {
+            parent.removeView(this);
+        }
+        mDragController.removeDropTarget((DropTarget) this);
+        clearFocus();
+        mFolderIcon.requestFocus();
+
+        if (mRearrangeOnClose) {
+            setupContentForNumItems(getItemCount());
+            mRearrangeOnClose = false;
+        }
+        if (getItemCount() <= 1) {
+            if (!mDragInProgress && !mSuppressFolderDeletion) {
+                replaceFolderWithFinalItem();
+            } else if (mDragInProgress) {
+                mDeleteFolderOnDropCompleted = true;
+            }
+        }
+        mSuppressFolderDeletion = false;
+    }
+
+    private void replaceFolderWithFinalItem() {
+        // Add the last remaining child to the workspace in place of the folder
+        Runnable onCompleteRunnable = new Runnable() {
+            @Override
+            public void run() {
+                CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen);
+
+               View child = null;
+                // Move the item from the folder to the workspace, in the position of the folder
+                if (getItemCount() == 1) {
+                    ShortcutInfo finalItem = mInfo.contents.get(0);
+                    child = mLauncher.createShortcut(R.layout.application, cellLayout,
+                            finalItem);
+                    LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
+                            mInfo.screen, mInfo.cellX, mInfo.cellY);
+                }
+                if (getItemCount() <= 1) {
+                    // Remove the folder
+                    LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
+                    cellLayout.removeView(mFolderIcon);
+                    if (mFolderIcon instanceof DropTarget) {
+                        mDragController.removeDropTarget((DropTarget) mFolderIcon);
+                    }
+                    mLauncher.removeFolder(mInfo);
+                }
+                // We add the child after removing the folder to prevent both from existing at
+                // the same time in the CellLayout.
+                if (child != null) {
+                    mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen,
+                            mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY);
+                }
+            }
+        };
+        View finalChild = getItemAt(0);
+        if (finalChild != null) {
+            mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable);
+        }
+        mDestroyed = true;
+    }
+
+    boolean isDestroyed() {
+        return mDestroyed;
+    }
+
+    // This method keeps track of the last item in the folder for the purposes
+    // of keyboard focus
+    private void updateTextViewFocus() {
+        View lastChild = getItemAt(getItemCount() - 1);
+        getItemAt(getItemCount() - 1);
+        if (lastChild != null) {
+            mFolderName.setNextFocusDownId(lastChild.getId());
+            mFolderName.setNextFocusRightId(lastChild.getId());
+            mFolderName.setNextFocusLeftId(lastChild.getId());
+            mFolderName.setNextFocusUpId(lastChild.getId());
+        }
+    }
+
+    public void onDrop(DragObject d) {
+        ShortcutInfo item;
+        if (d.dragInfo instanceof ApplicationInfo) {
+            // Came from all apps -- make a copy
+            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
+            item.spanX = 1;
+            item.spanY = 1;
+        } else {
+            item = (ShortcutInfo) d.dragInfo;
+        }
+        // Dragged from self onto self, currently this is the only path possible, however
+        // we keep this as a distinct code path.
+        if (item == mCurrentDragInfo) {
+            ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag();
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams();
+            si.cellX = lp.cellX = mEmptyCell[0];
+            si.cellX = lp.cellY = mEmptyCell[1];
+            mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true);
+            if (d.dragView.hasDrawn()) {
+                mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView);
+            } else {
+                d.deferDragViewCleanupPostAnimation = false;
+                mCurrentDragView.setVisibility(VISIBLE);
+            }
+            mItemsInvalidated = true;
+            setupContentDimensions(getItemCount());
+            mSuppressOnAdd = true;
+        }
+        mInfo.add(item);
+    }
+
+    public void onAdd(ShortcutInfo item) {
+        mItemsInvalidated = true;
+        // If the item was dropped onto this open folder, we have done the work associated
+        // with adding the item to the folder, as indicated by mSuppressOnAdd being set
+        if (mSuppressOnAdd) return;
+        if (!findAndSetEmptyCells(item)) {
+            // The current layout is full, can we expand it?
+            setupContentForNumItems(getItemCount() + 1);
+            findAndSetEmptyCells(item);
+        }
+        createAndAddShortcut(item);
+        LauncherModel.addOrMoveItemInDatabase(
+                mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+    }
+
+    public void onRemove(ShortcutInfo item) {
+        mItemsInvalidated = true;
+        // If this item is being dragged from this open folder, we have already handled
+        // the work associated with removing the item, so we don't have to do anything here.
+        if (item == mCurrentDragInfo) return;
+        View v = getViewForInfo(item);
+        mContent.removeView(v);
+        if (mState == STATE_ANIMATING) {
+            mRearrangeOnClose = true;
+        } else {
+            setupContentForNumItems(getItemCount());
+        }
+        if (getItemCount() <= 1) {
+            replaceFolderWithFinalItem();
+        }
+    }
+
+    private View getViewForInfo(ShortcutInfo item) {
+        for (int j = 0; j < mContent.getCountY(); j++) {
+            for (int i = 0; i < mContent.getCountX(); i++) {
+                View v = mContent.getChildAt(i, j);
+                if (v.getTag() == item) {
+                    return v;
+                }
+            }
+        }
+        return null;
+    }
+
+    public void onItemsChanged() {
+        updateTextViewFocus();
+    }
+
+    public void onTitleChanged(CharSequence title) {
+    }
+
+    public ArrayList<View> getItemsInReadingOrder() {
+        return getItemsInReadingOrder(true);
+    }
+
+    public ArrayList<View> getItemsInReadingOrder(boolean includeCurrentDragItem) {
+        if (mItemsInvalidated) {
+            mItemsInReadingOrder.clear();
+            for (int j = 0; j < mContent.getCountY(); j++) {
+                for (int i = 0; i < mContent.getCountX(); i++) {
+                    View v = mContent.getChildAt(i, j);
+                    if (v != null) {
+                        ShortcutInfo info = (ShortcutInfo) v.getTag();
+                        if (info != mCurrentDragInfo || includeCurrentDragItem) {
+                            mItemsInReadingOrder.add(v);
+                        }
+                    }
+                }
+            }
+            mItemsInvalidated = false;
+        }
+        return mItemsInReadingOrder;
+    }
+
+    public void getLocationInDragLayer(int[] loc) {
+        mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
+    }
+
+    public void onFocusChange(View v, boolean hasFocus) {
+        if (v == mFolderName && hasFocus) {
+            startEditingFolderName();
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FolderEditText.java b/FairphoneHome/src/org/fairphone/launcher/FolderEditText.java
new file mode 100644
index 0000000..670ba89
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FolderEditText.java
@@ -0,0 +1,51 @@
+/*
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+public class FolderEditText extends EditText {
+
+    private Folder mFolder;
+
+    public FolderEditText(Context context) {
+        super(context);
+    }
+
+    public FolderEditText(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FolderEditText(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setFolder(Folder folder) {
+        mFolder = folder;
+    }
+
+    @Override
+    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        // Catch the back button on the soft keyboard so that we can just close the activity
+        if (event.getKeyCode() == android.view.KeyEvent.KEYCODE_BACK) {
+            mFolder.doneEditingFolderName(true);
+        }
+        return super.onKeyPreIme(keyCode, event);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FolderIcon.java b/FairphoneHome/src/org/fairphone/launcher/FolderIcon.java
new file mode 100644
index 0000000..eeec8ea
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FolderIcon.java
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.DropTarget.DragObject;
+import org.fairphone.launcher.FolderInfo.FolderListener;
+
+/**
+ * An icon that can appear on in the workspace representing an {@link UserFolder}.
+ */
+public class FolderIcon extends LinearLayout implements FolderListener {
+    private Launcher mLauncher;
+    private Folder mFolder;
+    private FolderInfo mInfo;
+    private static boolean sStaticValuesDirty = true;
+
+    private CheckLongPressHelper mLongPressHelper;
+
+    // The number of icons to display in the
+    private static final int NUM_ITEMS_IN_PREVIEW = 3;
+    private static final int CONSUMPTION_ANIMATION_DURATION = 100;
+    private static final int DROP_IN_ANIMATION_DURATION = 400;
+    private static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
+    private static final int FINAL_ITEM_ANIMATION_DURATION = 200;
+
+    // The degree to which the inner ring grows when accepting drop
+    private static final float INNER_RING_GROWTH_FACTOR = 0.15f;
+
+    // The degree to which the outer ring is scaled in its natural state
+    private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
+
+    // The amount of vertical spread between items in the stack [0...1]
+    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.24f;
+
+    // The degree to which the item in the back of the stack is scaled [0...1]
+    // (0 means it's not scaled at all, 1 means it's scaled to nothing)
+    private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
+
+    public static Drawable sSharedFolderLeaveBehind = null;
+
+    private ImageView mPreviewBackground;
+    private BubbleTextView mFolderName;
+
+    FolderRingAnimator mFolderRingAnimator = null;
+
+    // These variables are all associated with the drawing of the preview; they are stored
+    // as member variables for shared usage and to avoid computation on each frame
+    private int mIntrinsicIconSize;
+    private float mBaselineIconScale;
+    private int mBaselineIconSize;
+    private int mAvailableSpaceInPreview;
+    private int mTotalWidth = -1;
+    private int mPreviewOffsetX;
+    private int mPreviewOffsetY;
+    private float mMaxPerspectiveShift;
+    boolean mAnimating = false;
+
+    private PreviewItemDrawingParams mParams = new PreviewItemDrawingParams(0, 0, 0, 0);
+    private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0);
+    private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>();
+
+    public FolderIcon(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public FolderIcon(Context context) {
+        super(context);
+        init();
+    }
+
+    private void init() {
+        mLongPressHelper = new CheckLongPressHelper(this);
+    }
+
+    public boolean isDropEnabled() {
+        final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
+        final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
+        final Workspace workspace = (Workspace) cellLayout.getParent();
+        return !workspace.isSmall();
+    }
+
+    static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
+            FolderInfo folderInfo, IconCache iconCache) {
+        @SuppressWarnings("all") // suppress dead code warning
+        final boolean error = INITIAL_ITEM_ANIMATION_DURATION >= DROP_IN_ANIMATION_DURATION;
+        if (error) {
+            throw new IllegalStateException("DROP_IN_ANIMATION_DURATION must be greater than " +
+                    "INITIAL_ITEM_ANIMATION_DURATION, as sequencing of adding first two items " +
+                    "is dependent on this");
+        }
+
+        FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
+
+        icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name);
+        icon.mFolderName.setText(folderInfo.title);
+        icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
+
+        icon.setTag(folderInfo);
+        icon.setOnClickListener(launcher);
+        icon.mInfo = folderInfo;
+        icon.mLauncher = launcher;
+        icon.setContentDescription(String.format(launcher.getString(R.string.folder_name_format),
+                folderInfo.title));
+        Folder folder = Folder.fromXml(launcher);
+        folder.setDragController(launcher.getDragController());
+        folder.setFolderIcon(icon);
+        folder.bind(folderInfo);
+        icon.mFolder = folder;
+
+        icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
+        folderInfo.addListener(icon);
+
+        return icon;
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        sStaticValuesDirty = true;
+        return super.onSaveInstanceState();
+    }
+
+    public static class FolderRingAnimator {
+        public int mCellX;
+        public int mCellY;
+        private CellLayout mCellLayout;
+        public float mOuterRingSize;
+        public float mInnerRingSize;
+        public FolderIcon mFolderIcon = null;
+        public Drawable mOuterRingDrawable = null;
+        public Drawable mInnerRingDrawable = null;
+        public static Drawable sSharedOuterRingDrawable = null;
+        public static Drawable sSharedInnerRingDrawable = null;
+        public static int sPreviewSize = -1;
+        public static int sPreviewPadding = -1;
+
+        private ValueAnimator mAcceptAnimator;
+        private ValueAnimator mNeutralAnimator;
+
+        public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
+            mFolderIcon = folderIcon;
+            Resources res = launcher.getResources();
+            mOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo);
+            mInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo);
+
+            // We need to reload the static values when configuration changes in case they are
+            // different in another configuration
+            if (sStaticValuesDirty) {
+                sPreviewSize = res.getDimensionPixelSize(R.dimen.folder_preview_size);
+                sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
+                sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo);
+                sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo);
+                sSharedFolderLeaveBehind = res.getDrawable(R.drawable.portal_ring_rest);
+                sStaticValuesDirty = false;
+            }
+        }
+
+        public void animateToAcceptState() {
+            if (mNeutralAnimator != null) {
+                mNeutralAnimator.cancel();
+            }
+            mAcceptAnimator = LauncherAnimUtils.ofFloat(0f, 1f);
+            mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+
+            final int previewSize = sPreviewSize;
+            mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    final float percent = (Float) animation.getAnimatedValue();
+                    mOuterRingSize = (1 + percent * OUTER_RING_GROWTH_FACTOR) * previewSize;
+                    mInnerRingSize = (1 + percent * INNER_RING_GROWTH_FACTOR) * previewSize;
+                    if (mCellLayout != null) {
+                        mCellLayout.invalidate();
+                    }
+                }
+            });
+            mAcceptAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    if (mFolderIcon != null) {
+                        mFolderIcon.mPreviewBackground.setVisibility(INVISIBLE);
+                    }
+                }
+            });
+            mAcceptAnimator.start();
+        }
+
+        public void animateToNaturalState() {
+            if (mAcceptAnimator != null) {
+                mAcceptAnimator.cancel();
+            }
+            mNeutralAnimator = LauncherAnimUtils.ofFloat(0f, 1f);
+            mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+
+            final int previewSize = sPreviewSize;
+            mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    final float percent = (Float) animation.getAnimatedValue();
+                    mOuterRingSize = (1 + (1 - percent) * OUTER_RING_GROWTH_FACTOR) * previewSize;
+                    mInnerRingSize = (1 + (1 - percent) * INNER_RING_GROWTH_FACTOR) * previewSize;
+                    if (mCellLayout != null) {
+                        mCellLayout.invalidate();
+                    }
+                }
+            });
+            mNeutralAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (mCellLayout != null) {
+                        mCellLayout.hideFolderAccept(FolderRingAnimator.this);
+                    }
+                    if (mFolderIcon != null) {
+                        mFolderIcon.mPreviewBackground.setVisibility(VISIBLE);
+                    }
+                }
+            });
+            mNeutralAnimator.start();
+        }
+
+        // Location is expressed in window coordinates
+        public void getCell(int[] loc) {
+            loc[0] = mCellX;
+            loc[1] = mCellY;
+        }
+
+        // Location is expressed in window coordinates
+        public void setCell(int x, int y) {
+            mCellX = x;
+            mCellY = y;
+        }
+
+        public void setCellLayout(CellLayout layout) {
+            mCellLayout = layout;
+        }
+
+        public float getOuterRingSize() {
+            return mOuterRingSize;
+        }
+
+        public float getInnerRingSize() {
+            return mInnerRingSize;
+        }
+    }
+
+    Folder getFolder() {
+        return mFolder;
+    }
+
+    FolderInfo getFolderInfo() {
+        return mInfo;
+    }
+
+    private boolean willAcceptItem(ItemInfo item) {
+        final int itemType = item.itemType;
+        return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+                itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
+                !mFolder.isFull() && item != mInfo && !mInfo.opened);
+    }
+
+    public boolean acceptDrop(Object dragInfo) {
+        final ItemInfo item = (ItemInfo) dragInfo;
+        return !mFolder.isDestroyed() && willAcceptItem(item);
+    }
+
+    public void addItem(ShortcutInfo item) {
+        mInfo.add(item);
+    }
+
+    public void onDragEnter(Object dragInfo) {
+        if (mFolder.isDestroyed() || !willAcceptItem((ItemInfo) dragInfo)) return;
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+        CellLayout layout = (CellLayout) getParent().getParent();
+        mFolderRingAnimator.setCell(lp.cellX, lp.cellY);
+        mFolderRingAnimator.setCellLayout(layout);
+        mFolderRingAnimator.animateToAcceptState();
+        layout.showFolderAccept(mFolderRingAnimator);
+    }
+
+    public void onDragOver(Object dragInfo) {
+    }
+
+    public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
+            final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
+            float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
+
+        // These correspond two the drawable and view that the icon was dropped _onto_
+        Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
+        computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
+                destView.getMeasuredWidth());
+
+        // This will animate the first item from it's position as an icon into its
+        // position as the first item in the preview
+        animateFirstItem(animateDrawable, INITIAL_ITEM_ANIMATION_DURATION, false, null);
+        addItem(destInfo);
+
+        // This will animate the dragView (srcView) into the new folder
+        onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable, null);
+    }
+
+    public void performDestroyAnimation(final View finalView, Runnable onCompleteRunnable) {
+        Drawable animateDrawable = ((TextView) finalView).getCompoundDrawables()[1];
+        computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), 
+                finalView.getMeasuredWidth());
+
+        // This will animate the first item from it's position as an icon into its
+        // position as the first item in the preview
+        animateFirstItem(animateDrawable, FINAL_ITEM_ANIMATION_DURATION, true,
+                onCompleteRunnable);
+    }
+
+    public void onDragExit(Object dragInfo) {
+        onDragExit();
+    }
+
+    public void onDragExit() {
+        mFolderRingAnimator.animateToNaturalState();
+    }
+
+    private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
+            float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable,
+            DragObject d) {
+        item.cellX = -1;
+        item.cellY = -1;
+
+        // Typically, the animateView corresponds to the DragView; however, if this is being done
+        // after a configuration activity (ie. for a Shortcut being dragged from AllApps) we
+        // will not have a view to animate
+        if (animateView != null) {
+            DragLayer dragLayer = mLauncher.getDragLayer();
+            Rect from = new Rect();
+            dragLayer.getViewRectRelativeToSelf(animateView, from);
+            Rect to = finalRect;
+            if (to == null) {
+                to = new Rect();
+                Workspace workspace = mLauncher.getWorkspace();
+                // Set cellLayout and this to it's final state to compute final animation locations
+                workspace.setFinalTransitionTransform((CellLayout) getParent().getParent());
+                float scaleX = getScaleX();
+                float scaleY = getScaleY();
+                setScaleX(1.0f);
+                setScaleY(1.0f);
+                scaleRelativeToDragLayer = dragLayer.getDescendantRectRelativeToSelf(this, to);
+                // Finished computing final animation locations, restore current state
+                setScaleX(scaleX);
+                setScaleY(scaleY);
+                workspace.resetTransitionTransform((CellLayout) getParent().getParent());
+            }
+
+            int[] center = new int[2];
+            float scale = getLocalCenterForIndex(index, center);
+            center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]);
+            center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
+
+            to.offset(center[0] - animateView.getMeasuredWidth() / 2,
+                    center[1] - animateView.getMeasuredHeight() / 2);
+
+            float finalAlpha = index < NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f;
+
+            float finalScale = scale * scaleRelativeToDragLayer;
+            dragLayer.animateView(animateView, from, to, finalAlpha,
+                    1, 1, finalScale, finalScale, DROP_IN_ANIMATION_DURATION,
+                    new DecelerateInterpolator(2), new AccelerateInterpolator(2),
+                    postAnimationRunnable, DragLayer.ANIMATION_END_DISAPPEAR, null);
+            addItem(item);
+            mHiddenItems.add(item);
+            postDelayed(new Runnable() {
+                public void run() {
+                    mHiddenItems.remove(item);
+                    invalidate();
+                }
+            }, DROP_IN_ANIMATION_DURATION);
+        } else {
+            addItem(item);
+        }
+    }
+
+    public void onDrop(DragObject d) {
+        ShortcutInfo item;
+        if (d.dragInfo instanceof ApplicationInfo) {
+            // Came from all apps -- make a copy
+            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
+        } else {
+            item = (ShortcutInfo) d.dragInfo;
+        }
+        mFolder.notifyDrop();
+        onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable, d);
+    }
+
+    public DropTarget getDropTargetDelegate(DragObject d) {
+        return null;
+    }
+
+    private void computePreviewDrawingParams(int drawableSize, int totalSize) {
+        if (mIntrinsicIconSize != drawableSize || mTotalWidth != totalSize) {
+            mIntrinsicIconSize = drawableSize;
+            mTotalWidth = totalSize;
+
+            final int previewSize = FolderRingAnimator.sPreviewSize;
+            final int previewPadding = FolderRingAnimator.sPreviewPadding;
+
+            mAvailableSpaceInPreview = (previewSize - 2 * previewPadding);
+            // cos(45) = 0.707  + ~= 0.1) = 0.8f
+            int adjustedAvailableSpace = (int) ((mAvailableSpaceInPreview / 2) * (1 + 0.8f));
+
+            int unscaledHeight = (int) (mIntrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR));
+            mBaselineIconScale = (1.0f * adjustedAvailableSpace / unscaledHeight);
+
+            mBaselineIconSize = (int) (mIntrinsicIconSize * mBaselineIconScale);
+            mMaxPerspectiveShift = mBaselineIconSize * PERSPECTIVE_SHIFT_FACTOR;
+
+            mPreviewOffsetX = (mTotalWidth - mAvailableSpaceInPreview) / 2;
+            mPreviewOffsetY = previewPadding;
+        }
+    }
+
+    private void computePreviewDrawingParams(Drawable d) {
+        computePreviewDrawingParams(d.getIntrinsicWidth(), getMeasuredWidth());
+    }
+
+    class PreviewItemDrawingParams {
+        PreviewItemDrawingParams(float transX, float transY, float scale, int overlayAlpha) {
+            this.transX = transX;
+            this.transY = transY;
+            this.scale = scale;
+            this.overlayAlpha = overlayAlpha;
+        }
+        float transX;
+        float transY;
+        float scale;
+        int overlayAlpha;
+        Drawable drawable;
+    }
+
+    private float getLocalCenterForIndex(int index, int[] center) {
+        mParams = computePreviewItemDrawingParams(Math.min(NUM_ITEMS_IN_PREVIEW, index), mParams);
+
+        mParams.transX += mPreviewOffsetX;
+        mParams.transY += mPreviewOffsetY;
+        float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2;
+        float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2;
+
+        center[0] = (int) Math.round(offsetX);
+        center[1] = (int) Math.round(offsetY);
+        return mParams.scale;
+    }
+
+    private PreviewItemDrawingParams computePreviewItemDrawingParams(int index,
+            PreviewItemDrawingParams params) {
+        index = NUM_ITEMS_IN_PREVIEW - index - 1;
+        float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1);
+        float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
+
+        float offset = (1 - r) * mMaxPerspectiveShift;
+        float scaledSize = scale * mBaselineIconSize;
+        float scaleOffsetCorrection = (1 - scale) * mBaselineIconSize;
+
+        // We want to imagine our coordinates from the bottom left, growing up and to the
+        // right. This is natural for the x-axis, but for the y-axis, we have to invert things.
+        float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
+        float transX = offset + scaleOffsetCorrection;
+        float totalScale = mBaselineIconScale * scale;
+        final int overlayAlpha = (int) (80 * (1 - r));
+
+        if (params == null) {
+            params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
+        } else {
+            params.transX = transX;
+            params.transY = transY;
+            params.scale = totalScale;
+            params.overlayAlpha = overlayAlpha;
+        }
+        return params;
+    }
+
+    private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params) {
+        canvas.save();
+        canvas.translate(params.transX + mPreviewOffsetX, params.transY + mPreviewOffsetY);
+        canvas.scale(params.scale, params.scale);
+        Drawable d = params.drawable;
+
+        if (d != null) {
+            d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
+            d.setFilterBitmap(true);
+            d.setColorFilter(Color.argb(params.overlayAlpha, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);
+            d.draw(canvas);
+            d.clearColorFilter();
+            d.setFilterBitmap(false);
+        }
+        canvas.restore();
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+
+        if (mFolder == null) return;
+        if (mFolder.getItemCount() == 0 && !mAnimating) return;
+
+        ArrayList<View> items = mFolder.getItemsInReadingOrder(false);
+        Drawable d;
+        TextView v;
+
+        // Update our drawing parameters if necessary
+        if (mAnimating) {
+            computePreviewDrawingParams(mAnimParams.drawable);
+        } else {
+            v = (TextView) items.get(0);
+            d = v.getCompoundDrawables()[1];
+            computePreviewDrawingParams(d);
+        }
+
+        int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW);
+        if (!mAnimating) {
+            for (int i = nItemsInPreview - 1; i >= 0; i--) {
+                v = (TextView) items.get(i);
+                if (!mHiddenItems.contains(v.getTag())) {
+                    d = v.getCompoundDrawables()[1];
+                    mParams = computePreviewItemDrawingParams(i, mParams);
+                    mParams.drawable = d;
+                    drawPreviewItem(canvas, mParams);
+                }
+            }
+        } else {
+            drawPreviewItem(canvas, mAnimParams);
+        }
+    }
+
+    private void animateFirstItem(final Drawable d, int duration, final boolean reverse,
+            final Runnable onCompleteRunnable) {
+        final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null);
+
+        final float scale0 = 1.0f;
+        final float transX0 = (mAvailableSpaceInPreview - d.getIntrinsicWidth()) / 2;
+        final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2;
+        mAnimParams.drawable = d;
+
+        ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1.0f);
+        va.addUpdateListener(new AnimatorUpdateListener(){
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float progress = (Float) animation.getAnimatedValue();
+                if (reverse) {
+                    progress = 1 - progress;
+                    mPreviewBackground.setAlpha(progress);
+                }
+
+                mAnimParams.transX = transX0 + progress * (finalParams.transX - transX0);
+                mAnimParams.transY = transY0 + progress * (finalParams.transY - transY0);
+                mAnimParams.scale = scale0 + progress * (finalParams.scale - scale0);
+                invalidate();
+            }
+        });
+        va.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mAnimating = true;
+            }
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimating = false;
+                if (onCompleteRunnable != null) {
+                    onCompleteRunnable.run();
+                }
+            }
+        });
+        va.setDuration(duration);
+        va.start();
+    }
+
+    public void setTextVisible(boolean visible) {
+        if (visible) {
+            mFolderName.setVisibility(VISIBLE);
+        } else {
+            mFolderName.setVisibility(INVISIBLE);
+        }
+    }
+
+    public boolean getTextVisible() {
+        return mFolderName.getVisibility() == VISIBLE;
+    }
+
+    public void onItemsChanged() {
+        invalidate();
+        requestLayout();
+    }
+
+    public void onAdd(ShortcutInfo item) {
+        invalidate();
+        requestLayout();
+    }
+
+    public void onRemove(ShortcutInfo item) {
+        invalidate();
+        requestLayout();
+    }
+
+    public void onTitleChanged(CharSequence title) {
+        mFolderName.setText(title.toString());
+        setContentDescription(String.format(getContext().getString(R.string.folder_name_format),
+                title));
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // Call the superclass onTouchEvent first, because sometimes it changes the state to
+        // isPressed() on an ACTION_UP
+        boolean result = super.onTouchEvent(event);
+
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mLongPressHelper.postCheckForLongPress();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                mLongPressHelper.cancelLongPress();
+                break;
+        }
+        return result;
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        mLongPressHelper.cancelLongPress();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/FolderInfo.java b/FairphoneHome/src/org/fairphone/launcher/FolderInfo.java
new file mode 100644
index 0000000..6f85043
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/FolderInfo.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.ArrayList;
+
+import android.content.ContentValues;
+
+/**
+ * Represents a folder containing shortcuts or apps.
+ */
+class FolderInfo extends ItemInfo {
+
+    /**
+     * Whether this folder has been opened
+     */
+    boolean opened;
+
+    /**
+     * The apps and shortcuts
+     */
+    ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
+
+    ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
+
+    FolderInfo() {
+        itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
+    }
+
+    /**
+     * Add an app or shortcut
+     *
+     * @param item
+     */
+    public void add(ShortcutInfo item) {
+        contents.add(item);
+        for (int i = 0; i < listeners.size(); i++) {
+            listeners.get(i).onAdd(item);
+        }
+        itemsChanged();
+    }
+
+    /**
+     * Remove an app or shortcut. Does not change the DB.
+     *
+     * @param item
+     */
+    public void remove(ShortcutInfo item) {
+        contents.remove(item);
+        for (int i = 0; i < listeners.size(); i++) {
+            listeners.get(i).onRemove(item);
+        }
+        itemsChanged();
+    }
+
+    public void setTitle(CharSequence title) {
+        this.title = title;
+        for (int i = 0; i < listeners.size(); i++) {
+            listeners.get(i).onTitleChanged(title);
+        }
+    }
+
+    @Override
+    void onAddToDatabase(ContentValues values) {
+        super.onAddToDatabase(values);
+        values.put(LauncherSettings.Favorites.TITLE, title.toString());
+    }
+
+    void addListener(FolderListener listener) {
+        listeners.add(listener);
+    }
+
+    void removeListener(FolderListener listener) {
+        if (listeners.contains(listener)) {
+            listeners.remove(listener);
+        }
+    }
+
+    void itemsChanged() {
+        for (int i = 0; i < listeners.size(); i++) {
+            listeners.get(i).onItemsChanged();
+        }
+    }
+
+    @Override
+    void unbind() {
+        super.unbind();
+        listeners.clear();
+    }
+
+    interface FolderListener {
+        public void onAdd(ShortcutInfo item);
+        public void onRemove(ShortcutInfo item);
+        public void onTitleChanged(CharSequence title);
+        public void onItemsChanged();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/HandleView.java b/FairphoneHome/src/org/fairphone/launcher/HandleView.java
new file mode 100644
index 0000000..1d32c21
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/HandleView.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+
+import org.fairphone.launcher.R;
+
+public class HandleView extends ImageView {
+    private static final int ORIENTATION_HORIZONTAL = 1;
+
+    private Launcher mLauncher;
+    private int mOrientation = ORIENTATION_HORIZONTAL;
+
+    public HandleView(Context context) {
+        super(context);
+    }
+
+    public HandleView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public HandleView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HandleView, defStyle, 0);
+        mOrientation = a.getInt(R.styleable.HandleView_direction, ORIENTATION_HORIZONTAL);
+        a.recycle();
+
+        setContentDescription(context.getString(R.string.all_apps_button_label));
+    }
+
+    @Override
+    public View focusSearch(int direction) {
+        View newFocus = super.focusSearch(direction);
+        if (newFocus == null && !mLauncher.isAllAppsVisible()) {
+            final Workspace workspace = mLauncher.getWorkspace();
+            workspace.dispatchUnhandledMove(null, direction);
+            return (mOrientation == ORIENTATION_HORIZONTAL && direction == FOCUS_DOWN) ?
+                    this : workspace;
+        }
+        return newFocus;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) {
+            return false;
+        }
+        return super.onTouchEvent(ev);
+    }
+
+    void setLauncher(Launcher launcher) {
+        mLauncher = launcher;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/HideFromAccessibilityHelper.java b/FairphoneHome/src/org/fairphone/launcher/HideFromAccessibilityHelper.java
new file mode 100644
index 0000000..bbc40eb
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/HideFromAccessibilityHelper.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.OnHierarchyChangeListener;
+
+import java.util.HashMap;
+
+public class HideFromAccessibilityHelper implements OnHierarchyChangeListener {
+    private HashMap<View, Integer> mPreviousValues;
+    boolean mHide;
+    boolean mOnlyAllApps;
+
+    public HideFromAccessibilityHelper() {
+        mPreviousValues = new HashMap<View, Integer>();
+        mHide = false;
+    }
+
+    public void setImportantForAccessibilityToNo(View v, boolean onlyAllApps) {
+        mOnlyAllApps = onlyAllApps;
+        setImportantForAccessibilityToNoHelper(v);
+        mHide = true;
+    }
+
+    private void setImportantForAccessibilityToNoHelper(View v) {
+        mPreviousValues.put(v, v.getImportantForAccessibility());
+        v.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+
+        // Call method on children recursively
+        if (v instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) v;
+            vg.setOnHierarchyChangeListener(this);
+            for (int i = 0; i < vg.getChildCount(); i++) {
+                View child = vg.getChildAt(i);
+
+                if (includeView(child)) {
+                    setImportantForAccessibilityToNoHelper(child);
+                }
+            }
+        }
+    }
+
+    public void restoreImportantForAccessibility(View v) {
+        if (mHide) {
+            restoreImportantForAccessibilityHelper(v);
+        }
+        mHide = false;
+    }
+
+    private void restoreImportantForAccessibilityHelper(View v) {
+        v.setImportantForAccessibility(mPreviousValues.get(v));
+        mPreviousValues.remove(v);
+
+        // Call method on children recursively
+        if (v instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) v;
+
+            // We assume if a class implements OnHierarchyChangeListener, it listens
+            // to changes to any of its children (happens to be the case in Launcher)
+            if (vg instanceof OnHierarchyChangeListener) {
+                vg.setOnHierarchyChangeListener((OnHierarchyChangeListener) vg);
+            } else {
+                vg.setOnHierarchyChangeListener(null);
+            }
+            for (int i = 0; i < vg.getChildCount(); i++) {
+                View child = vg.getChildAt(i);
+                if (includeView(child)) {
+                    restoreImportantForAccessibilityHelper(child);
+                }
+            }
+        }
+    }
+
+    public void onChildViewAdded(View parent, View child) {
+        if (mHide && includeView(child)) {
+            setImportantForAccessibilityToNoHelper(child);
+        }
+    }
+
+    public void onChildViewRemoved(View parent, View child) {
+        if (mHide && includeView(child)) {
+            restoreImportantForAccessibilityHelper(child);
+        }
+    }
+
+    private boolean includeView(View v) {
+        return !hasAncestorOfType(v, Cling.class) &&
+                (!mOnlyAllApps || hasAncestorOfType(v, AppsCustomizeTabHost.class));
+    }
+
+    private boolean hasAncestorOfType(View v, Class c) {
+        return v != null &&
+                (v.getClass().equals(c) ||
+                 (v.getParent() instanceof ViewGroup &&
+                  hasAncestorOfType((ViewGroup) v.getParent(), c)));
+    }
+}
\ No newline at end of file
diff --git a/FairphoneHome/src/org/fairphone/launcher/HolographicImageView.java b/FairphoneHome/src/org/fairphone/launcher/HolographicImageView.java
new file mode 100644
index 0000000..583d2f2
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/HolographicImageView.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+public class HolographicImageView extends ImageView {
+
+    private final HolographicViewHelper mHolographicHelper;
+
+    public HolographicImageView(Context context) {
+        this(context, null);
+    }
+
+    public HolographicImageView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public HolographicImageView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        mHolographicHelper = new HolographicViewHelper(context);
+    }
+
+    void invalidatePressedFocusedStates() {
+        mHolographicHelper.invalidatePressedFocusedStates(this);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        // One time call to generate the pressed/focused state -- must be called after
+        // measure/layout
+        mHolographicHelper.generatePressedFocusedStates(this);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/HolographicLinearLayout.java b/FairphoneHome/src/org/fairphone/launcher/HolographicLinearLayout.java
new file mode 100644
index 0000000..4abf1e9
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/HolographicLinearLayout.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import org.fairphone.launcher.R;
+
+public class HolographicLinearLayout extends LinearLayout {
+
+    private final HolographicViewHelper mHolographicHelper;
+    private ImageView mImageView;
+    private int mImageViewId;
+
+    public HolographicLinearLayout(Context context) {
+        this(context, null);
+    }
+
+    public HolographicLinearLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public HolographicLinearLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HolographicLinearLayout,
+                defStyle, 0);
+        mImageViewId = a.getResourceId(R.styleable.HolographicLinearLayout_sourceImageViewId, -1);
+        a.recycle();
+
+        setWillNotDraw(false);
+        mHolographicHelper = new HolographicViewHelper(context);
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+
+        if (mImageView != null) {
+            Drawable d = mImageView.getDrawable();
+            if (d instanceof StateListDrawable) {
+                StateListDrawable sld = (StateListDrawable) d;
+                sld.setState(getDrawableState());
+            }
+        }
+    }
+
+    void invalidatePressedFocusedStates() {
+        mHolographicHelper.invalidatePressedFocusedStates(mImageView);
+        invalidate();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        // One time call to generate the pressed/focused state -- must be called after
+        // measure/layout
+        if (mImageView == null) {
+            mImageView = (ImageView) findViewById(mImageViewId);
+        }
+        mHolographicHelper.generatePressedFocusedStates(mImageView);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/HolographicOutlineHelper.java b/FairphoneHome/src/org/fairphone/launcher/HolographicOutlineHelper.java
new file mode 100644
index 0000000..37dda31
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/HolographicOutlineHelper.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+
+public class HolographicOutlineHelper {
+    private final Paint mHolographicPaint = new Paint();
+    private final Paint mBlurPaint = new Paint();
+    private final Paint mErasePaint = new Paint();
+
+    public static final int MAX_OUTER_BLUR_RADIUS;
+    public static final int MIN_OUTER_BLUR_RADIUS;
+
+    private static final BlurMaskFilter sExtraThickOuterBlurMaskFilter;
+    private static final BlurMaskFilter sThickOuterBlurMaskFilter;
+    private static final BlurMaskFilter sMediumOuterBlurMaskFilter;
+    private static final BlurMaskFilter sThinOuterBlurMaskFilter;
+    private static final BlurMaskFilter sThickInnerBlurMaskFilter;
+    private static final BlurMaskFilter sExtraThickInnerBlurMaskFilter;
+    private static final BlurMaskFilter sMediumInnerBlurMaskFilter;
+
+    private static final int THICK = 0;
+    private static final int MEDIUM = 1;
+    private static final int EXTRA_THICK = 2;
+
+    static {
+        final float scale = LauncherApplication.getScreenDensity();
+
+        MIN_OUTER_BLUR_RADIUS = (int) (scale * 1.0f);
+        MAX_OUTER_BLUR_RADIUS = (int) (scale * 12.0f);
+
+        sExtraThickOuterBlurMaskFilter = new BlurMaskFilter(scale * 12.0f, BlurMaskFilter.Blur.OUTER);
+        sThickOuterBlurMaskFilter = new BlurMaskFilter(scale * 6.0f, BlurMaskFilter.Blur.OUTER);
+        sMediumOuterBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.OUTER);
+        sThinOuterBlurMaskFilter = new BlurMaskFilter(scale * 1.0f, BlurMaskFilter.Blur.OUTER);
+        sExtraThickInnerBlurMaskFilter = new BlurMaskFilter(scale * 6.0f, BlurMaskFilter.Blur.NORMAL);
+        sThickInnerBlurMaskFilter = new BlurMaskFilter(scale * 4.0f, BlurMaskFilter.Blur.NORMAL);
+        sMediumInnerBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.NORMAL);
+    }
+
+    HolographicOutlineHelper() {
+        mHolographicPaint.setFilterBitmap(true);
+        mHolographicPaint.setAntiAlias(true);
+        mBlurPaint.setFilterBitmap(true);
+        mBlurPaint.setAntiAlias(true);
+        mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+        mErasePaint.setFilterBitmap(true);
+        mErasePaint.setAntiAlias(true);
+    }
+
+    /**
+     * Returns the interpolated holographic highlight alpha for the effect we want when scrolling
+     * pages.
+     */
+    public static float highlightAlphaInterpolator(float r) {
+        float maxAlpha = 0.6f;
+        return (float) Math.pow(maxAlpha * (1.0f - r), 1.5f);
+    }
+
+    /**
+     * Returns the interpolated view alpha for the effect we want when scrolling pages.
+     */
+    public static float viewAlphaInterpolator(float r) {
+        final float pivot = 0.95f;
+        if (r < pivot) {
+            return (float) Math.pow(r / pivot, 1.5f);
+        } else {
+            return 1.0f;
+        }
+    }
+
+    /**
+     * Applies a more expensive and accurate outline to whatever is currently drawn in a specified
+     * bitmap.
+     */
+    void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
+            int outlineColor, int thickness) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, true,
+                thickness);
+    }
+    void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
+            int outlineColor, boolean clipAlpha, int thickness) {
+
+        // We start by removing most of the alpha channel so as to ignore shadows, and
+        // other types of partial transparency when defining the shape of the object
+        if (clipAlpha) {
+            int[] srcBuffer = new int[srcDst.getWidth() * srcDst.getHeight()];
+            srcDst.getPixels(srcBuffer,
+                    0, srcDst.getWidth(), 0, 0, srcDst.getWidth(), srcDst.getHeight());
+            for (int i = 0; i < srcBuffer.length; i++) {
+                final int alpha = srcBuffer[i] >>> 24;
+                if (alpha < 188) {
+                    srcBuffer[i] = 0;
+                }
+            }
+            srcDst.setPixels(srcBuffer,
+                    0, srcDst.getWidth(), 0, 0, srcDst.getWidth(), srcDst.getHeight());
+        }
+        Bitmap glowShape = srcDst.extractAlpha();
+
+        // calculate the outer blur first
+        BlurMaskFilter outerBlurMaskFilter;
+        switch (thickness) {
+            case EXTRA_THICK:
+                outerBlurMaskFilter = sExtraThickOuterBlurMaskFilter;
+                break;
+            case THICK:
+                outerBlurMaskFilter = sThickOuterBlurMaskFilter;
+                break;
+            case MEDIUM:
+                outerBlurMaskFilter = sMediumOuterBlurMaskFilter;
+                break;
+            default:
+                throw new RuntimeException("Invalid blur thickness");
+        }
+        mBlurPaint.setMaskFilter(outerBlurMaskFilter);
+        int[] outerBlurOffset = new int[2];
+        Bitmap thickOuterBlur = glowShape.extractAlpha(mBlurPaint, outerBlurOffset);
+        if (thickness == EXTRA_THICK) {
+            mBlurPaint.setMaskFilter(sMediumOuterBlurMaskFilter);
+        } else {
+            mBlurPaint.setMaskFilter(sThinOuterBlurMaskFilter);
+        }
+
+        int[] brightOutlineOffset = new int[2];
+        Bitmap brightOutline = glowShape.extractAlpha(mBlurPaint, brightOutlineOffset);
+
+        // calculate the inner blur
+        srcDstCanvas.setBitmap(glowShape);
+        srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
+        BlurMaskFilter innerBlurMaskFilter;
+        switch (thickness) {
+            case EXTRA_THICK:
+                innerBlurMaskFilter = sExtraThickInnerBlurMaskFilter;
+                break;
+            case THICK:
+                innerBlurMaskFilter = sThickInnerBlurMaskFilter;
+                break;
+            case MEDIUM:
+                innerBlurMaskFilter = sMediumInnerBlurMaskFilter;
+                break;
+            default:
+                throw new RuntimeException("Invalid blur thickness");
+        }
+        mBlurPaint.setMaskFilter(innerBlurMaskFilter);
+        int[] thickInnerBlurOffset = new int[2];
+        Bitmap thickInnerBlur = glowShape.extractAlpha(mBlurPaint, thickInnerBlurOffset);
+
+        // mask out the inner blur
+        srcDstCanvas.setBitmap(thickInnerBlur);
+        srcDstCanvas.drawBitmap(glowShape, -thickInnerBlurOffset[0],
+                -thickInnerBlurOffset[1], mErasePaint);
+        srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(),
+                mErasePaint);
+        srcDstCanvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1],
+                mErasePaint);
+
+        // draw the inner and outer blur
+        srcDstCanvas.setBitmap(srcDst);
+        srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
+        mHolographicPaint.setColor(color);
+        srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
+                mHolographicPaint);
+        srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1],
+                mHolographicPaint);
+
+        // draw the bright outline
+        mHolographicPaint.setColor(outlineColor);
+        srcDstCanvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1],
+                mHolographicPaint);
+
+        // cleanup
+        srcDstCanvas.setBitmap(null);
+        brightOutline.recycle();
+        thickOuterBlur.recycle();
+        thickInnerBlur.recycle();
+        glowShape.recycle();
+    }
+
+    void applyExtraThickExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
+            int outlineColor) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, EXTRA_THICK);
+    }
+
+    void applyThickExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
+            int outlineColor) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, THICK);
+    }
+
+    void applyMediumExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
+            int outlineColor, boolean clipAlpha) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, clipAlpha,
+                MEDIUM);
+    }
+
+    void applyMediumExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas, int color,
+            int outlineColor) {
+        applyExpensiveOutlineWithBlur(srcDst, srcDstCanvas, color, outlineColor, MEDIUM);
+    }
+
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/HolographicViewHelper.java b/FairphoneHome/src/org/fairphone/launcher/HolographicViewHelper.java
new file mode 100644
index 0000000..c6cb33a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/HolographicViewHelper.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.widget.ImageView;
+
+public class HolographicViewHelper {
+
+    private final Canvas mTempCanvas = new Canvas();
+
+    private boolean mStatesUpdated;
+    private int mHighlightColor;
+
+    public HolographicViewHelper(Context context) {
+        Resources res = context.getResources();
+        mHighlightColor = res.getColor(android.R.color.holo_blue_light);
+    }
+
+    /**
+     * Generate the pressed/focused states if necessary.
+     */
+    void generatePressedFocusedStates(ImageView v) {
+        if (!mStatesUpdated && v != null) {
+            mStatesUpdated = true;
+            Bitmap original = createOriginalImage(v, mTempCanvas);
+            Bitmap outline = createPressImage(v, mTempCanvas);
+            FastBitmapDrawable originalD = new FastBitmapDrawable(original);
+            FastBitmapDrawable outlineD = new FastBitmapDrawable(outline);
+
+            StateListDrawable states = new StateListDrawable();
+            states.addState(new int[] {android.R.attr.state_pressed}, outlineD);
+            states.addState(new int[] {android.R.attr.state_focused}, outlineD);
+            states.addState(new int[] {}, originalD);
+            v.setImageDrawable(states);
+        }
+    }
+
+    /**
+     * Invalidates the pressed/focused states.
+     */
+    void invalidatePressedFocusedStates(ImageView v) {
+        mStatesUpdated = false;
+        if (v != null) {
+            v.invalidate();
+        }
+    }
+
+    /**
+     * Creates a copy of the original image.
+     */
+    private Bitmap createOriginalImage(ImageView v, Canvas canvas) {
+        final Drawable d = v.getDrawable();
+        final Bitmap b = Bitmap.createBitmap(
+                d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
+        canvas.setBitmap(b);
+        canvas.save();
+            d.draw(canvas);
+        canvas.restore();
+        canvas.setBitmap(null);
+
+        return b;
+    }
+
+    /**
+     * Creates a new press state image which is the old image with a blue overlay.
+     * Responsibility for the bitmap is transferred to the caller.
+     */
+    private Bitmap createPressImage(ImageView v, Canvas canvas) {
+        final Drawable d = v.getDrawable();
+        final Bitmap b = Bitmap.createBitmap(
+                d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
+        canvas.setBitmap(b);
+        canvas.save();
+            d.draw(canvas);
+        canvas.restore();
+        canvas.drawColor(mHighlightColor, PorterDuff.Mode.SRC_IN);
+        canvas.setBitmap(null);
+
+        return b;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Hotseat.java b/FairphoneHome/src/org/fairphone/launcher/Hotseat.java
new file mode 100644
index 0000000..2899a0e
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Hotseat.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import org.fairphone.launcher.R;
+
+public class Hotseat extends FrameLayout {
+    @SuppressWarnings("unused")
+    private static final String TAG = "Hotseat";
+
+    private Launcher mLauncher;
+    private CellLayout mContent;
+
+    private int mCellCountX;
+    private int mCellCountY;
+    private int mAllAppsButtonRank;
+
+    private boolean mTransposeLayoutWithOrientation;
+    private boolean mIsLandscape;
+
+    public Hotseat(Context context) {
+        this(context, null);
+    }
+
+    public Hotseat(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public Hotseat(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.Hotseat, defStyle, 0);
+        Resources r = context.getResources();
+        mCellCountX = a.getInt(R.styleable.Hotseat_cellCountX, -1);
+        mCellCountY = a.getInt(R.styleable.Hotseat_cellCountY, -1);
+        mAllAppsButtonRank = r.getInteger(R.integer.hotseat_all_apps_index);
+        mTransposeLayoutWithOrientation = 
+                r.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
+        mIsLandscape = context.getResources().getConfiguration().orientation ==
+            Configuration.ORIENTATION_LANDSCAPE;
+    }
+
+    public void setup(Launcher launcher) {
+        mLauncher = launcher;
+        setOnKeyListener(new HotseatIconKeyEventListener());
+    }
+
+    CellLayout getLayout() {
+        return mContent;
+    }
+  
+    private boolean hasVerticalHotseat() {
+        return (mIsLandscape && mTransposeLayoutWithOrientation);
+    }
+
+    /* Get the orientation invariant order of the item in the hotseat for persistence. */
+    int getOrderInHotseat(int x, int y) {
+        return hasVerticalHotseat() ? (mContent.getCountY() - y - 1) : x;
+    }
+    /* Get the orientation specific coordinates given an invariant order in the hotseat. */
+    int getCellXFromOrder(int rank) {
+        return hasVerticalHotseat() ? 0 : rank;
+    }
+    int getCellYFromOrder(int rank) {
+        return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0;
+    }
+    public boolean isAllAppsButtonRank(int rank) {
+        return rank == mAllAppsButtonRank;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        if (mCellCountX < 0) mCellCountX = LauncherModel.getCellCountX();
+        if (mCellCountY < 0) mCellCountY = LauncherModel.getCellCountY();
+        mContent = (CellLayout) findViewById(R.id.layout);
+        mContent.setGridSize(mCellCountX, mCellCountY);
+        mContent.setIsHotseat(true);
+
+        resetLayout();
+    }
+
+    void resetLayout() {
+        mContent.removeAllViewsInLayout();
+
+        // Add the Apps button
+        Context context = getContext();
+        LayoutInflater inflater = LayoutInflater.from(context);
+        BubbleTextView allAppsButton = (BubbleTextView)
+                inflater.inflate(R.layout.application, mContent, false);
+        allAppsButton.setCompoundDrawablesWithIntrinsicBounds(null,
+                context.getResources().getDrawable(R.drawable.all_apps_button_icon), null, null);
+        allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
+        allAppsButton.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (mLauncher != null &&
+                    (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
+                    mLauncher.onTouchDownAllAppsButton(v);
+                }
+                return false;
+            }
+        });
+
+        allAppsButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(android.view.View v) {
+                if (mLauncher != null) {
+                    mLauncher.onClickAllAppsButton(v);
+                }
+            }
+        });
+
+        // Note: We do this to ensure that the hotseat is always laid out in the orientation of
+        // the hotseat in order regardless of which orientation they were added
+        int x = getCellXFromOrder(mAllAppsButtonRank);
+        int y = getCellYFromOrder(mAllAppsButtonRank);
+        CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
+        lp.canReorder = false;
+        mContent.addViewToCellLayout(allAppsButton, -1, 0, lp, true);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/IconCache.java b/FairphoneHome/src/org/fairphone/launcher/IconCache.java
new file mode 100644
index 0000000..fac1b02
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/IconCache.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+
+import java.util.HashMap;
+
+/**
+ * Cache of application icons.  Icons can be made from any thread.
+ */
+public class IconCache {
+    @SuppressWarnings("unused")
+    private static final String TAG = "Launcher.IconCache";
+
+    private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
+
+    private static class CacheEntry {
+        public Bitmap icon;
+        public String title;
+    }
+
+    private final Bitmap mDefaultIcon;
+    private final LauncherApplication mContext;
+    private final PackageManager mPackageManager;
+    private final HashMap<ComponentName, CacheEntry> mCache =
+            new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
+    private int mIconDpi;
+
+    public IconCache(LauncherApplication context) {
+        ActivityManager activityManager =
+                (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+
+        mContext = context;
+        mPackageManager = context.getPackageManager();
+        mIconDpi = activityManager.getLauncherLargeIconDensity();
+
+        // need to set mIconDpi before getting default icon
+        mDefaultIcon = makeDefaultIcon();
+    }
+
+    public Drawable getFullResDefaultActivityIcon() {
+        return getFullResIcon(Resources.getSystem(),
+                android.R.mipmap.sym_def_app_icon);
+    }
+
+    public Drawable getFullResIcon(Resources resources, int iconId) {
+        Drawable d;
+        try {
+            d = resources.getDrawableForDensity(iconId, mIconDpi);
+        } catch (Resources.NotFoundException e) {
+            d = null;
+        }
+
+        return (d != null) ? d : getFullResDefaultActivityIcon();
+    }
+
+    public Drawable getFullResIcon(String packageName, int iconId) {
+        Resources resources;
+        try {
+            resources = mPackageManager.getResourcesForApplication(packageName);
+        } catch (PackageManager.NameNotFoundException e) {
+            resources = null;
+        }
+        if (resources != null) {
+            if (iconId != 0) {
+                return getFullResIcon(resources, iconId);
+            }
+        }
+        return getFullResDefaultActivityIcon();
+    }
+
+    public Drawable getFullResIcon(ResolveInfo info) {
+        return getFullResIcon(info.activityInfo);
+    }
+
+    public Drawable getFullResIcon(ActivityInfo info) {
+
+        Resources resources;
+        try {
+            resources = mPackageManager.getResourcesForApplication(
+                    info.applicationInfo);
+        } catch (PackageManager.NameNotFoundException e) {
+            resources = null;
+        }
+        if (resources != null) {
+            int iconId = info.getIconResource();
+            if (iconId != 0) {
+                return getFullResIcon(resources, iconId);
+            }
+        }
+        return getFullResDefaultActivityIcon();
+    }
+
+    private Bitmap makeDefaultIcon() {
+        Drawable d = getFullResDefaultActivityIcon();
+        Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1),
+                Math.max(d.getIntrinsicHeight(), 1),
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        d.setBounds(0, 0, b.getWidth(), b.getHeight());
+        d.draw(c);
+        c.setBitmap(null);
+        return b;
+    }
+
+    /**
+     * Remove any records for the supplied ComponentName.
+     */
+    public void remove(ComponentName componentName) {
+        synchronized (mCache) {
+            mCache.remove(componentName);
+        }
+    }
+
+    public boolean contains(ComponentName componentName){
+    	synchronized (mCache) {
+    		return mCache.containsKey(componentName);
+		}
+    }
+    
+    /**
+     * Empty out the cache.
+     */
+    public void flush() {
+        synchronized (mCache) {
+            mCache.clear();
+        }
+    }
+
+    /**
+     * Fill in "application" with the icon and label for "info."
+     */
+    public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info,
+            HashMap<Object, CharSequence> labelCache) {
+        synchronized (mCache) {
+            CacheEntry entry = cacheLocked(application.componentName, info, labelCache);
+
+            application.title = entry.title;
+            application.iconBitmap = entry.icon;
+        }
+    }
+
+    public Bitmap getIcon(Intent intent) {
+        synchronized (mCache) {
+            final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
+            ComponentName component = intent.getComponent();
+
+            if (resolveInfo == null || component == null) {
+                return mDefaultIcon;
+            }
+
+            CacheEntry entry = cacheLocked(component, resolveInfo, null);
+            return entry.icon;
+        }
+    }
+
+    public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo,
+            HashMap<Object, CharSequence> labelCache) {
+        synchronized (mCache) {
+            if (resolveInfo == null || component == null) {
+                return null;
+            }
+
+            CacheEntry entry = cacheLocked(component, resolveInfo, labelCache);
+            return entry.icon;
+        }
+    }
+
+    public boolean isDefaultIcon(Bitmap icon) {
+        return mDefaultIcon == icon;
+    }
+
+    private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info,
+            HashMap<Object, CharSequence> labelCache) {
+        CacheEntry entry = mCache.get(componentName);
+        if (entry == null) {
+            entry = new CacheEntry();
+
+            mCache.put(componentName, entry);
+
+            ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
+            if (labelCache != null && labelCache.containsKey(key)) {
+                entry.title = labelCache.get(key).toString();
+            } else {
+                entry.title = info.loadLabel(mPackageManager).toString();
+                if (labelCache != null) {
+                    labelCache.put(key, entry.title);
+                }
+            }
+            if (entry.title == null) {
+                entry.title = info.activityInfo.name;
+            }
+
+            entry.icon = Utilities.createIconBitmap(
+                    getFullResIcon(info), mContext);
+        }
+        return entry;
+    }
+
+    public HashMap<ComponentName,Bitmap> getAllIcons() {
+        synchronized (mCache) {
+            HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
+            for (ComponentName cn : mCache.keySet()) {
+                final CacheEntry e = mCache.get(cn);
+                set.put(cn, e.icon);
+            }
+            return set;
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/InfoDropTarget.java b/FairphoneHome/src/org/fairphone/launcher/InfoDropTarget.java
new file mode 100644
index 0000000..b07e51a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/InfoDropTarget.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.drawable.TransitionDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.fairphone.launcher.R;
+
+public class InfoDropTarget extends ButtonDropTarget {
+
+    private ColorStateList mOriginalTextColor;
+    private TransitionDrawable mDrawable;
+
+    public InfoDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public InfoDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mOriginalTextColor = getTextColors();
+
+        // Get the hover color
+        Resources r = getResources();
+        mHoverColor = r.getColor(R.color.info_target_hover_tint);
+        mDrawable = (TransitionDrawable) getCurrentDrawable();
+        mDrawable.setCrossFadeEnabled(true);
+
+        // Remove the text in the Phone UI in landscape
+        int orientation = getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            if (!LauncherApplication.isScreenLarge()) {
+                setText("");
+            }
+        }
+    }
+
+    private boolean isFromAllApps(DragSource source) {
+        return (source instanceof AppsCustomizePagedView);
+    }
+
+    @Override
+    public boolean acceptDrop(DragObject d) {
+        // acceptDrop is called just before onDrop. We do the work here, rather than
+        // in onDrop, because it allows us to reject the drop (by returning false)
+        // so that the object being dragged isn't removed from the drag source.
+        ComponentName componentName = null;
+        if (d.dragInfo instanceof ApplicationInfo) {
+            componentName = ((ApplicationInfo) d.dragInfo).componentName;
+        } else if (d.dragInfo instanceof ShortcutInfo) {
+            componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
+        } else if (d.dragInfo instanceof PendingAddItemInfo) {
+            componentName = ((PendingAddItemInfo) d.dragInfo).componentName;
+        }
+        if (componentName != null) {
+            mLauncher.startApplicationDetailsActivity(componentName);
+        }
+
+        // There is no post-drop animation, so clean up the DragView now
+        d.deferDragViewCleanupPostAnimation = false;
+        return false;
+    }
+
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        boolean isVisible = true;
+
+        // Hide this button unless we are dragging something from AllApps
+        if (!isFromAllApps(source)) {
+            isVisible = false;
+        }
+
+        mActive = isVisible;
+        mDrawable.resetTransition();
+        setTextColor(mOriginalTextColor);
+        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void onDragEnd() {
+        super.onDragEnd();
+        mActive = false;
+    }
+
+    public void onDragEnter(DragObject d) {
+        super.onDragEnter(d);
+
+        mDrawable.startTransition(mTransitionDuration);
+        setTextColor(mHoverColor);
+    }
+
+    public void onDragExit(DragObject d) {
+        super.onDragExit(d);
+
+        if (!d.dragComplete) {
+            mDrawable.resetTransition();
+            setTextColor(mOriginalTextColor);
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/InstallShortcutReceiver.java b/FairphoneHome/src/org/fairphone/launcher/InstallShortcutReceiver.java
new file mode 100644
index 0000000..4e045fc
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/InstallShortcutReceiver.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.widget.Toast;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class InstallShortcutReceiver extends BroadcastReceiver {
+    public static final String ACTION_INSTALL_SHORTCUT =
+            "com.android.launcher.action.INSTALL_SHORTCUT";
+    public static final String NEW_APPS_PAGE_KEY = "apps.new.page";
+    public static final String NEW_APPS_LIST_KEY = "apps.new.list";
+
+    public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
+    public static final int NEW_SHORTCUT_STAGGER_DELAY = 75;
+
+    private static final int INSTALL_SHORTCUT_SUCCESSFUL = 0;
+    private static final int INSTALL_SHORTCUT_IS_DUPLICATE = -1;
+    private static final int INSTALL_SHORTCUT_NO_SPACE = -2;
+
+    // A mime-type representing shortcut data
+    public static final String SHORTCUT_MIMETYPE =
+            "com.android.launcher/shortcut";
+
+    // The set of shortcuts that are pending install
+    private static ArrayList<PendingInstallShortcutInfo> mInstallQueue =
+            new ArrayList<PendingInstallShortcutInfo>();
+
+    // Determines whether to defer installing shortcuts immediately until
+    // processAllPendingInstalls() is called.
+    private static boolean mUseInstallQueue = false;
+
+    private static class PendingInstallShortcutInfo {
+        Intent data;
+        Intent launchIntent;
+        String name;
+
+        public PendingInstallShortcutInfo(Intent rawData, String shortcutName,
+                Intent shortcutIntent) {
+            data = rawData;
+            name = shortcutName;
+            launchIntent = shortcutIntent;
+        }
+    }
+
+    public void onReceive(Context context, Intent data) {
+        if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
+            return;
+        }
+
+        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+        if (intent == null) {
+            return;
+        }
+        // This name is only used for comparisons and notifications, so fall back to activity name
+        // if not supplied
+        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+        if (name == null) {
+            try {
+                PackageManager pm = context.getPackageManager();
+                ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0);
+                name = info.loadLabel(pm).toString();
+            } catch (PackageManager.NameNotFoundException nnfe) {
+                return;
+            }
+        }
+        // Queue the item up for adding if launcher has not loaded properly yet
+        boolean launcherNotLoaded = LauncherModel.getCellCountX() <= 0 ||
+                LauncherModel.getCellCountY() <= 0;
+
+        PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, name, intent);
+        if (mUseInstallQueue || launcherNotLoaded) {
+            mInstallQueue.add(info);
+        } else {
+            processInstallShortcut(context, info);
+        }
+    }
+
+    static void enableInstallQueue() {
+        mUseInstallQueue = true;
+    }
+    static void disableAndFlushInstallQueue(Context context) {
+        mUseInstallQueue = false;
+        flushInstallQueue(context);
+    }
+    static void flushInstallQueue(Context context) {
+        Iterator<PendingInstallShortcutInfo> iter = mInstallQueue.iterator();
+        while (iter.hasNext()) {
+            processInstallShortcut(context, iter.next());
+            iter.remove();
+        }
+    }
+
+    private static void processInstallShortcut(Context context,
+            PendingInstallShortcutInfo pendingInfo) {
+        String spKey = LauncherApplication.getSharedPreferencesKey();
+        SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+
+        final Intent data = pendingInfo.data;
+        final Intent intent = pendingInfo.launchIntent;
+        final String name = pendingInfo.name;
+
+        // Lock on the app so that we don't try and get the items while apps are being added
+        LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+        final int[] result = {INSTALL_SHORTCUT_SUCCESSFUL};
+        boolean found = false;
+        synchronized (app) {
+            final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
+            final boolean exists = LauncherModel.shortcutExists(context, name, intent);
+
+            // Try adding to the workspace screens incrementally, starting at the default or center
+            // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))
+            final int screen = Launcher.DEFAULT_SCREEN;
+            for (int i = 0; i < (2 * Launcher.SCREEN_COUNT) + 1 && !found; ++i) {
+                int si = screen + (int) ((i / 2f) + 0.5f) * ((i % 2 == 1) ? 1 : -1);
+                if (0 <= si && si < Launcher.SCREEN_COUNT) {
+                    found = installShortcut(context, data, items, name, intent, si, exists, sp,
+                            result);
+                }
+            }
+        }
+
+        // We only report error messages (duplicate shortcut or out of space) as the add-animation
+        // will provide feedback otherwise
+        if (!found) {
+            if (result[0] == INSTALL_SHORTCUT_NO_SPACE) {
+                Toast.makeText(context, context.getString(R.string.completely_out_of_space),
+                        Toast.LENGTH_SHORT).show();
+            } else if (result[0] == INSTALL_SHORTCUT_IS_DUPLICATE) {
+                Toast.makeText(context, context.getString(R.string.shortcut_duplicate, name),
+                        Toast.LENGTH_SHORT).show();
+            }
+        }
+    }
+
+    private static boolean installShortcut(Context context, Intent data, ArrayList<ItemInfo> items,
+            String name, Intent intent, final int screen, boolean shortcutExists,
+            final SharedPreferences sharedPrefs, int[] result) {
+        int[] tmpCoordinates = new int[2];
+        if (findEmptyCell(context, items, tmpCoordinates, screen)) {
+            if (intent != null) {
+                if (intent.getAction() == null) {
+                    intent.setAction(Intent.ACTION_VIEW);
+                } else if (intent.getAction().equals(Intent.ACTION_MAIN) &&
+                        intent.getCategories() != null &&
+                        intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
+                    intent.addFlags(
+                        Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                }
+
+                // By default, we allow for duplicate entries (located in
+                // different places)
+                boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
+                if (duplicate || !shortcutExists) {
+                    // If the new app is going to fall into the same page as before, then just
+                    // continue adding to the current page
+                    int newAppsScreen = sharedPrefs.getInt(NEW_APPS_PAGE_KEY, screen);
+                    Set<String> newApps = new HashSet<String>();
+                    if (newAppsScreen == screen) {
+                        newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps);
+                    }
+                    synchronized (newApps) {
+                        newApps.add(intent.toUri(0).toString());
+                    }
+                    final Set<String> savedNewApps = newApps;
+                    new Thread("setNewAppsThread") {
+                        public void run() {
+                            synchronized (savedNewApps) {
+                                sharedPrefs.edit()
+                                           .putInt(NEW_APPS_PAGE_KEY, screen)
+                                           .putStringSet(NEW_APPS_LIST_KEY, savedNewApps)
+                                           .commit();
+                            }
+                        }
+                    }.start();
+
+                    // Update the Launcher db
+                    LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+                    ShortcutInfo info = app.getModel().addShortcut(context, data,
+                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
+                            tmpCoordinates[0], tmpCoordinates[1], true);
+                    if (info == null) {
+                        return false;
+                    }
+                } else {
+                    result[0] = INSTALL_SHORTCUT_IS_DUPLICATE;
+                }
+
+                return true;
+            }
+        } else {
+            result[0] = INSTALL_SHORTCUT_NO_SPACE;
+        }
+
+        return false;
+    }
+
+    private static boolean findEmptyCell(Context context, ArrayList<ItemInfo> items, int[] xy,
+            int screen) {
+        final int xCount = LauncherModel.getCellCountX();
+        final int yCount = LauncherModel.getCellCountY();
+        boolean[][] occupied = new boolean[xCount][yCount];
+
+        ItemInfo item = null;
+        int cellX, cellY, spanX, spanY;
+        for (int i = 0; i < items.size(); ++i) {
+            item = items.get(i);
+            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                if (item.screen == screen) {
+                    cellX = item.cellX;
+                    cellY = item.cellY;
+                    spanX = item.spanX;
+                    spanY = item.spanY;
+                    for (int x = cellX; 0 <= x && x < cellX + spanX && x < xCount; x++) {
+                        for (int y = cellY; 0 <= y && y < cellY + spanY && y < yCount; y++) {
+                            occupied[x][y] = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/InstallWidgetReceiver.java b/FairphoneHome/src/org/fairphone/launcher/InstallWidgetReceiver.java
new file mode 100644
index 0000000..cebb049
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/InstallWidgetReceiver.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.List;
+
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ClipData;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.ResolveInfo;
+import android.database.DataSetObserver;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListAdapter;
+
+/**
+ * We will likely flesh this out later, to handle allow external apps to place widgets, but for now,
+ * we just want to expose the action around for checking elsewhere.
+ */
+public class InstallWidgetReceiver {
+    public static final String ACTION_INSTALL_WIDGET =
+            "com.android.launcher.action.INSTALL_WIDGET";
+    public static final String ACTION_SUPPORTS_CLIPDATA_MIMETYPE =
+            "com.android.launcher.action.SUPPORTS_CLIPDATA_MIMETYPE";
+
+    // Currently not exposed.  Put into Intent when we want to make it public.
+    // TEMP: Should we call this "EXTRA_APPWIDGET_PROVIDER"?
+    public static final String EXTRA_APPWIDGET_COMPONENT =
+        "com.android.launcher.extra.widget.COMPONENT";
+    public static final String EXTRA_APPWIDGET_CONFIGURATION_DATA_MIME_TYPE =
+        "com.android.launcher.extra.widget.CONFIGURATION_DATA_MIME_TYPE";
+    public static final String EXTRA_APPWIDGET_CONFIGURATION_DATA =
+        "com.android.launcher.extra.widget.CONFIGURATION_DATA";
+
+    /**
+     * A simple data class that contains per-item information that the adapter below can reference.
+     */
+    public static class WidgetMimeTypeHandlerData {
+        public ResolveInfo resolveInfo;
+        public AppWidgetProviderInfo widgetInfo;
+
+        public WidgetMimeTypeHandlerData(ResolveInfo rInfo, AppWidgetProviderInfo wInfo) {
+            resolveInfo = rInfo;
+            widgetInfo = wInfo;
+        }
+    }
+
+    /**
+     * The ListAdapter which presents all the valid widgets that can be created for a given drop.
+     */
+    public static class WidgetListAdapter implements ListAdapter, DialogInterface.OnClickListener {
+        private LayoutInflater mInflater;
+        private Launcher mLauncher;
+        private String mMimeType;
+        private ClipData mClipData;
+        private List<WidgetMimeTypeHandlerData> mActivities;
+        private CellLayout mTargetLayout;
+        private int mTargetLayoutScreen;
+        private int[] mTargetLayoutPos;
+
+        public WidgetListAdapter(Launcher l, String mimeType, ClipData data,
+                List<WidgetMimeTypeHandlerData> list, CellLayout target,
+                int targetScreen, int[] targetPos) {
+            mLauncher = l;
+            mMimeType = mimeType;
+            mClipData = data;
+            mActivities = list;
+            mTargetLayout = target;
+            mTargetLayoutScreen = targetScreen;
+            mTargetLayoutPos = targetPos;
+        }
+
+        @Override
+        public void registerDataSetObserver(DataSetObserver observer) {
+        }
+
+        @Override
+        public void unregisterDataSetObserver(DataSetObserver observer) {
+        }
+
+        @Override
+        public int getCount() {
+            return mActivities.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean hasStableIds() {
+            return true;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final Context context = parent.getContext();
+
+            // Lazy-create inflater
+            if (mInflater == null) {
+                mInflater = LayoutInflater.from(context);
+            }
+
+            return convertView;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return 0;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 1;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return mActivities.isEmpty();
+        }
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return false;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return true;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            final AppWidgetProviderInfo widgetInfo = mActivities.get(which).widgetInfo;
+
+            final PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo(widgetInfo, mMimeType,
+                    mClipData);
+            mLauncher.addAppWidgetFromDrop(createInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                    mTargetLayoutScreen, null, null, mTargetLayoutPos);
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/InterruptibleInOutAnimator.java b/FairphoneHome/src/org/fairphone/launcher/InterruptibleInOutAnimator.java
new file mode 100644
index 0000000..f67d25a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/InterruptibleInOutAnimator.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+
+/**
+ * A convenience class for two-way animations, e.g. a fadeIn/fadeOut animation.
+ * With a regular ValueAnimator, if you call reverse to show the 'out' animation, you'll get
+ * a frame-by-frame mirror of the 'in' animation -- i.e., the interpolated values will
+ * be exactly reversed. Using this class, both the 'in' and the 'out' animation use the
+ * interpolator in the same direction.
+ */
+public class InterruptibleInOutAnimator {
+    private long mOriginalDuration;
+    private float mOriginalFromValue;
+    private float mOriginalToValue;
+    private ValueAnimator mAnimator;
+
+    private boolean mFirstRun = true;
+
+    private Object mTag = null;
+
+    private static final int STOPPED = 0;
+    private static final int IN = 1;
+    private static final int OUT = 2;
+
+    // TODO: This isn't really necessary, but is here to help diagnose a bug in the drag viz
+    private int mDirection = STOPPED;
+
+    public InterruptibleInOutAnimator(long duration, float fromValue, float toValue) {
+        mAnimator = LauncherAnimUtils.ofFloat(fromValue, toValue).setDuration(duration);
+        mOriginalDuration = duration;
+        mOriginalFromValue = fromValue;
+        mOriginalToValue = toValue;
+
+        mAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mDirection = STOPPED;
+            }
+        });
+    }
+
+    private void animate(int direction) {
+        final long currentPlayTime = mAnimator.getCurrentPlayTime();
+        final float toValue = (direction == IN) ? mOriginalToValue : mOriginalFromValue;
+        final float startValue = mFirstRun ? mOriginalFromValue :
+                ((Float) mAnimator.getAnimatedValue()).floatValue();
+
+        // Make sure it's stopped before we modify any values
+        cancel();
+
+        mDirection = direction;
+
+        // Ensure we don't calculate a non-sensical duration
+        long duration = mOriginalDuration - currentPlayTime;
+        mAnimator.setDuration(Math.max(0, Math.min(duration, mOriginalDuration)));
+
+        mAnimator.setFloatValues(startValue, toValue);
+        mAnimator.start();
+        mFirstRun = false;
+    }
+
+    public void cancel() {
+        mAnimator.cancel();
+        mDirection = STOPPED;
+    }
+
+    public void end() {
+        mAnimator.end();
+        mDirection = STOPPED;
+    }
+
+    /**
+     * Return true when the animation is not running and it hasn't even been started.
+     */
+    public boolean isStopped() {
+        return mDirection == STOPPED;
+    }
+
+    /**
+     * This is the equivalent of calling Animator.start(), except that it can be called when
+     * the animation is running in the opposite direction, in which case we reverse
+     * direction and animate for a correspondingly shorter duration.
+     */
+    public void animateIn() {
+        animate(IN);
+    }
+
+    /**
+     * This is the roughly the equivalent of calling Animator.reverse(), except that it uses the
+     * same interpolation curve as animateIn(), rather than mirroring it. Also, like animateIn(),
+     * if the animation is currently running in the opposite direction, we reverse
+     * direction and animate for a correspondingly shorter duration.
+     */
+    public void animateOut() {
+        animate(OUT);
+    }
+
+    public void setTag(Object tag) {
+        mTag = tag;
+    }
+
+    public Object getTag() {
+        return mTag;
+    }
+
+    public ValueAnimator getAnimator() {
+        return mAnimator;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/ItemInfo.java b/FairphoneHome/src/org/fairphone/launcher/ItemInfo.java
new file mode 100644
index 0000000..c615984
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/ItemInfo.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.ContentValues;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Represents an item in the launcher.
+ */
+class ItemInfo {
+    
+    static final int NO_ID = -1;
+    
+    /**
+     * The id in the settings database for this item
+     */
+    long id = NO_ID;
+    
+    /**
+     * One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_FOLDER}, or
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}.
+     */
+    int itemType;
+    
+    /**
+     * The id of the container that holds this item. For the desktop, this will be 
+     * {@link LauncherSettings.Favorites#CONTAINER_DESKTOP}. For the all applications folder it
+     * will be {@link #NO_ID} (since it is not stored in the settings DB). For user folders
+     * it will be the id of the folder.
+     */
+    long container = NO_ID;
+    
+    /**
+     * Iindicates the screen in which the shortcut appears.
+     */
+    int screen = -1;
+    
+    /**
+     * Indicates the X position of the associated cell.
+     */
+    int cellX = -1;
+
+    /**
+     * Indicates the Y position of the associated cell.
+     */
+    int cellY = -1;
+
+    /**
+     * Indicates the X cell span.
+     */
+    int spanX = 1;
+
+    /**
+     * Indicates the Y cell span.
+     */
+    int spanY = 1;
+
+    /**
+     * Indicates the minimum X cell span.
+     */
+    int minSpanX = 1;
+
+    /**
+     * Indicates the minimum Y cell span.
+     */
+    int minSpanY = 1;
+
+    /**
+     * Indicates that this item needs to be updated in the db
+     */
+    boolean requiresDbUpdate = false;
+
+    /**
+     * Title of the item
+     */
+    CharSequence title;
+
+    /**
+     * The position of the item in a drag-and-drop operation.
+     */
+    int[] dropPos = null;
+
+    ItemInfo() {
+    }
+
+    ItemInfo(ItemInfo info) {
+        id = info.id;
+        cellX = info.cellX;
+        cellY = info.cellY;
+        spanX = info.spanX;
+        spanY = info.spanY;
+        screen = info.screen;
+        itemType = info.itemType;
+        container = info.container;
+        // tempdebug:
+        LauncherModel.checkItemInfo(this);
+    }
+
+    /** Returns the package name that the intent will resolve to, or an empty string if
+     *  none exists. */
+    static String getPackageName(Intent intent) {
+        if (intent != null) {
+            String packageName = intent.getPackage();
+            if (packageName == null && intent.getComponent() != null) {
+                packageName = intent.getComponent().getPackageName();
+            }
+            if (packageName != null) {
+                return packageName;
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Write the fields of this item to the DB
+     * 
+     * @param values
+     */
+    void onAddToDatabase(ContentValues values) { 
+        values.put(LauncherSettings.BaseLauncherColumns.ITEM_TYPE, itemType);
+        values.put(LauncherSettings.Favorites.CONTAINER, container);
+        values.put(LauncherSettings.Favorites.SCREEN, screen);
+        values.put(LauncherSettings.Favorites.CELLX, cellX);
+        values.put(LauncherSettings.Favorites.CELLY, cellY);
+        values.put(LauncherSettings.Favorites.SPANX, spanX);
+        values.put(LauncherSettings.Favorites.SPANY, spanY);
+    }
+
+    void updateValuesWithCoordinates(ContentValues values, int cellX, int cellY) {
+        values.put(LauncherSettings.Favorites.CELLX, cellX);
+        values.put(LauncherSettings.Favorites.CELLY, cellY);
+    }
+
+    static byte[] flattenBitmap(Bitmap bitmap) {
+        // Try go guesstimate how much space the icon will take when serialized
+        // to avoid unnecessary allocations/copies during the write.
+        int size = bitmap.getWidth() * bitmap.getHeight() * 4;
+        ByteArrayOutputStream out = new ByteArrayOutputStream(size);
+        try {
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+            out.flush();
+            out.close();
+            return out.toByteArray();
+        } catch (IOException e) {
+            Log.w("Favorite", "Could not write icon");
+            return null;
+        }
+    }
+
+    static void writeBitmap(ContentValues values, Bitmap bitmap) {
+        if (bitmap != null) {
+            byte[] data = flattenBitmap(bitmap);
+            values.put(LauncherSettings.Favorites.ICON, data);
+        }
+    }
+
+    /**
+     * It is very important that sub-classes implement this if they contain any references
+     * to the activity (anything in the view hierarchy etc.). If not, leaks can result since
+     * ItemInfo objects persist across rotation and can hence leak by holding stale references
+     * to the old view hierarchy / activity.
+     */
+    void unbind() {
+    }
+
+    @Override
+    public String toString() {
+        return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
+            + " screen=" + screen + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
+            + " spanY=" + spanY + " dropPos=" + dropPos + ")";
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Launcher.java b/FairphoneHome/src/org/fairphone/launcher/Launcher.java
new file mode 100644
index 0000000..08a325c
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Launcher.java
@@ -0,0 +1,4498 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.fairphone.launcher.DropTarget.DragObject;
+import org.fairphone.launcher.edgeswipe.EdgeSwipeAppMenuHelper;
+import org.fairphone.launcher.edgeswipe.edit.EditFavoritesActivity;
+import org.fairphone.launcher.edgeswipe.ui.EdgeSwipeInterceptorViewListener;
+import org.fairphone.launcher.gappsinstaller.GappsInstallerHelper;
+import org.fairphone.oobe.OOBEActivity;
+import org.fairphone.widgets.appswitcher.AppDiscoverer;
+import org.fairphone.widgets.appswitcher.ApplicationRunInformation;
+import org.fairphone.widgets.appswitcher.WidgetProvider;
+import org.fairphone.widgets.gapps.GoogleAppsInstallerWidget;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.SearchManager;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Message;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.preference.PreferenceManager;
+import android.provider.Settings;
+import android.speech.RecognizerIntent;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.method.TextKeyListener;
+import android.util.Log;
+import android.view.Display;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.View;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Advanceable;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * Default launcher application.
+ * 
+ * Fair Phone Changes: =================== . Removed the access to the quick
+ * search bar . Removed the access to the hot seat (the locked 5 button row) .
+ * Removed the access to the dockdivider . Added AppSwitcher activity . Added
+ * EdgeSwipe
+ */
+@SuppressLint("ValidFragment")
+public final class Launcher extends Activity implements View.OnClickListener,
+		OnLongClickListener, LauncherModel.Callbacks, View.OnTouchListener {
+	private static final String APP_RUN_INFO_SEPARATOR = ";";
+	static final String TAG = "Launcher";
+	static final boolean LOGD = false;
+
+	static final boolean PROFILE_STARTUP = false;
+	static final boolean DEBUG_WIDGETS = false;
+	static final boolean DEBUG_STRICT_MODE = false;
+
+	public static final String APP_SWITCHER_LAUNCH_APP = "org.fairphone.launcher.LAUNCH";
+	public static final String APP_SWITCHER_RESET = "org.fairphone.launcher.RESET";
+	public static final String APP_SWITCHER_ALL_APPS = "org.fairphone.launcher.ALL_APPS";
+	public static final String PREFS_APP_SWITCHER_APPS_DATA = "FAIRPHONE_APP_SWITCHER_ALL_APPS";
+	private static SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(
+			"yyyy-MM-dd hh:mm:ss");
+
+	public static String APP_NAME = "org.fairphone.launcher.AppName";
+	public static String APP_PACKAGE = "org.fairphone.launcher.AppPackageName";
+	public static String APP_CLASS_NAME = "org.fairphone.launcher.AppClassName";
+
+	private static final int MENU_GROUP_WALLPAPER = 1;
+	private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1;
+	private static final int MENU_MANAGE_APPS = MENU_WALLPAPER_SETTINGS + 1;
+	private static final int MENU_SYSTEM_SETTINGS = MENU_MANAGE_APPS + 1;
+	private static final int MENU_HELP = MENU_SYSTEM_SETTINGS + 1;
+
+	private static final int MENU_SHOW_FP_OOBE = MENU_HELP + 1;
+
+	private static final int REQUEST_EDIT_FAVORITES = 100;
+
+	private static final int REQUEST_CREATE_SHORTCUT = 1;
+	private static final int REQUEST_CREATE_APPWIDGET = 5;
+	private static final int REQUEST_PICK_APPLICATION = 6;
+	private static final int REQUEST_PICK_SHORTCUT = 7;
+	private static final int REQUEST_PICK_APPWIDGET = 9;
+	private static final int REQUEST_PICK_WALLPAPER = 10;
+
+	private static final int REQUEST_BIND_APPWIDGET = 11;
+
+	static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
+
+	static final int SCREEN_COUNT = 5;
+	static final int DEFAULT_SCREEN = 2;
+
+	private static final String PREFERENCES = "launcher.preferences";
+	// To turn on these properties, type
+	// adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
+	static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
+	static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
+
+	// The Intent extra that defines whether to ignore the launch animation
+	static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION = "com.android.launcher.intent.extra.shortcut.INGORE_LAUNCH_ANIMATION";
+
+	// Type: int
+	private static final String RUNTIME_STATE_CURRENT_SCREEN = "launcher.current_screen";
+	// Type: int
+	private static final String RUNTIME_STATE = "launcher.state";
+	// Type: int
+	private static final String RUNTIME_STATE_PENDING_ADD_CONTAINER = "launcher.add_container";
+	// Type: int
+	private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
+	// Type: int
+	private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cell_x";
+	// Type: int
+	private static final String RUNTIME_STATE_PENDING_ADD_CELL_Y = "launcher.add_cell_y";
+	// Type: boolean
+	private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME = "launcher.rename_folder";
+	// Type: long
+	private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME_ID = "launcher.rename_folder_id";
+	// Type: int
+	private static final String RUNTIME_STATE_PENDING_ADD_SPAN_X = "launcher.add_span_x";
+	// Type: int
+	private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_span_y";
+	// Type: parcelable
+	private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info";
+
+	private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
+	private static final String TOOLBAR_VOICE_SEARCH_ICON_METADATA_NAME = "com.android.launcher.toolbar_voice_search_icon";
+
+	/** The different states that Launcher can be in. */
+	private enum State {
+		NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED
+	};
+
+	private State mState = State.WORKSPACE;
+	private AnimatorSet mStateAnimation;
+
+	static final int APPWIDGET_HOST_ID = 1024;
+	private static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
+	private static final int EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT = 600;
+	private static final int SHOW_CLING_DURATION = 550;
+	private static final int DISMISS_CLING_DURATION = 250;
+
+	private static final Object sLock = new Object();
+	private static int sScreen = DEFAULT_SCREEN;
+
+	// How long to wait before the new-shortcut animation automatically pans the
+	// workspace
+	private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 10;
+
+	private final BroadcastReceiver mCloseSystemDialogsReceiver = new CloseSystemDialogsIntentReceiver();
+	private final ContentObserver mWidgetObserver = new AppWidgetResetObserver();
+
+	private LayoutInflater mInflater;
+
+	private Workspace mWorkspace;
+	// private View mDockDivider;
+	private View mLauncherView;
+	private DragLayer mDragLayer;
+	private DragController mDragController;
+
+	private AppWidgetManager mAppWidgetManager;
+	private LauncherAppWidgetHost mAppWidgetHost;
+
+	private ItemInfo mPendingAddInfo = new ItemInfo();
+	private AppWidgetProviderInfo mPendingAddWidgetInfo;
+
+	private int[] mTmpAddItemCellCoordinates = new int[2];
+
+	private FolderInfo mFolderInfo;
+	private View mAllAppsButton;
+
+	private SearchDropTargetBar mSearchDropTargetBar;
+	private AppsCustomizeTabHost mAppsCustomizeTabHost;
+	private AppsCustomizePagedView mAppsCustomizeContent;
+	private boolean mAutoAdvanceRunning = false;
+
+	private Bundle mSavedState;
+	// We set the state in both onCreate and then onNewIntent in some cases,
+	// which causes both
+	// scroll issues (because the workspace may not have been measured yet) and
+	// extra work.
+	// Instead, just save the state that we need to restore Launcher to, and
+	// commit it in onResume.
+	private State mOnResumeState = State.NONE;
+
+	private SpannableStringBuilder mDefaultKeySsb = null;
+
+	private boolean mWorkspaceLoading = true;
+
+	private boolean mPaused = true;
+	private boolean mRestoring;
+	private boolean mWaitingForResult;
+	private boolean mOnResumeNeedsLoad;
+
+	// Keep track of whether the user has left launcher
+	private static boolean sPausedFromUserAction = false;
+
+	private Bundle mSavedInstanceState;
+
+	private LauncherModel mModel;
+	private IconCache mIconCache;
+	private boolean mUserPresent = true;
+	private boolean mVisible = false;
+	private boolean mAttached = false;
+
+	private static LocaleConfiguration sLocaleConfiguration = null;
+
+	private static HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
+
+	private Intent mAppMarketIntent = null;
+
+	// Related to the auto-advancing of widgets
+	private final int ADVANCE_MSG = 1;
+	private final int mAdvanceInterval = 20000;
+	private final int mAdvanceStagger = 250;
+	private long mAutoAdvanceSentTime;
+	private long mAutoAdvanceTimeLeft = -1;
+	private HashMap<View, AppWidgetProviderInfo> mWidgetsToAdvance = new HashMap<View, AppWidgetProviderInfo>();
+
+	// Determines how long to wait after a rotation before restoring the screen
+	// orientation to
+	// match the sensor state.
+	private final int mRestoreScreenOrientationDelay = 500;
+
+	// External icons saved in case of resource changes, orientation, etc.
+	private static Drawable.ConstantState[] sGlobalSearchIcon = new Drawable.ConstantState[2];
+	private static Drawable.ConstantState[] sVoiceSearchIcon = new Drawable.ConstantState[2];
+	private static Drawable.ConstantState[] sAppMarketIcon = new Drawable.ConstantState[2];
+
+	private Drawable mWorkspaceBackgroundDrawable;
+	private Drawable mBlackBackgroundDrawable;
+
+	private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<Integer>();
+
+	static final ArrayList<String> sDumpLogs = new ArrayList<String>();
+	private static final String SHOW_OOBE_EDIT_FAVORITES = "SHOW_FP_OOBE_EDIT_FAVORITES";
+	private static final String SHOW_OOBE_EDGE_SWIPE_MENU = "SHOW_FP_OOBE_EDGE_SWIPE_MENU";
+	public static final String SHOW_OOBE_APP_SWITCHER = "SHOW_FP_OOBE_APP_SWITCHER";
+	private static final String SHOW_VALUES_VIDEO = "SHOW_FAIRPHONE_VALUES_VIDEO";
+
+	// We only want to get the SharedPreferences once since it does an FS stat
+	// each time we get
+	// it from the context.
+	private SharedPreferences mSharedPrefs;
+
+	// Holds the page that we need to animate to, and the icon views that we
+	// need to animate up
+	// when we scroll to that page on resume.
+	private int mNewShortcutAnimatePage = -1;
+	private ArrayList<View> mNewShortcutAnimateViews = new ArrayList<View>();
+	private ImageView mFolderIconImageView;
+	private Bitmap mFolderIconBitmap;
+	private Canvas mFolderIconCanvas;
+	private Rect mRectForFolderAnimation = new Rect();
+
+	private BubbleTextView mWaitingForResume;
+
+	private HideFromAccessibilityHelper mHideFromAccessibilityHelper = new HideFromAccessibilityHelper();
+
+	protected FrameLayout mAppMenuContainerView;
+	protected EdgeSwipeAppMenuHelper mAppMenuHelper;
+
+	private Runnable mBuildLayersRunnable = new Runnable() {
+		public void run() {
+			if (mWorkspace != null) {
+				mWorkspace.buildPageHardwareLayers();
+			}
+		}
+	};
+	private GappsInstallerHelper mGappsInstaller;
+	
+	private FrameLayout mSystemUpdaterWindow;
+
+	private static ArrayList<PendingAddArguments> sPendingAddList = new ArrayList<PendingAddArguments>();
+
+	private static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
+
+	private static class PendingAddArguments {
+		int requestCode;
+		Intent intent;
+		long container;
+		int screen;
+		int cellX;
+		int cellY;
+	}
+
+	private static boolean isPropertyEnabled(String propertyName) {
+		return Log.isLoggable(propertyName, Log.VERBOSE);
+	}
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+
+		if (DEBUG_STRICT_MODE) {
+			StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+					.detectDiskReads().detectDiskWrites().detectNetwork() // or
+																			// .detectAll()
+																			// for
+																			// all
+																			// detectable
+																			// problems
+					.penaltyLog().build());
+			StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+					.detectLeakedSqlLiteObjects().detectLeakedClosableObjects()
+					.penaltyLog().penaltyDeath().build());
+		}
+
+		Log.i(Launcher.class.getSimpleName(), "Create Launcher");
+
+		super.onCreate(savedInstanceState);
+		LauncherApplication app = ((LauncherApplication) getApplication());
+		mSharedPrefs = getSharedPreferences(
+				LauncherApplication.getSharedPreferencesKey(),
+				Context.MODE_PRIVATE);
+		// set the app launcher model defined by the application
+		mModel = app.setLauncher(this);
+		// obtain the already created iconCache with the correct DPI
+		mIconCache = app.getIconCache();
+		// create a dragController
+		mDragController = new DragController(this);
+		mInflater = getLayoutInflater();
+
+		// AppWidgetManager - Updates AppWidget state; gets information about
+		// installed AppWidget providers and other AppWidget related state.
+		mAppWidgetManager = AppWidgetManager.getInstance(this);
+		// AppWidgetHost provides the interaction with the AppWidget service for
+		// apps, like the home screen, that want to embed AppWidgets in their
+		// UI.
+		mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
+		// Start receiving onAppWidgetChanged calls for your AppWidgets.
+		mAppWidgetHost.startListening();
+
+		// If we are getting an onCreate, we can actually preempt onResume and
+		// unset mPaused here,
+		// this also ensures that any synchronous binding below doesn't
+		// re-trigger another
+		// LauncherModel load.
+		mPaused = false;
+
+		if (PROFILE_STARTUP) {
+			android.os.Debug.startMethodTracing(Environment
+					.getExternalStorageDirectory() + "/launcher");
+		}
+
+		checkForLocaleChange();
+		setContentView(R.layout.launcher);
+		setupViews();
+		showFirstRunWorkspaceCling();
+
+		registerContentObservers();
+
+		lockAllApps();
+
+		mSavedState = savedInstanceState;
+		restoreState(mSavedState);
+
+		// Update customization drawer _after_ restoring the states
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.onPackagesUpdated();
+		}
+
+		if (PROFILE_STARTUP) {
+			android.os.Debug.stopMethodTracing();
+		}
+
+		if (!mRestoring) {
+			if (sPausedFromUserAction) {
+				// If the user leaves launcher, then we should just load items
+				// asynchronously when
+				// they return.
+				mModel.startLoader(true, -1);
+			} else {
+				// We only load the page synchronously if the user rotates (or
+				// triggers a
+				// configuration change) while launcher is in the foreground
+				mModel.startLoader(true, mWorkspace.getCurrentPage());
+			}
+		}
+
+		if (!mModel.isAllAppsLoaded()) {
+			ViewGroup appsCustomizeContentParent = (ViewGroup) mAppsCustomizeContent
+					.getParent();
+			mInflater.inflate(R.layout.apps_customize_progressbar,
+					appsCustomizeContentParent);
+		}
+
+		// For handling default keys
+		mDefaultKeySsb = new SpannableStringBuilder();
+		Selection.setSelection(mDefaultKeySsb, 0);
+
+		IntentFilter filter = new IntentFilter(
+				Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+		registerReceiver(mCloseSystemDialogsReceiver, filter);
+
+		updateGlobalIcons();
+
+		// set up defaults
+		PreferenceManager
+				.setDefaultValues(this, R.xml.launcher_settings, false);
+
+		// On large interfaces, we want the screen to auto-rotate based on the
+		// current orientation
+		unlockScreenOrientation(false);
+
+		// loads all save info
+		loadAppRunInfo(this);
+
+		// setup favorites
+		setupFavoriteApps();
+		
+		// setup the gapps installer
+		mGappsInstaller = new GappsInstallerHelper(this);
+	}
+	
+	public void persistAppRunInfo(Context context) {
+		SharedPreferences prefs = context.getSharedPreferences(
+				PREFS_APP_SWITCHER_APPS_DATA, 0);
+
+		// get the current prefs and clear to update
+		android.content.SharedPreferences.Editor editor = prefs.edit();
+		editor.clear();
+
+		for (ApplicationRunInformation appInfo : AppDiscoverer.getInstance()
+				.getAllAppRunInfo()) {
+			String appSerialized = serializeAppToString(appInfo);
+
+			editor.putString(ApplicationRunInformation
+					.serializeComponentName(appInfo.getComponentName()),
+					appSerialized);
+		}
+
+		editor.commit();
+	}
+
+	public void saveAppSwitcherData() {
+		persistAppRunInfo(this);
+	}
+
+	private String serializeAppToString(ApplicationRunInformation appInfo) {
+		StringBuffer sb = new StringBuffer();
+
+		sb.append(appInfo.getCount()).append(APP_RUN_INFO_SEPARATOR)
+				.append(DATE_FORMATTER.format(appInfo.getLastExecution()));
+
+		return sb.toString();
+	}
+
+	private ApplicationRunInformation deserializeFromString(String component,
+			String data) {
+
+		Log.d(TAG, "fairphone debug > " + data);
+		String[] splits = data.split(APP_RUN_INFO_SEPARATOR);
+		int count = Integer.parseInt(splits[0]);
+		Date lastExecution = null;
+		try {
+			lastExecution = DATE_FORMATTER.parse(splits[1]);
+		} catch (ParseException e) {
+			e.printStackTrace();
+			lastExecution = Calendar.getInstance().getTime();
+		}
+
+		ApplicationRunInformation appRunInfo = new ApplicationRunInformation(
+				ApplicationRunInformation.deserializeComponentName(component),
+				count);
+		appRunInfo.setLastExecution(lastExecution);
+
+		return appRunInfo;
+	}
+
+	public void loadAppRunInfo(Context context) {
+		// Most Used
+		Log.d("ui", "loadAppRunInfos: loading ");
+		AppDiscoverer.getInstance().resetState();
+
+		SharedPreferences prefs = context.getSharedPreferences(
+				PREFS_APP_SWITCHER_APPS_DATA, 0);
+
+		List<ApplicationRunInformation> allApps = new ArrayList<ApplicationRunInformation>();
+
+		Map<String, ?> componentNames = prefs.getAll();
+		for (String component : componentNames.keySet()) {
+			String data = prefs.getString(component, "");
+
+			if (data.length() == 0) {
+				continue;
+			}
+
+			allApps.add(deserializeFromString(component, data));
+		}
+
+		// set the all apps
+		AppDiscoverer.getInstance().setAllRunInfo(allApps);
+	}
+	
+	private BroadcastReceiver mBCastAppSwitcherAllApps;
+	private BroadcastReceiver mBCastAppSwitcherReset;
+	private BroadcastReceiver mBCastAppSwitcherLauncher;
+
+	private void clearAppSwitcherBroadcastReceivers(){
+		unregisterReceiver(mBCastAppSwitcherAllApps);
+		unregisterReceiver(mBCastAppSwitcherReset);
+		unregisterReceiver(mBCastAppSwitcherLauncher);
+	}
+	
+	private void setupBroadcastReceivers() {
+		// launching the application
+		
+		mBCastAppSwitcherAllApps = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+				Log.i(TAG,"Received a call from widget....Show all apps");
+				showAllApps(true);
+			}
+		};
+		
+		mBCastAppSwitcherReset = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+				Log.i(TAG,"Received a call from widget....Reset");
+
+				DialogFragment newFragment = new ResetDialogFragment();
+				newFragment.show(getFragmentManager(), "reset");
+			}
+		};
+		
+		mBCastAppSwitcherLauncher = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+
+				String packageName = intent.getStringExtra(Launcher.APP_PACKAGE);
+				String className = intent
+						.getStringExtra(Launcher.APP_CLASS_NAME);
+
+				Log.i(TAG,"Received a call from widget....Launch App "
+								+ packageName + " - " + className);
+
+				Intent launchIntent = getPackageManager()
+						.getLaunchIntentForPackage(packageName);
+
+				if (launchIntent != null) {
+					launchIntent.setComponent(new ComponentName(packageName,
+							className));
+					startActivity(null, launchIntent, "edgeSwipeLaunch");
+				}
+			}
+		};
+		
+		
+		
+		registerReceiver(mBCastAppSwitcherAllApps, new IntentFilter(APP_SWITCHER_ALL_APPS));
+
+		registerReceiver(mBCastAppSwitcherReset, new IntentFilter(Launcher.APP_SWITCHER_RESET));
+
+		registerReceiver(mBCastAppSwitcherLauncher, new IntentFilter(Launcher.APP_SWITCHER_LAUNCH_APP));
+	}
+	
+	
+
+	/**
+	 * Setup the edge favorite apps launcher.
+	 */
+	private void setupFavoriteApps() {
+		mAppMenuContainerView = (FrameLayout) findViewById(R.id.appMenuContainer);
+		mAppMenuHelper = new EdgeSwipeAppMenuHelper(this, mDragController,
+				mAppMenuContainerView, this);
+		mAppMenuHelper.updateIcons();
+	}
+
+	public EdgeSwipeAppMenuHelper getEdgeSwipeMenuHelper() {
+		return mAppMenuHelper;
+	}
+
+	protected void onUserLeaveHint() {
+		super.onUserLeaveHint();
+		sPausedFromUserAction = true;
+	}
+
+	private void updateGlobalIcons() {
+		// If we have a saved version of these external icons, we load them up
+		// immediately
+		int coi = getCurrentOrientationIndexForGlobalIcons();
+		if (
+		sAppMarketIcon[coi] == null) {
+			updateAppMarketIcon();
+		}
+		if (sAppMarketIcon[coi] != null) {
+			updateAppMarketIcon(sAppMarketIcon[coi]);
+		}
+	}
+
+	private void checkForLocaleChange() {
+		if (sLocaleConfiguration == null) {
+			new AsyncTask<Void, Void, LocaleConfiguration>() {
+				@Override
+				protected LocaleConfiguration doInBackground(Void... unused) {
+					LocaleConfiguration localeConfiguration = new LocaleConfiguration();
+					readConfiguration(Launcher.this, localeConfiguration);
+					return localeConfiguration;
+				}
+
+				@Override
+				protected void onPostExecute(LocaleConfiguration result) {
+					sLocaleConfiguration = result;
+					checkForLocaleChange(); // recursive, but now with a locale
+											// configuration
+				}
+			}.execute();
+			return;
+		}
+
+		final Configuration configuration = getResources().getConfiguration();
+
+		final String previousLocale = sLocaleConfiguration.locale;
+		final String locale = configuration.locale.toString();
+
+		final int previousMcc = sLocaleConfiguration.mcc;
+		final int mcc = configuration.mcc;
+
+		final int previousMnc = sLocaleConfiguration.mnc;
+		final int mnc = configuration.mnc;
+
+		boolean localeChanged = !locale.equals(previousLocale)
+				|| mcc != previousMcc || mnc != previousMnc;
+
+		if (localeChanged) {
+			sLocaleConfiguration.locale = locale;
+			sLocaleConfiguration.mcc = mcc;
+			sLocaleConfiguration.mnc = mnc;
+
+			mIconCache.flush();
+
+			final LocaleConfiguration localeConfiguration = sLocaleConfiguration;
+			new Thread("WriteLocaleConfiguration") {
+				@Override
+				public void run() {
+					writeConfiguration(Launcher.this, localeConfiguration);
+				}
+			}.start();
+		}
+	}
+
+	private static class LocaleConfiguration {
+		public String locale;
+		public int mcc = -1;
+		public int mnc = -1;
+	}
+
+	private static void readConfiguration(Context context,
+			LocaleConfiguration configuration) {
+		DataInputStream in = null;
+		try {
+			in = new DataInputStream(context.openFileInput(PREFERENCES));
+			configuration.locale = in.readUTF();
+			configuration.mcc = in.readInt();
+			configuration.mnc = in.readInt();
+		} catch (FileNotFoundException e) {
+			// Ignore
+		} catch (IOException e) {
+			// Ignore
+		} finally {
+			if (in != null) {
+				try {
+					in.close();
+				} catch (IOException e) {
+					// Ignore
+				}
+			}
+		}
+	}
+
+	private static void writeConfiguration(Context context,
+			LocaleConfiguration configuration) {
+		DataOutputStream out = null;
+		try {
+			out = new DataOutputStream(context.openFileOutput(PREFERENCES,
+					MODE_PRIVATE));
+			out.writeUTF(configuration.locale);
+			out.writeInt(configuration.mcc);
+			out.writeInt(configuration.mnc);
+			out.flush();
+		} catch (FileNotFoundException e) {
+			// Ignore
+		} catch (IOException e) {
+			// noinspection ResultOfMethodCallIgnored
+			context.getFileStreamPath(PREFERENCES).delete();
+		} finally {
+			if (out != null) {
+				try {
+					out.close();
+				} catch (IOException e) {
+					// Ignore
+				}
+			}
+		}
+	}
+
+	public DragLayer getDragLayer() {
+		return mDragLayer;
+	}
+
+	boolean isDraggingEnabled() {
+		// We prevent dragging when we are loading the workspace as it is
+		// possible to pick up a view
+		// that is subsequently removed from the workspace in startBinding().
+		return !mModel.isLoadingWorkspace();
+	}
+
+	static int getScreen() {
+		synchronized (sLock) {
+			return sScreen;
+		}
+	}
+
+	static void setScreen(int screen) {
+		synchronized (sLock) {
+			sScreen = screen;
+		}
+	}
+
+	/**
+	 * Returns whether we should delay spring loaded mode -- for shortcuts and
+	 * widgets that have a configuration step, this allows the proper animations
+	 * to run after other transitions.
+	 */
+	private boolean completeAdd(PendingAddArguments args) {
+		boolean result = false;
+		switch (args.requestCode) {
+		case REQUEST_PICK_APPLICATION:
+			completeAddApplication(args.intent, args.container, args.screen,
+					args.cellX, args.cellY);
+			break;
+		case REQUEST_PICK_SHORTCUT:
+			processShortcut(args.intent);
+			break;
+		case REQUEST_CREATE_SHORTCUT:
+			completeAddShortcut(args.intent, args.container, args.screen,
+					args.cellX, args.cellY);
+			result = true;
+			break;
+		case REQUEST_CREATE_APPWIDGET:
+			int appWidgetId = args.intent.getIntExtra(
+					AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+			completeAddAppWidget(appWidgetId, args.container, args.screen,
+					null, null);
+			result = true;
+			break;
+		case REQUEST_PICK_WALLPAPER:
+			// We just wanted the activity result here so we can clear
+			// mWaitingForResult
+			break;
+		case REQUEST_EDIT_FAVORITES:
+			break;
+		default:
+			break;
+		}
+		// Before adding this resetAddInfo(), after a shortcut was added to a
+		// workspace screen,
+		// if you turned the screen off and then back while in All Apps,
+		// Launcher would not
+		// return to the workspace. Clearing mAddInfo.container here fixes this
+		// issue
+		resetAddInfo();
+		return result;
+	}
+
+	@Override
+	protected void onActivityResult(final int requestCode,
+			final int resultCode, final Intent data) {
+
+		boolean delayExitSpringLoadedMode = false;
+
+		mWaitingForResult = false;
+
+		if (requestCode == REQUEST_EDIT_FAVORITES) {
+			mAppMenuHelper.updateIcons();
+
+			mWaitingForResult = false;
+			return;
+		}
+
+		if (requestCode == REQUEST_BIND_APPWIDGET) {
+			int appWidgetId = data != null ? data.getIntExtra(
+					AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
+			if (resultCode == RESULT_CANCELED) {
+				completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
+			} else if (resultCode == RESULT_OK) {
+				addAppWidgetImpl(appWidgetId, mPendingAddInfo, null,
+						mPendingAddWidgetInfo);
+			}
+			return;
+		}
+
+		boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET);
+		// We have special handling for widgets
+		if (isWidgetDrop) {
+			int appWidgetId = data != null ? data.getIntExtra(
+					AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
+			if (appWidgetId < 0) {
+				Log.e(TAG,
+						"Error: appWidgetId (EXTRA_APPWIDGET_ID) was not returned from the \\"
+								+ "widget configuration activity.");
+				completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
+			} else {
+				completeTwoStageWidgetDrop(resultCode, appWidgetId);
+			}
+			return;
+		}
+
+		// The pattern used here is that a user PICKs a specific application,
+		// which, depending on the target, might need to CREATE the actual
+		// target.
+
+		// For example, the user would PICK_SHORTCUT for "Music playlist", and
+		// we
+		// launch over to the Music app to actually CREATE_SHORTCUT.
+		if (resultCode == RESULT_OK
+				&& mPendingAddInfo.container != ItemInfo.NO_ID) {
+			final PendingAddArguments args = new PendingAddArguments();
+			args.requestCode = requestCode;
+			args.intent = data;
+			args.container = mPendingAddInfo.container;
+			args.screen = mPendingAddInfo.screen;
+			args.cellX = mPendingAddInfo.cellX;
+			args.cellY = mPendingAddInfo.cellY;
+			if (isWorkspaceLocked()) {
+				sPendingAddList.add(args);
+			} else {
+				delayExitSpringLoadedMode = completeAdd(args);
+			}
+		}
+		mDragLayer.clearAnimatedView();
+		// Exit spring loaded mode if necessary after cancelling the
+		// configuration of a widget
+		exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED),
+				delayExitSpringLoadedMode, null);
+	}
+
+	private void completeTwoStageWidgetDrop(final int resultCode,
+			final int appWidgetId) {
+		CellLayout cellLayout = (CellLayout) mWorkspace
+				.getChildAt(mPendingAddInfo.screen);
+		Runnable onCompleteRunnable = null;
+		int animationType = 0;
+
+		AppWidgetHostView boundWidget = null;
+		if (resultCode == RESULT_OK) {
+			animationType = Workspace.COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION;
+			final AppWidgetHostView layout = mAppWidgetHost.createView(this,
+					appWidgetId, mPendingAddWidgetInfo);
+			boundWidget = layout;
+			onCompleteRunnable = new Runnable() {
+				@Override
+				public void run() {
+					completeAddAppWidget(appWidgetId,
+							mPendingAddInfo.container, mPendingAddInfo.screen,
+							layout, null);
+					exitSpringLoadedDragModeDelayed(
+							(resultCode != RESULT_CANCELED), false, null);
+				}
+			};
+		} else if (resultCode == RESULT_CANCELED) {
+			animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION;
+			onCompleteRunnable = new Runnable() {
+				@Override
+				public void run() {
+					exitSpringLoadedDragModeDelayed(
+							(resultCode != RESULT_CANCELED), false, null);
+				}
+			};
+		}
+		if (mDragLayer.getAnimatedView() != null) {
+			mWorkspace.animateWidgetDrop(mPendingAddInfo, cellLayout,
+					(DragView) mDragLayer.getAnimatedView(),
+					onCompleteRunnable, animationType, boundWidget, true);
+		} else {
+			// The animated view may be null in the case of a rotation during
+			// widget configuration
+			onCompleteRunnable.run();
+		}
+	}
+
+	@Override
+	protected void onResume() {
+		super.onResume();
+
+		// Restore the previous launcher state
+		if (mOnResumeState == State.WORKSPACE) {
+			showWorkspace(false);
+		} else if (mOnResumeState == State.APPS_CUSTOMIZE) {
+			showAllApps(false);
+		}
+		mOnResumeState = State.NONE;
+
+		// Background was set to gradient in onPause(), restore to black if in
+		// all apps.
+		setWorkspaceBackground(mState == State.WORKSPACE);
+
+		// Process any items that were added while Launcher was away
+		InstallShortcutReceiver.flushInstallQueue(this);
+
+		mPaused = false;
+		sPausedFromUserAction = false;
+		if (mRestoring || mOnResumeNeedsLoad) {
+			mWorkspaceLoading = true;
+			mModel.startLoader(true, -1);
+			mRestoring = false;
+			mOnResumeNeedsLoad = false;
+		}
+
+		// Reset the pressed state of icons that were locked in the press state
+		// while activities
+		// were launching
+		if (mWaitingForResume != null) {
+			// Resets the previous workspace icon press state
+			mWaitingForResume.setStayPressed(false);
+		}
+		if (mAppsCustomizeContent != null) {
+			// Resets the previous all apps icon press state
+			mAppsCustomizeContent.resetDrawableState();
+		}
+		// It is possible that widgets can receive updates while launcher is not
+		// in the foreground.
+		// Consequently, the widgets will be inflated in the orientation of the
+		// foreground activity
+		// (framework issue). On resuming, we ensure that any widgets are
+		// inflated for the current
+		// orientation.
+		getWorkspace().reinflateWidgetsIfNecessary();
+
+		// Again, as with the above scenario, it's possible that one or more of
+		// the global icons
+		// were updated in the wrong orientation.
+		updateGlobalIcons();
+
+		// show OOBE
+		startOOBEActivityOnFirstUse(SHOW_OOBE_EDGE_SWIPE_MENU,
+				OOBEActivity.OOBE_DEVICE_TUTORIAL);
+		
+		// broadcast receivers for the appSwitcher
+		setupBroadcastReceivers();
+		
+	}
+
+	@Override
+	protected void onPause() {
+		// NOTE: We want all transitions from launcher to act as if the
+		// wallpaper were enabled
+		// to be consistent. So re-enable the flag here, and we will re-disable
+		// it as necessary
+		// when Launcher resumes and we are still in AllApps.
+		updateWallpaperVisibility(true);
+
+		super.onPause();
+		mPaused = true;
+		mDragController.cancelDrag();
+		mDragController.resetLastGestureUpTime();
+
+		persistAppRunInfo(this);
+		
+		clearAppSwitcherBroadcastReceivers();
+	}
+
+	@Override
+	public Object onRetainNonConfigurationInstance() {
+		// Flag the loader to stop early before switching
+		mModel.stopLoader();
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.surrender();
+		}
+		return Boolean.TRUE;
+	}
+
+
+	private boolean acceptFilter() {
+		final InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+		return !inputManager.isFullscreenMode();
+	}
+
+	@Override
+	public boolean onKeyDown(int keyCode, KeyEvent event) {
+		final int uniChar = event.getUnicodeChar();
+		final boolean handled = super.onKeyDown(keyCode, event);
+		final boolean isKeyNotWhitespace = uniChar > 0
+				&& !Character.isWhitespace(uniChar);
+		if (!handled && acceptFilter() && isKeyNotWhitespace) {
+			boolean gotKey = TextKeyListener.getInstance().onKeyDown(
+					mWorkspace, mDefaultKeySsb, keyCode, event);
+			if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
+				// something usable has been typed - start a search
+				// the typed text will be retrieved and cleared by
+				// showSearchDialog()
+				// If there are multiple keystrokes before the search dialog
+				// takes focus,
+				// onSearchRequested() will be called for every keystroke,
+				// but it is idempotent, so it's fine.
+				return onSearchRequested();
+			}
+		}
+
+		// Eat the long press event so the keyboard doesn't come up.
+		if (keyCode == KeyEvent.KEYCODE_MENU && event.isLongPress()) {
+			return true;
+		}
+
+		return handled;
+	}
+
+	private String getTypedText() {
+		return mDefaultKeySsb.toString();
+	}
+
+	private void clearTypedText() {
+		mDefaultKeySsb.clear();
+		mDefaultKeySsb.clearSpans();
+		Selection.setSelection(mDefaultKeySsb, 0);
+	}
+
+	/**
+	 * Given the integer (ordinal) value of a State enum instance, convert it to
+	 * a variable of type State
+	 */
+	private static State intToState(int stateOrdinal) {
+		State state = State.WORKSPACE;
+		final State[] stateValues = State.values();
+		for (int i = 0; i < stateValues.length; i++) {
+			if (stateValues[i].ordinal() == stateOrdinal) {
+				state = stateValues[i];
+				break;
+			}
+		}
+		return state;
+	}
+
+	/**
+	 * Restores the previous state, if it exists.
+	 * 
+	 * @param savedState
+	 *            The previous state.
+	 */
+	private void restoreState(Bundle savedState) {
+		if (savedState == null) {
+			return;
+		}
+
+		State state = intToState(savedState.getInt(RUNTIME_STATE,
+				State.WORKSPACE.ordinal()));
+		if (state == State.APPS_CUSTOMIZE) {
+			mOnResumeState = State.APPS_CUSTOMIZE;
+		}
+
+		int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN, -1);
+		if (currentScreen > -1) {
+			mWorkspace.setCurrentPage(currentScreen);
+		}
+
+		final long pendingAddContainer = savedState.getLong(
+				RUNTIME_STATE_PENDING_ADD_CONTAINER, -1);
+		final int pendingAddScreen = savedState.getInt(
+				RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
+
+		if (pendingAddContainer != ItemInfo.NO_ID && pendingAddScreen > -1) {
+			mPendingAddInfo.container = pendingAddContainer;
+			mPendingAddInfo.screen = pendingAddScreen;
+			mPendingAddInfo.cellX = savedState
+					.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
+			mPendingAddInfo.cellY = savedState
+					.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
+			mPendingAddInfo.spanX = savedState
+					.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X);
+			mPendingAddInfo.spanY = savedState
+					.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y);
+			mPendingAddWidgetInfo = savedState
+					.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
+			mWaitingForResult = true;
+			mRestoring = true;
+		}
+
+		boolean renameFolder = savedState.getBoolean(
+				RUNTIME_STATE_PENDING_FOLDER_RENAME, false);
+		if (renameFolder) {
+			long id = savedState
+					.getLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID);
+			mFolderInfo = mModel.getFolderById(this, sFolders, id);
+			mRestoring = true;
+		}
+
+		// Restore the AppsCustomize tab
+		if (mAppsCustomizeTabHost != null) {
+			String curTab = savedState.getString("apps_customize_currentTab");
+			if (curTab != null) {
+				mAppsCustomizeTabHost
+						.setContentTypeImmediate(mAppsCustomizeTabHost
+								.getContentTypeForTabTag(curTab));
+				mAppsCustomizeContent.loadAssociatedPages(mAppsCustomizeContent
+						.getCurrentPage());
+			}
+
+			int currentIndex = savedState.getInt("apps_customize_currentIndex");
+			mAppsCustomizeContent.restorePageForIndex(currentIndex);
+		}
+	}
+
+	/**
+	 * Finds all the views we need and configure them properly.
+	 */
+	private void setupViews() {
+		final DragController dragController = mDragController;
+
+		// launcherView - The frame for all the shizzle of the launcher
+		mLauncherView = findViewById(R.id.launcher);
+		// The layer above the workspace that will enable people to drag along
+		// the workspace
+		mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
+		// the workspace itself
+		mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
+
+		mLauncherView
+				.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+		mWorkspaceBackgroundDrawable = getResources().getDrawable(
+				R.drawable.workspace_bg);
+		mBlackBackgroundDrawable = new ColorDrawable(Color.BLACK);
+
+		// Setup the drag layer
+		mDragLayer.setup(this, dragController);
+
+		// Setup the workspace
+		mWorkspace.setHapticFeedbackEnabled(false);
+		mWorkspace.setOnLongClickListener(this);
+		mWorkspace.setup(dragController);
+		dragController.addDragListener(mWorkspace);
+
+		// Get the search/delete bar
+		mSearchDropTargetBar = (SearchDropTargetBar) mDragLayer
+				.findViewById(R.id.qsb_bar);
+
+		// Setup AppsCustomize
+		mAppsCustomizeTabHost = (AppsCustomizeTabHost) findViewById(R.id.apps_customize_pane);
+		mAppsCustomizeContent = (AppsCustomizePagedView) mAppsCustomizeTabHost
+				.findViewById(R.id.apps_customize_pane_content);
+		mAppsCustomizeContent.setup(this, dragController);
+
+		// Setup the drag controller (drop targets have to be added in reverse
+		// order in priority)
+		dragController.setDragScoller(mWorkspace);
+		dragController.setScrollView(mDragLayer);
+		dragController.setMoveTarget(mWorkspace);
+		dragController.addDropTarget(mWorkspace);
+		if (mSearchDropTargetBar != null) {
+			mSearchDropTargetBar.setup(this, dragController);
+		}
+		
+		// 
+		mSystemUpdaterWindow = (FrameLayout)findViewById(R.id.systemUpdater);
+		
+		mSystemUpdaterWindow.setVisibility( View.GONE );
+	}
+	
+	
+
+	/**
+	 * Creates a view representing a shortcut.
+	 * 
+	 * @param info
+	 *            The data structure describing the shortcut.
+	 * 
+	 * @return A View inflated from R.layout.application.
+	 */
+	View createShortcut(ShortcutInfo info) {
+		return createShortcut(R.layout.application,
+				(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
+				info);
+	}
+
+	/**
+	 * Creates a view representing a shortcut inflated from the specified
+	 * resource.
+	 * 
+	 * @param layoutResId
+	 *            The id of the XML layout used to create the shortcut.
+	 * @param parent
+	 *            The group the shortcut belongs to.
+	 * @param info
+	 *            The data structure describing the shortcut.
+	 * 
+	 * @return A View inflated from layoutResId.
+	 */
+	View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
+		BubbleTextView favorite = (BubbleTextView) mInflater.inflate(
+				layoutResId, parent, false);
+		favorite.applyFromShortcutInfo(info, mIconCache);
+		favorite.setOnClickListener(this);
+		return favorite;
+	}
+
+	/**
+	 * Add an application shortcut to the workspace.
+	 * 
+	 * @param data
+	 *            The intent describing the application.
+	 * @param cellInfo
+	 *            The position on screen where to create the shortcut.
+	 */
+	void completeAddApplication(Intent data, long container, int screen,
+			int cellX, int cellY) {
+		final int[] cellXY = mTmpAddItemCellCoordinates;
+		final CellLayout layout = getCellLayout(container, screen);
+
+		// First we check if we already know the exact location where we want to
+		// add this item.
+		if (cellX >= 0 && cellY >= 0) {
+			cellXY[0] = cellX;
+			cellXY[1] = cellY;
+		} else if (!layout.findCellForSpan(cellXY, 1, 1)) {
+			showOutOfSpaceMessage(isHotseatLayout(layout));
+			return;
+		}
+
+		final ShortcutInfo info = mModel.getShortcutInfo(getPackageManager(),
+				data, this);
+
+		if (info != null) {
+			info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK
+					| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+			info.container = ItemInfo.NO_ID;
+			mWorkspace.addApplicationShortcut(info, layout, container, screen,
+					cellXY[0], cellXY[1], isWorkspaceLocked(), cellX, cellY);
+		} else {
+			Log.e(TAG, "Couldn't find ActivityInfo for selected application: "
+					+ data);
+		}
+	}
+
+	/**
+	 * Add a shortcut to the workspace.
+	 * 
+	 * @param data
+	 *            The intent describing the shortcut.
+	 * @param cellInfo
+	 *            The position on screen where to create the shortcut.
+	 */
+	private void completeAddShortcut(Intent data, long container, int screen,
+			int cellX, int cellY) {
+		int[] cellXY = mTmpAddItemCellCoordinates;
+		int[] touchXY = mPendingAddInfo.dropPos;
+		CellLayout layout = getCellLayout(container, screen);
+
+		boolean foundCellSpan = false;
+
+		ShortcutInfo info = mModel.infoFromShortcutIntent(this, data, null);
+		if (info == null) {
+			return;
+		}
+		final View view = createShortcut(info);
+
+		// First we check if we already know the exact location where we want to
+		// add this item.
+		if (cellX >= 0 && cellY >= 0) {
+			cellXY[0] = cellX;
+			cellXY[1] = cellY;
+			foundCellSpan = true;
+
+			// If appropriate, either create a folder or add to an existing
+			// folder
+			if (mWorkspace.createUserFolderIfNecessary(view, container, layout,
+					cellXY, 0, true, null, null)) {
+				return;
+			}
+			DragObject dragObject = new DragObject();
+			dragObject.dragInfo = info;
+			if (mWorkspace.addToExistingFolderIfNecessary(view, layout, cellXY,
+					0, dragObject, true)) {
+				return;
+			}
+		} else if (touchXY != null) {
+			// when dragging and dropping, just find the closest free spot
+			int[] result = layout.findNearestVacantArea(touchXY[0], touchXY[1],
+					1, 1, cellXY);
+			foundCellSpan = (result != null);
+		} else {
+			foundCellSpan = layout.findCellForSpan(cellXY, 1, 1);
+		}
+
+		if (!foundCellSpan) {
+			showOutOfSpaceMessage(isHotseatLayout(layout));
+			return;
+		}
+
+		LauncherModel.addItemToDatabase(this, info, container, screen,
+				cellXY[0], cellXY[1], false);
+
+		if (!mRestoring) {
+			mWorkspace.addInScreen(view, container, screen, cellXY[0],
+					cellXY[1], 1, 1, isWorkspaceLocked());
+		}
+	}
+
+	static int[] getSpanForWidget(Context context, ComponentName component,
+			int minWidth, int minHeight) {
+		Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(context,
+				component, null);
+		// We want to account for the extra amount of padding that we are adding
+		// to the widget
+		// to ensure that it gets the full amount of space that it has requested
+		int requiredWidth = minWidth + padding.left + padding.right;
+		int requiredHeight = minHeight + padding.top + padding.bottom;
+		return CellLayout.rectToCell(context.getResources(), requiredWidth,
+				requiredHeight, null);
+	}
+
+	static int[] getSpanForWidget(Context context, AppWidgetProviderInfo info) {
+		return getSpanForWidget(context, info.provider, info.minWidth,
+				info.minHeight);
+	}
+
+	static int[] getMinSpanForWidget(Context context, AppWidgetProviderInfo info) {
+		return getSpanForWidget(context, info.provider, info.minResizeWidth,
+				info.minResizeHeight);
+	}
+
+	static int[] getSpanForWidget(Context context, PendingAddWidgetInfo info) {
+		return getSpanForWidget(context, info.componentName, info.minWidth,
+				info.minHeight);
+	}
+
+	static int[] getMinSpanForWidget(Context context, PendingAddWidgetInfo info) {
+		return getSpanForWidget(context, info.componentName,
+				info.minResizeWidth, info.minResizeHeight);
+	}
+
+	/**
+	 * Add a widget to the workspace.
+	 * 
+	 * @param appWidgetId
+	 *            The app widget id
+	 * @param cellInfo
+	 *            The position on screen where to create the widget.
+	 */
+	private void completeAddAppWidget(final int appWidgetId, long container,
+			int screen, AppWidgetHostView hostView,
+			AppWidgetProviderInfo appWidgetInfo) {
+		if (appWidgetInfo == null) {
+			appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+		}
+
+		// Calculate the grid spans needed to fit this widget
+		CellLayout layout = getCellLayout(container, screen);
+
+		int[] minSpanXY = getMinSpanForWidget(this, appWidgetInfo);
+		int[] spanXY = getSpanForWidget(this, appWidgetInfo);
+
+		// Try finding open space on Launcher screen
+		// We have saved the position to which the widget was dragged-- this
+		// really only matters
+		// if we are placing widgets on a "spring-loaded" screen
+		int[] cellXY = mTmpAddItemCellCoordinates;
+		int[] touchXY = mPendingAddInfo.dropPos;
+		int[] finalSpan = new int[2];
+		boolean foundCellSpan = false;
+		if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
+			cellXY[0] = mPendingAddInfo.cellX;
+			cellXY[1] = mPendingAddInfo.cellY;
+			spanXY[0] = mPendingAddInfo.spanX;
+			spanXY[1] = mPendingAddInfo.spanY;
+			foundCellSpan = true;
+		} else if (touchXY != null) {
+			// when dragging and dropping, just find the closest free spot
+			int[] result = layout.findNearestVacantArea(touchXY[0], touchXY[1],
+					minSpanXY[0], minSpanXY[1], spanXY[0], spanXY[1], cellXY,
+					finalSpan);
+			spanXY[0] = finalSpan[0];
+			spanXY[1] = finalSpan[1];
+			foundCellSpan = (result != null);
+		} else {
+			foundCellSpan = layout.findCellForSpan(cellXY, minSpanXY[0],
+					minSpanXY[1]);
+		}
+
+		if (!foundCellSpan) {
+			if (appWidgetId != -1) {
+				// Deleting an app widget ID is a void call but writes to disk
+				// before returning
+				// to the caller...
+				new Thread("deleteAppWidgetId") {
+					public void run() {
+						mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+					}
+				}.start();
+			}
+			showOutOfSpaceMessage(isHotseatLayout(layout));
+			return;
+		}
+
+		// Build Launcher-specific widget info and save to database
+		LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(
+				appWidgetId, appWidgetInfo.provider);
+		launcherInfo.spanX = spanXY[0];
+		launcherInfo.spanY = spanXY[1];
+		launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
+		launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
+
+		LauncherModel.addItemToDatabase(this, launcherInfo, container, screen,
+				cellXY[0], cellXY[1], false);
+
+		if (!mRestoring) {
+			if (hostView == null) {
+				// Perform actual inflation because we're live
+				launcherInfo.hostView = mAppWidgetHost.createView(this,
+						appWidgetId, appWidgetInfo);
+				launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);
+			} else {
+				// The AppWidgetHostView has already been inflated and
+				// instantiated
+				launcherInfo.hostView = hostView;
+			}
+
+			launcherInfo.hostView.setTag(launcherInfo);
+			launcherInfo.hostView.setVisibility(View.VISIBLE);
+			launcherInfo.notifyWidgetSizeChanged(this);
+
+			mWorkspace.addInScreen(launcherInfo.hostView, container, screen,
+					cellXY[0], cellXY[1], launcherInfo.spanX,
+					launcherInfo.spanY, isWorkspaceLocked());
+
+			addWidgetToAutoAdvanceIfNeeded(launcherInfo.hostView, appWidgetInfo);
+		}
+		resetAddInfo();
+	}
+
+	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			final String action = intent.getAction();
+			if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+				mUserPresent = false;
+				mDragLayer.clearAllResizeFrames();
+				updateRunning();
+
+				// Reset AllApps to its initial state only if we are not in the
+				// middle of
+				// processing a multi-step drop
+				if (mAppsCustomizeTabHost != null
+						&& mPendingAddInfo.container == ItemInfo.NO_ID) {
+					mAppsCustomizeTabHost.reset();
+					showWorkspace(false);
+				}
+			} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
+				mUserPresent = true;
+				updateRunning();
+			}
+		}
+	};
+
+	@Override
+	public void onAttachedToWindow() {
+		super.onAttachedToWindow();
+
+		// Listen for broadcasts related to user-presence
+		final IntentFilter filter = new IntentFilter();
+		filter.addAction(Intent.ACTION_SCREEN_OFF);
+		filter.addAction(Intent.ACTION_USER_PRESENT);
+		registerReceiver(mReceiver, filter);
+
+		mAttached = true;
+		mVisible = true;
+	}
+
+	@Override
+	public void onDetachedFromWindow() {
+		super.onDetachedFromWindow();
+		mVisible = false;
+
+		if (mAttached) {
+			unregisterReceiver(mReceiver);
+			
+			mAttached = false;
+		}
+		updateRunning();
+	}
+
+	public void onWindowVisibilityChanged(int visibility) {
+		mVisible = visibility == View.VISIBLE;
+		updateRunning();
+		// The following code used to be in onResume, but it turns out onResume
+		// is called when
+		// you're in All Apps and click home to go to the workspace.
+		// onWindowVisibilityChanged
+		// is a more appropriate event to handle
+		if (mVisible) {
+			mAppsCustomizeTabHost.onWindowVisible();
+			if (!mWorkspaceLoading) {
+				final ViewTreeObserver observer = mWorkspace
+						.getViewTreeObserver();
+				// We want to let Launcher draw itself at least once before we
+				// force it to build
+				// layers on all the workspace pages, so that transitioning to
+				// Launcher from other
+				// apps is nice and speedy. Usually the first call to preDraw
+				// doesn't correspond to
+				// a true draw so we wait until the second preDraw call to be
+				// safe
+				observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+					public boolean onPreDraw() {
+						// We delay the layer building a bit in order to give
+						// other message processing a time to run. In particular
+						// this avoids a delay in hiding the IME if it was
+						// currently shown, because doing that may involve
+						// some communication back with the app.
+						mWorkspace.postDelayed(mBuildLayersRunnable, 500);
+
+						observer.removeOnPreDrawListener(this);
+						return true;
+					}
+				});
+			}
+			// When Launcher comes back to foreground, a different Activity
+			// might be responsible for
+			// the app market intent, so refresh the icon
+			updateAppMarketIcon();
+			clearTypedText();
+		}
+	}
+
+	private void sendAdvanceMessage(long delay) {
+		mHandler.removeMessages(ADVANCE_MSG);
+		Message msg = mHandler.obtainMessage(ADVANCE_MSG);
+		mHandler.sendMessageDelayed(msg, delay);
+		mAutoAdvanceSentTime = System.currentTimeMillis();
+	}
+
+	private void updateRunning() {
+		boolean autoAdvanceRunning = mVisible && mUserPresent
+				&& !mWidgetsToAdvance.isEmpty();
+		if (autoAdvanceRunning != mAutoAdvanceRunning) {
+			mAutoAdvanceRunning = autoAdvanceRunning;
+			if (autoAdvanceRunning) {
+				long delay = mAutoAdvanceTimeLeft == -1 ? mAdvanceInterval
+						: mAutoAdvanceTimeLeft;
+				sendAdvanceMessage(delay);
+			} else {
+				if (!mWidgetsToAdvance.isEmpty()) {
+					mAutoAdvanceTimeLeft = Math
+							.max(0,
+									mAdvanceInterval
+											- (System.currentTimeMillis() - mAutoAdvanceSentTime));
+				}
+				mHandler.removeMessages(ADVANCE_MSG);
+				mHandler.removeMessages(0); // Remove messages sent using
+											// postDelayed()
+			}
+		}
+	}
+
+	private final Handler mHandler = new Handler() {
+		@Override
+		public void handleMessage(Message msg) {
+			if (msg.what == ADVANCE_MSG) {
+				int i = 0;
+				for (View key : mWidgetsToAdvance.keySet()) {
+					final View v = key
+							.findViewById(mWidgetsToAdvance.get(key).autoAdvanceViewId);
+					final int delay = mAdvanceStagger * i;
+					if (v instanceof Advanceable) {
+						postDelayed(new Runnable() {
+							public void run() {
+								((Advanceable) v).advance();
+							}
+						}, delay);
+					}
+					i++;
+				}
+				sendAdvanceMessage(mAdvanceInterval);
+			}
+		}
+	};
+
+	void addWidgetToAutoAdvanceIfNeeded(View hostView,
+			AppWidgetProviderInfo appWidgetInfo) {
+		if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1)
+			return;
+		View v = hostView.findViewById(appWidgetInfo.autoAdvanceViewId);
+		if (v instanceof Advanceable) {
+			mWidgetsToAdvance.put(hostView, appWidgetInfo);
+			((Advanceable) v).fyiWillBeAdvancedByHostKThx();
+			updateRunning();
+		}
+	}
+
+	void removeWidgetToAutoAdvance(View hostView) {
+		if (mWidgetsToAdvance.containsKey(hostView)) {
+			mWidgetsToAdvance.remove(hostView);
+			updateRunning();
+		}
+	}
+
+	public void removeAppWidget(LauncherAppWidgetInfo launcherInfo) {
+		removeWidgetToAutoAdvance(launcherInfo.hostView);
+		launcherInfo.hostView = null;
+	}
+
+	void showOutOfSpaceMessage(boolean isHotseatLayout) {
+		int strId = (isHotseatLayout ? R.string.hotseat_out_of_space
+				: R.string.out_of_space);
+		Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
+	}
+
+	public LauncherAppWidgetHost getAppWidgetHost() {
+		return mAppWidgetHost;
+	}
+
+	public LauncherModel getModel() {
+		return mModel;
+	}
+
+	void closeSystemDialogs() {
+		getWindow().closeAllPanels();
+
+		// Whatever we were doing is hereby canceled.
+		mWaitingForResult = false;
+	}
+
+	@Override
+	protected void onNewIntent(Intent intent) {
+		super.onNewIntent(intent);
+
+		// Close the menu
+		if (Intent.ACTION_MAIN.equals(intent.getAction())) {
+			// also will cancel mWaitingForResult.
+			closeSystemDialogs();
+
+			final boolean alreadyOnHome = ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
+
+			Runnable processIntent = new Runnable() {
+				public void run() {
+					if (mWorkspace == null) {
+						// Can be cases where mWorkspace is null, this prevents
+						// a NPE
+						return;
+					}
+					Folder openFolder = mWorkspace.getOpenFolder();
+					// In all these cases, only animate if we're already on home
+					mWorkspace.exitWidgetResizeMode();
+					if (alreadyOnHome && mState == State.WORKSPACE
+							&& !mWorkspace.isTouchActive()
+							&& openFolder == null) {
+						mWorkspace.moveToDefaultScreen(true);
+					}
+
+					closeFolder();
+					exitSpringLoadedDragMode();
+
+					// If we are already on home, then just animate back to the
+					// workspace,
+					// otherwise, just wait until onResume to set the state back
+					// to Workspace
+					if (alreadyOnHome) {
+						showWorkspace(true);
+					} else {
+						mOnResumeState = State.WORKSPACE;
+					}
+
+					final View v = getWindow().peekDecorView();
+					if (v != null && v.getWindowToken() != null) {
+						InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
+						imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+					}
+
+					// Reset AllApps to its initial state
+					if (!alreadyOnHome && mAppsCustomizeTabHost != null) {
+						mAppsCustomizeTabHost.reset();
+					}
+				}
+			};
+
+			if (alreadyOnHome && !mWorkspace.hasWindowFocus()) {
+				// Delay processing of the intent to allow the status bar
+				// animation to finish
+				// first in order to avoid janky animations.
+				mWorkspace.postDelayed(processIntent, 350);
+			} else {
+				// Process the intent immediately.
+				processIntent.run();
+			}
+
+		}
+	}
+
+	@Override
+	public void onRestoreInstanceState(Bundle state) {
+		super.onRestoreInstanceState(state);
+		for (int page : mSynchronouslyBoundPages) {
+			mWorkspace.restoreInstanceStateForChild(page);
+		}
+	}
+
+	@Override
+	protected void onSaveInstanceState(Bundle outState) {
+		outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getNextPage());
+		super.onSaveInstanceState(outState);
+
+		outState.putInt(RUNTIME_STATE, mState.ordinal());
+		// We close any open folder since it will not be re-opened, and we need
+		// to make sure
+		// this state is reflected.
+		closeFolder();
+
+		if (mPendingAddInfo.container != ItemInfo.NO_ID
+				&& mPendingAddInfo.screen > -1 && mWaitingForResult) {
+			outState.putLong(RUNTIME_STATE_PENDING_ADD_CONTAINER,
+					mPendingAddInfo.container);
+			outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN,
+					mPendingAddInfo.screen);
+			outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X,
+					mPendingAddInfo.cellX);
+			outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y,
+					mPendingAddInfo.cellY);
+			outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X,
+					mPendingAddInfo.spanX);
+			outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y,
+					mPendingAddInfo.spanY);
+			outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO,
+					mPendingAddWidgetInfo);
+		}
+
+		if (mFolderInfo != null && mWaitingForResult) {
+			outState.putBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, true);
+			outState.putLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID,
+					mFolderInfo.id);
+		}
+
+		// Save the current AppsCustomize tab
+		if (mAppsCustomizeTabHost != null) {
+			String currentTabTag = mAppsCustomizeTabHost.getCurrentTabTag();
+			if (currentTabTag != null) {
+				outState.putString("apps_customize_currentTab", currentTabTag);
+			}
+			int currentIndex = mAppsCustomizeContent
+					.getSaveInstanceStateIndex();
+			outState.putInt("apps_customize_currentIndex", currentIndex);
+		}
+	}
+
+	@Override
+	public void onDestroy() {
+		super.onDestroy();
+
+		// Remove all pending runnables
+		mHandler.removeMessages(ADVANCE_MSG);
+		mHandler.removeMessages(0);
+		mWorkspace.removeCallbacks(mBuildLayersRunnable);
+
+		// Stop callbacks from LauncherModel
+		LauncherApplication app = ((LauncherApplication) getApplication());
+		mModel.stopLoader();
+		app.setLauncher(null);
+
+		try {
+			mAppWidgetHost.stopListening();
+		} catch (NullPointerException ex) {
+			Log.w(TAG,
+					"problem while stopping AppWidgetHost during Launcher destruction",
+					ex);
+		}
+		mAppWidgetHost = null;
+
+		mWidgetsToAdvance.clear();
+
+		TextKeyListener.getInstance().release();
+
+		// Disconnect any of the callbacks and drawables associated with
+		// ItemInfos on the workspace
+		// to prevent leaking Launcher activities on orientation change.
+		if (mModel != null) {
+			mModel.unbindItemInfosAndClearQueuedBindRunnables();
+		}
+
+		getContentResolver().unregisterContentObserver(mWidgetObserver);
+		unregisterReceiver(mCloseSystemDialogsReceiver);
+
+		mDragLayer.clearAllResizeFrames();
+		((ViewGroup) mWorkspace.getParent()).removeAllViews();
+		mWorkspace.removeAllViews();
+		mWorkspace = null;
+		mDragController = null;
+
+		LauncherAnimUtils.onDestroyActivity();
+	}
+
+	public DragController getDragController() {
+		return mDragController;
+	}
+
+	@Override
+	public void startActivityForResult(Intent intent, int requestCode) {
+		if (requestCode >= 0)
+			mWaitingForResult = true;
+
+		if (intent != null) {
+			super.startActivityForResult(intent, requestCode);
+		}
+	}
+
+	/**
+	 * Indicates that we want global search for this activity by setting the
+	 * globalSearch argument for {@link #startSearch} to true.
+	 */
+	@Override
+	public void startSearch(String initialQuery, boolean selectInitialQuery,
+			Bundle appSearchData, boolean globalSearch) {
+
+		showWorkspace(true);
+
+		if (initialQuery == null) {
+			// Use any text typed in the launcher as the initial query
+			initialQuery = getTypedText();
+		}
+		if (appSearchData == null) {
+			appSearchData = new Bundle();
+			appSearchData.putString("Test", "launcher-search");
+		}
+		Rect sourceBounds = new Rect();
+		if (mSearchDropTargetBar != null) {
+			sourceBounds = mSearchDropTargetBar.getSearchBarBounds();
+		}
+
+		startGlobalSearch(initialQuery, selectInitialQuery, appSearchData,
+				sourceBounds);
+	}
+
+	/**
+	 * Starts the global search activity. This code is a copied from
+	 * SearchManager
+	 */
+	public void startGlobalSearch(String initialQuery,
+			boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
+		final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+		ComponentName globalSearchActivity = searchManager
+				.getGlobalSearchActivity();
+		if (globalSearchActivity == null) {
+			Log.w(TAG, "No global search activity found.");
+			return;
+		}
+		Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+		intent.setComponent(globalSearchActivity);
+		// Make sure that we have a Bundle to put source in
+		if (appSearchData == null) {
+			appSearchData = new Bundle();
+		} else {
+			appSearchData = new Bundle(appSearchData);
+		}
+		// Set source to package name of app that starts global search, if not
+		// set already.
+		if (!appSearchData.containsKey("source")) {
+			appSearchData.putString("source", getPackageName());
+		}
+		intent.putExtra(SearchManager.APP_DATA, appSearchData);
+		if (!TextUtils.isEmpty(initialQuery)) {
+			intent.putExtra(SearchManager.QUERY, initialQuery);
+		}
+		if (selectInitialQuery) {
+			intent.putExtra(SearchManager.EXTRA_SELECT_QUERY,
+					selectInitialQuery);
+		}
+		intent.setSourceBounds(sourceBounds);
+		try {
+			startActivity(intent);
+		} catch (ActivityNotFoundException ex) {
+			Log.e(TAG, "Global search activity not found: "
+					+ globalSearchActivity);
+		}
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu menu) {
+		if (isWorkspaceLocked()) {
+			return false;
+		}
+
+		super.onCreateOptionsMenu(menu);
+
+		Intent manageApps = new Intent(
+				Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS);
+		manageApps.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+				| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+		Intent settings = new Intent(android.provider.Settings.ACTION_SETTINGS);
+		settings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+				| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+		String helpUrl = getString(R.string.help_url);
+		Intent help = new Intent(Intent.ACTION_VIEW, Uri.parse(helpUrl));
+		help.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+				| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+		menu.add(MENU_GROUP_WALLPAPER, MENU_WALLPAPER_SETTINGS, 0,
+				R.string.menu_wallpaper)
+				.setIcon(android.R.drawable.ic_menu_gallery)
+				.setAlphabeticShortcut('W');
+		menu.add(0, MENU_MANAGE_APPS, 0, R.string.menu_manage_apps)
+				.setIcon(android.R.drawable.ic_menu_manage)
+				.setIntent(manageApps).setAlphabeticShortcut('M');
+		menu.add(0, MENU_SYSTEM_SETTINGS, 0, R.string.menu_settings)
+				.setIcon(android.R.drawable.ic_menu_preferences)
+				.setIntent(settings).setAlphabeticShortcut('P');
+		if (!helpUrl.isEmpty()) {
+			menu.add(0, MENU_HELP, 0, R.string.menu_help)
+					.setIcon(android.R.drawable.ic_menu_help).setIntent(help)
+					.setAlphabeticShortcut('H');
+		}
+
+		menu.add(0, MENU_SHOW_FP_OOBE, 0, R.string.menu_show_OOBE)
+				.setAlphabeticShortcut('T');
+
+		return true;
+	}
+
+	@Override
+	public boolean onPrepareOptionsMenu(Menu menu) {
+		super.onPrepareOptionsMenu(menu);
+
+		if (mAppsCustomizeTabHost.isTransitioning()) {
+			return false;
+		}
+		boolean allAppsVisible = (mAppsCustomizeTabHost.getVisibility() == View.VISIBLE);
+		menu.setGroupVisible(MENU_GROUP_WALLPAPER, !allAppsVisible);
+
+		return true;
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		switch (item.getItemId()) {
+		case MENU_WALLPAPER_SETTINGS:
+			startWallpaper();
+			return true;
+		case MENU_SHOW_FP_OOBE:
+			startOOBEActivity(OOBEActivity.OOBE_FULL_TUTORIAL);
+			return true;
+		}
+
+		return super.onOptionsItemSelected(item);
+	}
+
+	@Override
+	public boolean onSearchRequested() {
+		startSearch(null, false, null, true);
+		// Use a custom animation for launching search
+		return true;
+	}
+
+	public boolean isWorkspaceLocked() {
+		return mWorkspaceLoading || mWaitingForResult;
+	}
+
+	private void resetAddInfo() {
+		mPendingAddInfo.container = ItemInfo.NO_ID;
+		mPendingAddInfo.screen = -1;
+		mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
+		mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
+		mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = -1;
+		mPendingAddInfo.dropPos = null;
+	}
+
+	void addAppWidgetImpl(final int appWidgetId, ItemInfo info,
+			AppWidgetHostView boundWidget, AppWidgetProviderInfo appWidgetInfo) {
+		if (appWidgetInfo.configure != null) {
+			mPendingAddWidgetInfo = appWidgetInfo;
+
+			// Launch over to configure widget, if needed
+			Intent intent = new Intent(
+					AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+			intent.setComponent(appWidgetInfo.configure);
+			intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+			startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
+		} else {
+			// Otherwise just add it
+			completeAddAppWidget(appWidgetId, info.container, info.screen,
+					boundWidget, appWidgetInfo);
+			// Exit spring loaded mode if necessary after adding the widget
+			exitSpringLoadedDragModeDelayed(true, false, null);
+		}
+	}
+
+	/**
+	 * Process a shortcut drop.
+	 * 
+	 * @param componentName
+	 *            The name of the component
+	 * @param screen
+	 *            The screen where it should be added
+	 * @param cell
+	 *            The cell it should be added to, optional
+	 * @param position
+	 *            The location on the screen where it was dropped, optional
+	 */
+	void processShortcutFromDrop(ComponentName componentName, long container,
+			int screen, int[] cell, int[] loc) {
+		resetAddInfo();
+		mPendingAddInfo.container = container;
+		mPendingAddInfo.screen = screen;
+		mPendingAddInfo.dropPos = loc;
+
+		if (cell != null) {
+			mPendingAddInfo.cellX = cell[0];
+			mPendingAddInfo.cellY = cell[1];
+		}
+
+		Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
+		createShortcutIntent.setComponent(componentName);
+		processShortcut(createShortcutIntent);
+	}
+
+	/**
+	 * Process a widget drop.
+	 * 
+	 * @param info
+	 *            The PendingAppWidgetInfo of the widget being added.
+	 * @param screen
+	 *            The screen where it should be added
+	 * @param cell
+	 *            The cell it should be added to, optional
+	 * @param position
+	 *            The location on the screen where it was dropped, optional
+	 */
+	void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container,
+			int screen, int[] cell, int[] span, int[] loc) {
+		resetAddInfo();
+		mPendingAddInfo.container = info.container = container;
+		mPendingAddInfo.screen = info.screen = screen;
+		mPendingAddInfo.dropPos = loc;
+		mPendingAddInfo.minSpanX = info.minSpanX;
+		mPendingAddInfo.minSpanY = info.minSpanY;
+
+		if (cell != null) {
+			mPendingAddInfo.cellX = cell[0];
+			mPendingAddInfo.cellY = cell[1];
+		}
+		if (span != null) {
+			mPendingAddInfo.spanX = span[0];
+			mPendingAddInfo.spanY = span[1];
+		}
+
+		AppWidgetHostView hostView = info.boundWidget;
+		int appWidgetId;
+		if (hostView != null) {
+			appWidgetId = hostView.getAppWidgetId();
+			addAppWidgetImpl(appWidgetId, info, hostView, info.info);
+		} else {
+			// In this case, we either need to start an activity to get
+			// permission to bind
+			// the widget, or we need to start an activity to configure the
+			// widget, or both.
+			appWidgetId = getAppWidgetHost().allocateAppWidgetId();
+			Bundle options = info.bindOptions;
+
+			boolean success = false;
+			if (success) {
+				addAppWidgetImpl(appWidgetId, info, null, info.info);
+			} else {
+				mPendingAddWidgetInfo = info.info;
+				Intent intent = new Intent(
+						AppWidgetManager.ACTION_APPWIDGET_BIND);
+				intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
+						appWidgetId);
+				intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,
+						info.componentName);
+				startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
+			}
+		}
+	}
+
+	void processShortcut(Intent intent) {
+		// Handle case where user selected "Applications"
+		String applicationName = getResources().getString(
+				R.string.group_applications);
+		String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+
+		if (applicationName != null && applicationName.equals(shortcutName)) {
+			Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+			mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+			Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
+			pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
+			pickIntent.putExtra(Intent.EXTRA_TITLE,
+					getText(R.string.title_select_application));
+			startActivityForResultSafely(pickIntent, REQUEST_PICK_APPLICATION);
+		} else {
+			startActivityForResultSafely(intent, REQUEST_CREATE_SHORTCUT);
+		}
+	}
+
+	void processWallpaper(Intent intent) {
+		startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
+	}
+
+	FolderIcon addFolder(CellLayout layout, long container, final int screen,
+			int cellX, int cellY) {
+		final FolderInfo folderInfo = new FolderInfo();
+		folderInfo.title = getText(R.string.folder_name);
+
+		// Update the model
+		LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container,
+				screen, cellX, cellY, false);
+		sFolders.put(folderInfo.id, folderInfo);
+
+		// Create the view
+		FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
+				layout, folderInfo, mIconCache);
+		mWorkspace.addInScreen(newFolder, container, screen, cellX, cellY, 1,
+				1, isWorkspaceLocked());
+		return newFolder;
+	}
+
+	void removeFolder(FolderInfo folder) {
+		sFolders.remove(folder.id);
+	}
+
+	private void startWallpaper() {
+		showWorkspace(true);
+		final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
+		Intent chooser = Intent.createChooser(pickWallpaper,
+				getText(R.string.chooser_wallpaper));
+
+		startActivityForResult(chooser, REQUEST_PICK_WALLPAPER);
+	}
+
+	/**
+	 * Registers various content observers. The current implementation registers
+	 * only a favorites observer to keep track of the favorites applications.
+	 */
+	private void registerContentObservers() {
+		ContentResolver resolver = getContentResolver();
+		resolver.registerContentObserver(
+				LauncherProvider.CONTENT_APPWIDGET_RESET_URI, true,
+				mWidgetObserver);
+	}
+
+	@Override
+	public boolean dispatchKeyEvent(KeyEvent event) {
+		if (event.getAction() == KeyEvent.ACTION_DOWN) {
+			switch (event.getKeyCode()) {
+			case KeyEvent.KEYCODE_HOME:
+				return true;
+			case KeyEvent.KEYCODE_VOLUME_DOWN:
+				if (isPropertyEnabled(DUMP_STATE_PROPERTY)) {
+					dumpState();
+					return true;
+				}
+				break;
+			}
+		} else if (event.getAction() == KeyEvent.ACTION_UP) {
+			switch (event.getKeyCode()) {
+			case KeyEvent.KEYCODE_HOME:
+				return true;
+			}
+		}
+
+		return super.dispatchKeyEvent(event);
+	}
+
+	@Override
+	public void onBackPressed() {
+		if (isAllAppsVisible()) {
+			showWorkspace(true);
+		} else if (mWorkspace.getOpenFolder() != null) {
+			Folder openFolder = mWorkspace.getOpenFolder();
+			if (openFolder.isEditingName()) {
+				openFolder.dismissEditingName();
+			} else {
+				closeFolder();
+			}
+		} else {
+			mWorkspace.exitWidgetResizeMode();
+
+			// Back button is a no-op here, but give at least some feedback for
+			// the button press
+			mWorkspace.showOutlinesTemporarily();
+		}
+	}
+
+	/**
+	 * Re-listen when widgets are reset.
+	 */
+	private void onAppWidgetReset() {
+		if (mAppWidgetHost != null) {
+			mAppWidgetHost.startListening();
+		}
+	}
+
+	/**
+	 * Launches the intent referred by the clicked shortcut.
+	 * 
+	 * @param v
+	 *            The view representing the clicked shortcut.
+	 */
+	public void onClick(View v) {
+		// Make sure that rogue clicks don't get through while allapps is
+		// launching, or after the
+		// view has detached (it's possible for this to happen if the view is
+		// removed mid touch).
+		if (v.getWindowToken() == null) {
+			return;
+		}
+
+		if (!mWorkspace.isFinishedSwitchingState()) {
+			return;
+		}
+
+		Object tag = v.getTag();
+		if (tag instanceof ShortcutInfo) {
+			// Open shortcut
+			final Intent intent = ((ShortcutInfo) tag).intent;
+			int[] pos = new int[2];
+			v.getLocationOnScreen(pos);
+			intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0]
+					+ v.getWidth(), pos[1] + v.getHeight()));
+
+			boolean success = startActivitySafely(v, intent, tag);
+
+			if (success && v instanceof BubbleTextView) {
+				mWaitingForResume = (BubbleTextView) v;
+				mWaitingForResume.setStayPressed(true);
+			}
+		} else if (tag instanceof FolderInfo) {
+			if (v instanceof FolderIcon) {
+				FolderIcon fi = (FolderIcon) v;
+				handleFolderClick(fi);
+			}
+		} else if (v == mAllAppsButton) {
+			if (isAllAppsVisible()) {
+				showWorkspace(true);
+			} else {
+				onClickAllAppsButton(v);
+			}
+		}
+	}
+
+	public boolean onTouch(View v, MotionEvent event) {
+		// this is an intercepted event being forwarded from mWorkspace;
+		// clicking anywhere on the workspace causes the customization drawer to
+		// slide down
+		showWorkspace(true);
+		return false;
+	}
+
+	/**
+	 * Event handler for the search button
+	 * 
+	 * @param v
+	 *            The view that was clicked.
+	 */
+	public void onClickSearchButton(View v) {
+		v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+
+		onSearchRequested();
+	}
+
+	/**
+	 * Event handler for the voice button
+	 * 
+	 * @param v
+	 *            The view that was clicked.
+	 */
+	public void onClickVoiceButton(View v) {
+		v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+
+		try {
+			final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+			ComponentName activityName = searchManager
+					.getGlobalSearchActivity();
+			Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+			if (activityName != null) {
+				intent.setPackage(activityName.getPackageName());
+			}
+			startActivity(null, intent, "onClickVoiceButton");
+		} catch (ActivityNotFoundException e) {
+			Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+			startActivitySafely(null, intent, "onClickVoiceButton");
+		}
+	}
+
+	/**
+	 * Event handler for the "grid" button that appears on the home screen,
+	 * which enters all apps mode.
+	 * 
+	 * @param v
+	 *            The view that was clicked.
+	 */
+	public void onClickAllAppsButton(View v) {
+		showAllApps(true);
+	}
+
+	public void onTouchDownAllAppsButton(View v) {
+		// Provide the same haptic feedback that the system offers for virtual
+		// keys.
+		v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+	}
+
+	public void onClickAppMarketButton(View v) {
+		if (mAppMarketIntent != null) {
+			startActivitySafely(v, mAppMarketIntent, "app market");
+		} else {
+			Log.e(TAG, "Invalid app market intent.");
+		}
+	}
+
+	void startApplicationDetailsActivity(ComponentName componentName) {
+		String packageName = componentName.getPackageName();
+		Intent intent = new Intent(
+				Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts(
+						"package", packageName, null));
+		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+				| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+		startActivitySafely(null, intent, "startApplicationDetailsActivity");
+	}
+
+	void startApplicationUninstallActivity(ApplicationInfo appInfo) {
+
+		if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) == 0) {
+			// System applications cannot be installed. For now, show a toast
+			// explaining that.
+			// We may give them the option of disabling apps this way.
+			int messageId = R.string.uninstall_system_app_text;
+			Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show();
+		} else {
+			String packageName = appInfo.componentName.getPackageName();
+
+			Log.d(TAG, "Uninstalling Activity >>> " + packageName);
+
+			String className = appInfo.componentName.getClassName();
+			Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts(
+					"package", packageName, className));
+			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+					| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+			startActivity(intent);
+
+			AppDiscoverer.getInstance().applicationRemoved(
+					appInfo.componentName);
+
+			updateAppSwitcherWidgets();
+		}
+	}
+
+	public boolean startActivity(View v, Intent intent, Object tag) {
+
+		ComponentName component = intent != null ? intent.getComponent() : null;
+		String packageName = intent != null ? ItemInfo.getPackageName(intent)
+				: "implicit Intent.";
+
+		Log.d(TAG,
+				"Start Activity >>> "
+						+ (component != null ? component.toString()
+								: packageName));
+
+		boolean explicitIntent = component != null;
+
+		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+		try {
+			// Only launch using the new animation if the shortcut has not opted
+			// out (this is a
+			// private contract between launcher and may be ignored in the
+			// future).
+			boolean useLaunchAnimation = (v != null)
+					&& !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
+			if (useLaunchAnimation) {
+				ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v,
+						0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
+
+				startActivity(intent, opts.toBundle());
+			} else {
+				startActivity(intent);
+			}
+
+			if (explicitIntent) {
+				updateActivityInfoViaExplicitIntent(component);
+			} else {
+				Log.i(TAG, "Could not log this, implicit intent.");
+			}
+
+			return true;
+
+		} catch (SecurityException e) {
+			Toast.makeText(this, R.string.activity_not_found,
+					Toast.LENGTH_SHORT).show();
+			Log.e(TAG,
+					"Launcher does not have the permission to launch "
+							+ intent
+							+ ". Make sure to create a MAIN intent-filter for the corresponding activity "
+							+ "or use the exported attribute for this activity. "
+							+ "tag=" + tag + " intent=" + intent, e);
+		}
+		return false;
+	}
+
+	private void updateActivityInfoViaExplicitIntent(ComponentName component) {
+		AppDiscoverer.getInstance().applicationStarted(
+				generateAppInfo(component));
+
+		updateAppSwitcherWidgets();
+	}
+
+	public void updateAppSwitcherWidgets() {
+		AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
+		int[] appWidgetIds = appWidgetManager
+				.getAppWidgetIds(new ComponentName(this, WidgetProvider.class));
+		if (appWidgetIds.length > 0) {
+			new WidgetProvider().onUpdate(this, appWidgetManager, appWidgetIds);
+		}
+	}
+	
+	public void updateGoogleAppsIntallerWidgets() {
+		AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
+		int[] appWidgetIds = appWidgetManager
+				.getAppWidgetIds(new ComponentName(this, GoogleAppsInstallerWidget.class));
+		if (appWidgetIds.length > 0) {
+			new GoogleAppsInstallerWidget().onUpdate(this, appWidgetManager, appWidgetIds);
+		}
+	}
+
+	private ApplicationRunInformation generateAppInfo(ComponentName component) {
+		ApplicationRunInformation appInfo = new ApplicationRunInformation(
+				component);
+		appInfo.incrementCount();
+		appInfo.setLastExecution(Calendar.getInstance().getTime());
+
+		return appInfo;
+	}
+
+	boolean startActivitySafely(View v, Intent intent, Object tag) {
+		boolean success = false;
+		try {
+			success = startActivity(v, intent, tag);
+		} catch (ActivityNotFoundException e) {
+			Toast.makeText(this, R.string.activity_not_found,
+					Toast.LENGTH_SHORT).show();
+			Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
+		}
+		return success;
+	}
+
+	void startActivityForResultSafely(Intent intent, int requestCode) {
+		ComponentName component = intent != null ? intent.getComponent() : null;
+		String packageName = intent != null ? ItemInfo.getPackageName(intent)
+				: "implicit Intent.";
+
+		Log.d(TAG, "Start Activity for Result > "
+				+ (component != null ? component.toString() : packageName));
+
+		try {
+			startActivityForResult(intent, requestCode);
+			if (component != null && (requestCode != REQUEST_CREATE_APPWIDGET && requestCode != REQUEST_BIND_APPWIDGET)) {
+				updateActivityInfoViaExplicitIntent(component);
+			}
+		} catch (ActivityNotFoundException e) {
+			Toast.makeText(this, R.string.activity_not_found,
+					Toast.LENGTH_SHORT).show();
+		} catch (SecurityException e) {
+			Toast.makeText(this, R.string.activity_not_found,
+					Toast.LENGTH_SHORT).show();
+			Log.e(TAG,
+					"Launcher does not have the permission to launch "
+							+ intent
+							+ ". Make sure to create a MAIN intent-filter for the corresponding activity "
+							+ "or use the exported attribute for this activity.",
+					e);
+		}
+	}
+
+	private void handleFolderClick(FolderIcon folderIcon) {
+		final FolderInfo info = folderIcon.getFolderInfo();
+		Folder openFolder = mWorkspace.getFolderForTag(info);
+
+		// If the folder info reports that the associated folder is open, then
+		// verify that
+		// it is actually opened. There have been a few instances where this
+		// gets out of sync.
+		if (info.opened && openFolder == null) {
+			Log.d(TAG,
+					"Folder info marked as open, but associated folder is not open. Screen: "
+							+ info.screen + " (" + info.cellX + ", "
+							+ info.cellY + ")");
+			info.opened = false;
+		}
+
+		if (!info.opened && !folderIcon.getFolder().isDestroyed()) {
+			// Close any open folder
+			closeFolder();
+			// Open the requested folder
+			openFolder(folderIcon);
+		} else {
+			// Find the open folder...
+			int folderScreen;
+			if (openFolder != null) {
+				folderScreen = mWorkspace.getPageForView(openFolder);
+				// .. and close it
+				closeFolder(openFolder);
+				if (folderScreen != mWorkspace.getCurrentPage()) {
+					// Close any folder open on the current screen
+					closeFolder();
+					// Pull the folder onto this screen
+					openFolder(folderIcon);
+				}
+			}
+		}
+	}
+
+	/**
+	 * This method draws the FolderIcon to an ImageView and then adds and
+	 * positions that ImageView in the DragLayer in the exact absolute location
+	 * of the original FolderIcon.
+	 */
+	private void copyFolderIconToImage(FolderIcon fi) {
+		final int width = fi.getMeasuredWidth();
+		final int height = fi.getMeasuredHeight();
+
+		// Lazy load ImageView, Bitmap and Canvas
+		if (mFolderIconImageView == null) {
+			mFolderIconImageView = new ImageView(this);
+		}
+		if (mFolderIconBitmap == null || mFolderIconBitmap.getWidth() != width
+				|| mFolderIconBitmap.getHeight() != height) {
+			mFolderIconBitmap = Bitmap.createBitmap(width, height,
+					Bitmap.Config.ARGB_8888);
+			mFolderIconCanvas = new Canvas(mFolderIconBitmap);
+		}
+
+		DragLayer.LayoutParams lp;
+		if (mFolderIconImageView.getLayoutParams() instanceof DragLayer.LayoutParams) {
+			lp = (DragLayer.LayoutParams) mFolderIconImageView
+					.getLayoutParams();
+		} else {
+			lp = new DragLayer.LayoutParams(width, height);
+		}
+
+		// The layout from which the folder is being opened may be scaled,
+		// adjust the starting
+		// view size by this scale factor.
+		float scale = mDragLayer.getDescendantRectRelativeToSelf(fi,
+				mRectForFolderAnimation);
+		lp.customPosition = true;
+		lp.x = mRectForFolderAnimation.left;
+		lp.y = mRectForFolderAnimation.top;
+		lp.width = (int) (scale * width);
+		lp.height = (int) (scale * height);
+
+		mFolderIconCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
+		fi.draw(mFolderIconCanvas);
+		mFolderIconImageView.setImageBitmap(mFolderIconBitmap);
+		if (fi.getFolder() != null) {
+			mFolderIconImageView.setPivotX(fi.getFolder()
+					.getPivotXForIconAnimation());
+			mFolderIconImageView.setPivotY(fi.getFolder()
+					.getPivotYForIconAnimation());
+		}
+		// Just in case this image view is still in the drag layer from a
+		// previous animation,
+		// we remove it and re-add it.
+		if (mDragLayer.indexOfChild(mFolderIconImageView) != -1) {
+			mDragLayer.removeView(mFolderIconImageView);
+		}
+		mDragLayer.addView(mFolderIconImageView, lp);
+		if (fi.getFolder() != null) {
+			fi.getFolder().bringToFront();
+		}
+	}
+
+	private void growAndFadeOutFolderIcon(FolderIcon fi) {
+		if (fi == null)
+			return;
+		PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+		PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",
+				1.5f);
+		PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY",
+				1.5f);
+
+		FolderInfo info = (FolderInfo) fi.getTag();
+		if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+			CellLayout cl = (CellLayout) fi.getParent().getParent();
+			CellLayout.LayoutParams lp = (CellLayout.LayoutParams) fi
+					.getLayoutParams();
+			cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
+		}
+
+		// Push an ImageView copy of the FolderIcon into the DragLayer and hide
+		// the original
+		copyFolderIconToImage(fi);
+		fi.setVisibility(View.INVISIBLE);
+
+		ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(
+				mFolderIconImageView, alpha, scaleX, scaleY);
+		oa.setDuration(getResources().getInteger(
+				R.integer.config_folderAnimDuration));
+		oa.start();
+	}
+
+	private void shrinkAndFadeInFolderIcon(final FolderIcon fi) {
+		if (fi == null)
+			return;
+		PropertyValuesHolder alpha = PropertyValuesHolder
+				.ofFloat("alpha", 1.0f);
+		PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",
+				1.0f);
+		PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY",
+				1.0f);
+
+		final CellLayout cl = (CellLayout) fi.getParent().getParent();
+
+		// We remove and re-draw the FolderIcon in-case it has changed
+		mDragLayer.removeView(mFolderIconImageView);
+		copyFolderIconToImage(fi);
+		ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(
+				mFolderIconImageView, alpha, scaleX, scaleY);
+		oa.setDuration(getResources().getInteger(
+				R.integer.config_folderAnimDuration));
+		oa.addListener(new AnimatorListenerAdapter() {
+			@Override
+			public void onAnimationEnd(Animator animation) {
+				if (cl != null) {
+					cl.clearFolderLeaveBehind();
+					// Remove the ImageView copy of the FolderIcon and make the
+					// original visible.
+					mDragLayer.removeView(mFolderIconImageView);
+					fi.setVisibility(View.VISIBLE);
+				}
+			}
+		});
+		oa.start();
+	}
+
+	/**
+	 * Opens the user folder described by the specified tag. The opening of the
+	 * folder is animated relative to the specified View. If the View is null,
+	 * no animation is played.
+	 * 
+	 * @param folderInfo
+	 *            The FolderInfo describing the folder to open.
+	 */
+	public void openFolder(FolderIcon folderIcon) {
+		Folder folder = folderIcon.getFolder();
+		FolderInfo info = folder.mInfo;
+
+		info.opened = true;
+
+		// Just verify that the folder hasn't already been added to the
+		// DragLayer.
+		// There was a one-off crash where the folder had a parent already.
+		if (folder.getParent() == null) {
+			mDragLayer.addView(folder);
+			mDragController.addDropTarget((DropTarget) folder);
+		} else {
+			Log.w(TAG, "Opening folder (" + folder
+					+ ") which already has a parent (" + folder.getParent()
+					+ ").");
+		}
+		folder.animateOpen();
+		growAndFadeOutFolderIcon(folderIcon);
+	}
+
+	public void closeFolder() {
+		Folder folder = mWorkspace.getOpenFolder();
+		if (folder != null) {
+			if (folder.isEditingName()) {
+				folder.dismissEditingName();
+			}
+			closeFolder(folder);
+
+			// Dismiss the folder cling
+			dismissFolderCling(null);
+		}
+	}
+
+	void closeFolder(Folder folder) {
+		folder.getInfo().opened = false;
+
+		ViewGroup parent = (ViewGroup) folder.getParent().getParent();
+		if (parent != null) {
+			FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
+			shrinkAndFadeInFolderIcon(fi);
+		}
+		folder.animateClosed();
+	}
+
+	public boolean onLongClick(View v) {
+		if (!isDraggingEnabled())
+			return false;
+		if (isWorkspaceLocked())
+			return false;
+		if (mState != State.WORKSPACE)
+			return false;
+
+		if (!(v instanceof CellLayout)) {
+			v = (View) v.getParent().getParent();
+		}
+
+		resetAddInfo();
+		CellLayout.CellInfo longClickCellInfo = (CellLayout.CellInfo) v
+				.getTag();
+		// This happens when long clicking an item with the dpad/trackball
+		if (longClickCellInfo == null) {
+			return true;
+		}
+
+		// The hotseat touch handling does not go through Workspace, and we
+		// always allow long press
+		// on hotseat items.
+		final View itemUnderLongClick = longClickCellInfo.cell;
+		boolean allowLongPress = /* isHotseatLayout(v) || */mWorkspace
+				.allowLongPress();
+		if (allowLongPress && !mDragController.isDragging()) {
+			if (itemUnderLongClick == null) {
+				// User long pressed on empty space
+				mWorkspace.performHapticFeedback(
+						HapticFeedbackConstants.LONG_PRESS,
+						HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+				startWallpaper();
+			} else {
+				if (!(itemUnderLongClick instanceof Folder)) {
+					// User long pressed on an item
+					mWorkspace.startDrag(longClickCellInfo);
+				}
+			}
+		}
+		return true;
+	}
+
+	boolean isHotseatLayout(View layout) {
+		return false;
+	}
+
+	Hotseat getHotseat() {
+		return null;
+	}
+
+	SearchDropTargetBar getSearchBar() {
+		return mSearchDropTargetBar;
+	}
+
+	/**
+	 * Returns the CellLayout of the specified container at the specified
+	 * screen.
+	 */
+	CellLayout getCellLayout(long container, int screen) {
+		return (CellLayout) mWorkspace.getChildAt(screen);
+	}
+
+	Workspace getWorkspace() {
+		return mWorkspace;
+	}
+
+	// Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
+	@Override
+	public boolean isAllAppsVisible() {
+		return (mState == State.APPS_CUSTOMIZE)
+				|| (mOnResumeState == State.APPS_CUSTOMIZE);
+	}
+
+	@Override
+	public boolean isAllAppsButtonRank(int rank) {
+		return false;
+	}
+
+	/**
+	 * Helper method for the cameraZoomIn/cameraZoomOut animations
+	 * 
+	 * @param view
+	 *            The view being animated
+	 * @param scaleFactor
+	 *            The scale factor used for the zoom
+	 */
+	private void setPivotsForZoom(View view, float scaleFactor) {
+		view.setPivotX(view.getWidth() / 2.0f);
+		view.setPivotY(view.getHeight() / 2.0f);
+	}
+
+	void disableWallpaperIfInAllApps() {
+		// Only disable it if we are in all apps
+		if (isAllAppsVisible()) {
+			if (mAppsCustomizeTabHost != null
+					&& !mAppsCustomizeTabHost.isTransitioning()) {
+				updateWallpaperVisibility(false);
+			}
+		}
+	}
+
+	private void setWorkspaceBackground(boolean workspace) {
+		mLauncherView.setBackground(workspace ? mWorkspaceBackgroundDrawable
+				: mBlackBackgroundDrawable);
+	}
+
+	void updateWallpaperVisibility(boolean visible) {
+		int wpflags = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
+				: 0;
+		int curflags = getWindow().getAttributes().flags
+				& WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+		if (wpflags != curflags) {
+			getWindow().setFlags(wpflags,
+					WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
+		}
+		setWorkspaceBackground(visible);
+	}
+
+	private void dispatchOnLauncherTransitionPrepare(View v, boolean animated,
+			boolean toWorkspace) {
+		if (v instanceof LauncherTransitionable) {
+			((LauncherTransitionable) v).onLauncherTransitionPrepare(this,
+					animated, toWorkspace);
+		}
+	}
+
+	private void dispatchOnLauncherTransitionStart(View v, boolean animated,
+			boolean toWorkspace) {
+		if (v instanceof LauncherTransitionable) {
+			((LauncherTransitionable) v).onLauncherTransitionStart(this,
+					animated, toWorkspace);
+		}
+
+		// Update the workspace transition step as well
+		dispatchOnLauncherTransitionStep(v, 0f);
+	}
+
+	private void dispatchOnLauncherTransitionStep(View v, float t) {
+		if (v instanceof LauncherTransitionable) {
+			((LauncherTransitionable) v).onLauncherTransitionStep(this, t);
+		}
+	}
+
+	private void dispatchOnLauncherTransitionEnd(View v, boolean animated,
+			boolean toWorkspace) {
+		if (v instanceof LauncherTransitionable) {
+			((LauncherTransitionable) v).onLauncherTransitionEnd(this,
+					animated, toWorkspace);
+		}
+
+		// Update the workspace transition step as well
+		dispatchOnLauncherTransitionStep(v, 1f);
+	}
+
+	/**
+	 * Things to test when changing the following seven functions. - Home from
+	 * workspace - from center screen - from other screens - Home from all apps
+	 * - from center screen - from other screens - Back from all apps - from
+	 * center screen - from other screens - Launch app from workspace and quit -
+	 * with back - with home - Launch app from all apps and quit - with back -
+	 * with home - Go to a screen that's not the default, then all apps, and
+	 * launch and app, and go back - with back -with home - On workspace, long
+	 * press power and go back - with back - with home - On all apps, long press
+	 * power and go back - with back - with home - On workspace, power off - On
+	 * all apps, power off - Launch an app and turn off the screen while in that
+	 * app - Go back with home key - Go back with back key TODO: make this not
+	 * go to workspace - From all apps - From workspace - Enter and exit car
+	 * mode (becuase it causes an extra configuration changed) - From all apps -
+	 * From the center workspace - From another workspace
+	 */
+
+	/**
+	 * Zoom the camera out from the workspace to reveal 'toView'. Assumes that
+	 * the view to show is anchored at either the very top or very bottom of the
+	 * screen.
+	 */
+	private void showAppsCustomizeHelper(final boolean animated,
+			final boolean springLoaded) {
+		if (mStateAnimation != null) {
+			mStateAnimation.cancel();
+			mStateAnimation = null;
+		}
+		final Resources res = getResources();
+
+		final int duration = res
+				.getInteger(R.integer.config_appsCustomizeZoomInTime);
+		final int fadeDuration = res
+				.getInteger(R.integer.config_appsCustomizeFadeInTime);
+		final float scale = (float) res
+				.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
+		final View fromView = mWorkspace;
+		final AppsCustomizeTabHost toView = mAppsCustomizeTabHost;
+		final int startDelay = res
+				.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger);
+
+		setPivotsForZoom(toView, scale);
+
+		// Shrink workspaces away if going to AppsCustomize from workspace
+		Animator workspaceAnim = mWorkspace.getChangeStateAnimation(
+				Workspace.State.SMALL, animated);
+
+		if (animated) {
+			toView.setScaleX(scale);
+			toView.setScaleY(scale);
+			final LauncherViewPropertyAnimator scaleAnim = new LauncherViewPropertyAnimator(
+					toView);
+			scaleAnim.scaleX(1f).scaleY(1f).setDuration(duration)
+					.setInterpolator(new Workspace.ZoomOutInterpolator());
+
+			toView.setVisibility(View.VISIBLE);
+			toView.setAlpha(0f);
+			final ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(toView,
+					"alpha", 0f, 1f).setDuration(fadeDuration);
+			alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
+			alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
+				@Override
+				public void onAnimationUpdate(ValueAnimator animation) {
+					if (animation == null) {
+						throw new RuntimeException("animation is null");
+					}
+					float t = (Float) animation.getAnimatedValue();
+					dispatchOnLauncherTransitionStep(fromView, t);
+					dispatchOnLauncherTransitionStep(toView, t);
+				}
+			});
+
+			// toView should appear right at the end of the workspace shrink
+			// animation
+			mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+			mStateAnimation.play(scaleAnim).after(startDelay);
+			mStateAnimation.play(alphaAnim).after(startDelay);
+
+			mStateAnimation.addListener(new AnimatorListenerAdapter() {
+				boolean animationCancelled = false;
+
+				@Override
+				public void onAnimationStart(Animator animation) {
+					updateWallpaperVisibility(true);
+					// Prepare the position
+					toView.setTranslationX(0.0f);
+					toView.setTranslationY(0.0f);
+					toView.setVisibility(View.VISIBLE);
+					toView.bringToFront();
+				}
+
+				@Override
+				public void onAnimationEnd(Animator animation) {
+					dispatchOnLauncherTransitionEnd(fromView, animated, false);
+					dispatchOnLauncherTransitionEnd(toView, animated, false);
+
+					if (mWorkspace != null && !springLoaded
+							&& !LauncherApplication.isScreenLarge()) {
+						// Hide the workspace scrollbar
+						mWorkspace.hideScrollingIndicator(true);
+					}
+					if (!animationCancelled) {
+						updateWallpaperVisibility(false);
+					}
+
+				}
+
+				@Override
+				public void onAnimationCancel(Animator animation) {
+					animationCancelled = true;
+				}
+			});
+
+			if (workspaceAnim != null) {
+				mStateAnimation.play(workspaceAnim);
+			}
+
+			boolean delayAnim = false;
+			final ViewTreeObserver observer;
+
+			dispatchOnLauncherTransitionPrepare(fromView, animated, false);
+			dispatchOnLauncherTransitionPrepare(toView, animated, false);
+
+			// If any of the objects being animated haven't been measured/laid
+			// out
+			// yet, delay the animation until we get a layout pass
+			if ((((LauncherTransitionable) toView).getContent()
+					.getMeasuredWidth() == 0)
+					|| (mWorkspace.getMeasuredWidth() == 0)
+					|| (toView.getMeasuredWidth() == 0)) {
+				observer = mWorkspace.getViewTreeObserver();
+				delayAnim = true;
+			} else {
+				observer = null;
+			}
+
+			final AnimatorSet stateAnimation = mStateAnimation;
+			final Runnable startAnimRunnable = new Runnable() {
+				public void run() {
+					// Check that mStateAnimation hasn't changed while
+					// we waited for a layout/draw pass
+					if (mStateAnimation != stateAnimation)
+						return;
+					setPivotsForZoom(toView, scale);
+					dispatchOnLauncherTransitionStart(fromView, animated, false);
+					dispatchOnLauncherTransitionStart(toView, animated, false);
+					toView.post(new Runnable() {
+						public void run() {
+							// Check that mStateAnimation hasn't changed while
+							// we waited for a layout/draw pass
+							if (mStateAnimation != stateAnimation)
+								return;
+							mStateAnimation.start();
+						}
+					});
+				}
+			};
+			if (delayAnim) {
+				final OnGlobalLayoutListener delayedStart = new OnGlobalLayoutListener() {
+					public void onGlobalLayout() {
+						toView.post(startAnimRunnable);
+						observer.removeOnGlobalLayoutListener(this);
+					}
+				};
+				observer.addOnGlobalLayoutListener(delayedStart);
+			} else {
+				startAnimRunnable.run();
+			}
+		} else {
+			toView.setTranslationX(0.0f);
+			toView.setTranslationY(0.0f);
+			toView.setScaleX(1.0f);
+			toView.setScaleY(1.0f);
+			toView.setVisibility(View.VISIBLE);
+			toView.bringToFront();
+
+			if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+				// Hide the workspace scrollbar
+				mWorkspace.hideScrollingIndicator(true);
+			}
+			dispatchOnLauncherTransitionPrepare(fromView, animated, false);
+			dispatchOnLauncherTransitionStart(fromView, animated, false);
+			dispatchOnLauncherTransitionEnd(fromView, animated, false);
+			dispatchOnLauncherTransitionPrepare(toView, animated, false);
+			dispatchOnLauncherTransitionStart(toView, animated, false);
+			dispatchOnLauncherTransitionEnd(toView, animated, false);
+			updateWallpaperVisibility(false);
+		}
+	}
+
+	/**
+	 * Zoom the camera back into the workspace, hiding 'fromView'. This is the
+	 * opposite of showAppsCustomizeHelper.
+	 * 
+	 * @param animated
+	 *            If true, the transition will be animated.
+	 */
+	private void hideAppsCustomizeHelper(State toState, final boolean animated,
+			final boolean springLoaded, final Runnable onCompleteRunnable) {
+
+		if (mStateAnimation != null) {
+			mStateAnimation.cancel();
+			mStateAnimation = null;
+		}
+		Resources res = getResources();
+
+		final int duration = res
+				.getInteger(R.integer.config_appsCustomizeZoomOutTime);
+		final int fadeOutDuration = res
+				.getInteger(R.integer.config_appsCustomizeFadeOutTime);
+		final float scaleFactor = (float) res
+				.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
+		final View fromView = mAppsCustomizeTabHost;
+		final View toView = mWorkspace;
+		Animator workspaceAnim = null;
+
+		if (toState == State.WORKSPACE) {
+			int stagger = res
+					.getInteger(R.integer.config_appsCustomizeWorkspaceAnimationStagger);
+			workspaceAnim = mWorkspace.getChangeStateAnimation(
+					Workspace.State.NORMAL, animated, stagger);
+		} else if (toState == State.APPS_CUSTOMIZE_SPRING_LOADED) {
+			workspaceAnim = mWorkspace.getChangeStateAnimation(
+					Workspace.State.SPRING_LOADED, animated);
+		}
+
+		setPivotsForZoom(fromView, scaleFactor);
+		updateWallpaperVisibility(true);
+		if (animated) {
+			final LauncherViewPropertyAnimator scaleAnim = new LauncherViewPropertyAnimator(
+					fromView);
+			scaleAnim.scaleX(scaleFactor).scaleY(scaleFactor)
+					.setDuration(duration)
+					.setInterpolator(new Workspace.ZoomInInterpolator());
+
+			final ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(fromView,
+					"alpha", 1f, 0f).setDuration(fadeOutDuration);
+			alphaAnim.setInterpolator(new AccelerateDecelerateInterpolator());
+			alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
+				@Override
+				public void onAnimationUpdate(ValueAnimator animation) {
+					float t = 1f - (Float) animation.getAnimatedValue();
+					dispatchOnLauncherTransitionStep(fromView, t);
+					dispatchOnLauncherTransitionStep(toView, t);
+				}
+			});
+
+			mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+
+			dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+			dispatchOnLauncherTransitionPrepare(toView, animated, true);
+			mAppsCustomizeContent.pauseScrolling();
+
+			mStateAnimation.addListener(new AnimatorListenerAdapter() {
+				@Override
+				public void onAnimationEnd(Animator animation) {
+					updateWallpaperVisibility(true);
+					fromView.setVisibility(View.GONE);
+					dispatchOnLauncherTransitionEnd(fromView, animated, true);
+					dispatchOnLauncherTransitionEnd(toView, animated, true);
+					if (mWorkspace != null) {
+						mWorkspace.hideScrollingIndicator(false);
+					}
+					if (onCompleteRunnable != null) {
+						onCompleteRunnable.run();
+					}
+					mAppsCustomizeContent.updateCurrentPageScroll();
+					mAppsCustomizeContent.resumeScrolling();
+				}
+			});
+
+			mStateAnimation.playTogether(scaleAnim, alphaAnim);
+			if (workspaceAnim != null) {
+				mStateAnimation.play(workspaceAnim);
+			}
+			dispatchOnLauncherTransitionStart(fromView, animated, true);
+			dispatchOnLauncherTransitionStart(toView, animated, true);
+			final Animator stateAnimation = mStateAnimation;
+			mWorkspace.post(new Runnable() {
+				public void run() {
+					if (stateAnimation != mStateAnimation)
+						return;
+					mStateAnimation.start();
+				}
+			});
+		} else {
+			fromView.setVisibility(View.GONE);
+			dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+			dispatchOnLauncherTransitionStart(fromView, animated, true);
+			dispatchOnLauncherTransitionEnd(fromView, animated, true);
+			dispatchOnLauncherTransitionPrepare(toView, animated, true);
+			dispatchOnLauncherTransitionStart(toView, animated, true);
+			dispatchOnLauncherTransitionEnd(toView, animated, true);
+			mWorkspace.hideScrollingIndicator(false);
+		}
+	}
+
+	@Override
+	public void onTrimMemory(int level) {
+		super.onTrimMemory(level);
+		if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
+			mAppsCustomizeTabHost.onTrimMemory();
+		}
+	}
+
+	@Override
+	public void onWindowFocusChanged(boolean hasFocus) {
+		if (!hasFocus) {
+			// When another window occludes launcher (like the notification
+			// shade, or recents),
+			// ensure that we enable the wallpaper flag so that transitions are
+			// done correctly.
+			updateWallpaperVisibility(true);
+		} else {
+			// When launcher has focus again, disable the wallpaper if we are in
+			// AllApps
+			mWorkspace.postDelayed(new Runnable() {
+				@Override
+				public void run() {
+					disableWallpaperIfInAllApps();
+				}
+			}, 500);
+		}
+	}
+
+	void showWorkspace(boolean animated) {
+		showWorkspace(animated, null);
+	}
+
+	void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
+		if (mState != State.WORKSPACE) {
+			boolean wasInSpringLoadedMode = (mState == State.APPS_CUSTOMIZE_SPRING_LOADED);
+			mWorkspace.setVisibility(View.VISIBLE);
+			hideAppsCustomizeHelper(State.WORKSPACE, animated, false,
+					onCompleteRunnable);
+
+			// Set focus to the AppsCustomize button
+			if (mAllAppsButton != null) {
+				mAllAppsButton.requestFocus();
+			}
+		}
+
+		mWorkspace.flashScrollingIndicator(animated);
+
+		// Change the state *after* we've called all the transition code
+		mState = State.WORKSPACE;
+
+		// Resume the auto-advance of widgets
+		mUserPresent = true;
+		updateRunning();
+
+		// Send an accessibility event to announce the context change
+		getWindow().getDecorView().sendAccessibilityEvent(
+				AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+	}
+
+	public void showAllApps(boolean animated) {
+		if (mState != State.WORKSPACE)
+			return;
+
+		showAppsCustomizeHelper(animated, false);
+		mAppsCustomizeTabHost.requestFocus();
+
+		// Change the state *after* we've called all the transition code
+		mState = State.APPS_CUSTOMIZE;
+
+		// Pause the auto-advance of widgets until we are out of AllApps
+		mUserPresent = false;
+		updateRunning();
+		closeFolder();
+
+		// Send an accessibility event to announce the context change
+		getWindow().getDecorView().sendAccessibilityEvent(
+				AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+	}
+
+	void enterSpringLoadedDragMode() {
+		if (isAllAppsVisible()) {
+			hideAppsCustomizeHelper(State.APPS_CUSTOMIZE_SPRING_LOADED, true,
+					true, null);
+			mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
+		}
+	}
+
+	void exitSpringLoadedDragModeDelayed(final boolean successfulDrop,
+			boolean extendedDelay, final Runnable onCompleteRunnable) {
+		if (mState != State.APPS_CUSTOMIZE_SPRING_LOADED)
+			return;
+
+		mHandler.postDelayed(new Runnable() {
+			@Override
+			public void run() {
+				if (successfulDrop) {
+					// Before we show workspace, hide all apps again because
+					// exitSpringLoadedDragMode made it visible.
+					mAppsCustomizeTabHost.setVisibility(View.GONE);
+					showWorkspace(true, onCompleteRunnable);
+				} else {
+					exitSpringLoadedDragMode();
+				}
+			}
+		}, (extendedDelay ? EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT
+				: EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT));
+	}
+
+	void exitSpringLoadedDragMode() {
+		if (mState == State.APPS_CUSTOMIZE_SPRING_LOADED) {
+			final boolean animated = true;
+			final boolean springLoaded = true;
+			showAppsCustomizeHelper(animated, springLoaded);
+			mState = State.APPS_CUSTOMIZE;
+		}
+		// Otherwise, we are not in spring loaded mode, so don't do anything.
+	}
+
+	void lockAllApps() {
+		// TODO
+	}
+
+	void unlockAllApps() {
+	}
+
+
+	/**
+	 * Add an item from all apps or customize onto the given workspace screen.
+	 * If layout is null, add to the current screen.
+	 */
+	void addExternalItemToScreen(ItemInfo itemInfo, final CellLayout layout) {
+		if (!mWorkspace.addExternalItemToScreen(itemInfo, layout)) {
+			showOutOfSpaceMessage(isHotseatLayout(layout));
+		}
+	}
+
+	/**
+	 * Maps the current orientation to an index for referencing orientation
+	 * correct global icons
+	 */
+	private int getCurrentOrientationIndexForGlobalIcons() {
+		// default - 0, landscape - 1
+		switch (getResources().getConfiguration().orientation) {
+		case Configuration.ORIENTATION_LANDSCAPE:
+			return 1;
+		default:
+			return 0;
+		}
+	}
+
+	private Drawable getExternalPackageToolbarIcon(ComponentName activityName,
+			String resourceName) {
+		try {
+			PackageManager packageManager = getPackageManager();
+			// Look for the toolbar icon specified in the activity meta-data
+			Bundle metaData = packageManager.getActivityInfo(activityName,
+					PackageManager.GET_META_DATA).metaData;
+			if (metaData != null) {
+				int iconResId = metaData.getInt(resourceName);
+				if (iconResId != 0) {
+					Resources res = packageManager
+							.getResourcesForActivity(activityName);
+					return res.getDrawable(iconResId);
+				}
+			}
+		} catch (NameNotFoundException e) {
+			// This can happen if the activity defines an invalid drawable
+			Log.w(TAG,
+					"Failed to load toolbar icon; "
+							+ activityName.flattenToShortString()
+							+ " not found", e);
+		} catch (Resources.NotFoundException nfe) {
+			// This can happen if the activity defines an invalid drawable
+			Log.w(TAG,
+					"Failed to load toolbar icon from "
+							+ activityName.flattenToShortString(), nfe);
+		}
+		return null;
+	}
+
+	// if successful in getting icon, return it; otherwise, set button to use
+	// default drawable
+	private Drawable.ConstantState updateTextButtonWithIconFromExternalActivity(
+			int buttonId, ComponentName activityName, int fallbackDrawableId,
+			String toolbarResourceName) {
+		Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName,
+				toolbarResourceName);
+		Resources r = getResources();
+		int w = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_width);
+		int h = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_height);
+
+		TextView button = (TextView) findViewById(buttonId);
+		// If we were unable to find the icon via the meta-data, use a generic
+		// one
+		if (toolbarIcon == null) {
+			toolbarIcon = r.getDrawable(fallbackDrawableId);
+			toolbarIcon.setBounds(0, 0, w, h);
+			if (button != null) {
+				button.setCompoundDrawables(toolbarIcon, null, null, null);
+			}
+			return null;
+		} else {
+			toolbarIcon.setBounds(0, 0, w, h);
+			if (button != null) {
+				button.setCompoundDrawables(toolbarIcon, null, null, null);
+			}
+			return toolbarIcon.getConstantState();
+		}
+	}
+
+	// if successful in getting icon, return it; otherwise, set button to use
+	// default drawable
+	private Drawable.ConstantState updateButtonWithIconFromExternalActivity(
+			int buttonId, ComponentName activityName, int fallbackDrawableId,
+			String toolbarResourceName) {
+		ImageView button = (ImageView) findViewById(buttonId);
+		Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName,
+				toolbarResourceName);
+
+		if (button != null) {
+			// If we were unable to find the icon via the meta-data, use a
+			// generic one
+			if (toolbarIcon == null) {
+				button.setImageResource(fallbackDrawableId);
+			} else {
+				button.setImageDrawable(toolbarIcon);
+			}
+		}
+
+		return toolbarIcon != null ? toolbarIcon.getConstantState() : null;
+
+	}
+
+	private void updateTextButtonWithDrawable(int buttonId, Drawable d) {
+		TextView button = (TextView) findViewById(buttonId);
+		button.setCompoundDrawables(d, null, null, null);
+	}
+
+	private void updateButtonWithDrawable(int buttonId, Drawable.ConstantState d) {
+		ImageView button = (ImageView) findViewById(buttonId);
+		button.setImageDrawable(d.newDrawable(getResources()));
+	}
+
+	private void invalidatePressedFocusedStates(View container, View button) {
+		if (container instanceof HolographicLinearLayout) {
+			HolographicLinearLayout layout = (HolographicLinearLayout) container;
+			layout.invalidatePressedFocusedStates();
+		} else if (button instanceof HolographicImageView) {
+			HolographicImageView view = (HolographicImageView) button;
+			view.invalidatePressedFocusedStates();
+		}
+	}
+
+
+	private void updateGlobalSearchIcon(Drawable.ConstantState d) {
+		final View searchButtonContainer = findViewById(R.id.search_button_container);
+		final View searchButton = (ImageView) findViewById(R.id.search_button);
+		updateButtonWithDrawable(R.id.search_button, d);
+		invalidatePressedFocusedStates(searchButtonContainer, searchButton);
+	}
+
+	private boolean updateVoiceSearchIcon(boolean searchVisible) {
+		final View voiceButtonContainer = findViewById(R.id.voice_button_container);
+		final View voiceButton = findViewById(R.id.voice_button);
+
+		// We only show/update the voice search icon if the search icon is
+		// enabled as well
+		final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+		ComponentName globalSearchActivity = searchManager
+				.getGlobalSearchActivity();
+
+		ComponentName activityName = null;
+		if (globalSearchActivity != null) {
+			// Check if the global search activity handles voice search
+			Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+			intent.setPackage(globalSearchActivity.getPackageName());
+			activityName = intent.resolveActivity(getPackageManager());
+		}
+
+		if (activityName == null) {
+			// Fallback: check if an activity other than the global search
+			// activity
+			// resolves this
+			Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+			activityName = intent.resolveActivity(getPackageManager());
+		}
+		if (searchVisible && activityName != null) {
+			int coi = getCurrentOrientationIndexForGlobalIcons();
+			sVoiceSearchIcon[coi] = updateButtonWithIconFromExternalActivity(
+					R.id.voice_button, activityName,
+					R.drawable.ic_home_voice_search_holo,
+					TOOLBAR_VOICE_SEARCH_ICON_METADATA_NAME);
+			if (sVoiceSearchIcon[coi] == null) {
+				sVoiceSearchIcon[coi] = updateButtonWithIconFromExternalActivity(
+						R.id.voice_button, activityName,
+						R.drawable.ic_home_voice_search_holo,
+						TOOLBAR_ICON_METADATA_NAME);
+			}
+			if (voiceButtonContainer != null)
+				voiceButtonContainer.setVisibility(View.VISIBLE);
+			voiceButton.setVisibility(View.VISIBLE);
+			invalidatePressedFocusedStates(voiceButtonContainer, voiceButton);
+			return true;
+		} else {
+			if (voiceButtonContainer != null)
+				voiceButtonContainer.setVisibility(View.GONE);
+			voiceButton.setVisibility(View.GONE);
+			return false;
+		}
+	}
+
+	private void updateVoiceSearchIcon(Drawable.ConstantState d) {
+		final View voiceButtonContainer = findViewById(R.id.voice_button_container);
+		final View voiceButton = findViewById(R.id.voice_button);
+		updateButtonWithDrawable(R.id.voice_button, d);
+		invalidatePressedFocusedStates(voiceButtonContainer, voiceButton);
+	}
+
+	/**
+	 * Sets the app market icon
+	 */
+	private void updateAppMarketIcon() {
+		final View marketButton = findViewById(R.id.market_button);
+		Intent intent = new Intent(Intent.ACTION_MAIN)
+				.addCategory(Intent.CATEGORY_APP_MARKET);
+		// Find the app market activity by resolving an intent.
+		// (If multiple app markets are installed, it will return the
+		// ResolverActivity.)
+		ComponentName activityName = intent
+				.resolveActivity(getPackageManager());
+		if (activityName != null) {
+			int coi = getCurrentOrientationIndexForGlobalIcons();
+			mAppMarketIntent = intent;
+			sAppMarketIcon[coi] = updateTextButtonWithIconFromExternalActivity(
+					R.id.market_button, activityName,
+					R.drawable.ic_launcher_market_holo,
+					TOOLBAR_ICON_METADATA_NAME);
+			marketButton.setVisibility(View.VISIBLE);
+		} else {
+			// We should hide and disable the view so that we don't try and
+			// restore the visibility
+			// of it when we swap between drag & normal states from
+			// IconDropTarget subclasses.
+			marketButton.setVisibility(View.GONE);
+			marketButton.setEnabled(false);
+		}
+	}
+
+	private void updateAppMarketIcon(Drawable.ConstantState d) {
+		// Ensure that the new drawable we are creating has the approprate
+		// toolbar icon bounds
+		Resources r = getResources();
+		Drawable marketIconDrawable = d.newDrawable(r);
+		int w = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_width);
+		int h = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_height);
+		marketIconDrawable.setBounds(0, 0, w, h);
+
+		updateTextButtonWithDrawable(R.id.market_button, marketIconDrawable);
+	}
+
+	@Override
+	public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+		final boolean result = super.dispatchPopulateAccessibilityEvent(event);
+		final List<CharSequence> text = event.getText();
+		text.clear();
+		// Populate event with a fake title based on the current state.
+		if (mState == State.APPS_CUSTOMIZE) {
+			text.add(getString(R.string.all_apps_button_label));
+		} else {
+			text.add(getString(R.string.all_apps_home_button_label));
+		}
+		return result;
+	}
+
+	/**
+	 * Receives notifications when system dialogs are to be closed.
+	 */
+	private class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			closeSystemDialogs();
+		}
+	}
+
+	/**
+	 * Receives notifications whenever the appwidgets are reset.
+	 */
+	private class AppWidgetResetObserver extends ContentObserver {
+		public AppWidgetResetObserver() {
+			super(new Handler());
+		}
+
+		@Override
+		public void onChange(boolean selfChange) {
+			onAppWidgetReset();
+		}
+	}
+
+	/**
+	 * If the activity is currently paused, signal that we need to re-run the
+	 * loader in onResume.
+	 * 
+	 * This needs to be called from incoming places where resources might have
+	 * been loaded while we are paused. That is becaues the Configuration might
+	 * be wrong when we're not running, and if it comes back to what it was when
+	 * we were paused, we are not restarted.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 * 
+	 * @return true if we are currently paused. The caller might be able to skip
+	 *         some work in that case since we will come back again.
+	 */
+	public boolean setLoadOnResume() {
+		if (mPaused) {
+			Log.i(TAG, "setLoadOnResume");
+			mOnResumeNeedsLoad = true;
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public int getCurrentWorkspaceScreen() {
+		if (mWorkspace != null) {
+			return mWorkspace.getCurrentPage();
+		} else {
+			return SCREEN_COUNT / 2;
+		}
+	}
+
+	/**
+	 * Refreshes the shortcuts shown on the workspace.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void startBinding() {
+		final Workspace workspace = mWorkspace;
+
+		mNewShortcutAnimatePage = -1;
+		mNewShortcutAnimateViews.clear();
+		mWorkspace.clearDropTargets();
+		int count = workspace.getChildCount();
+		for (int i = 0; i < count; i++) {
+			// Use removeAllViewsInLayout() to avoid an extra requestLayout()
+			// and invalidate().
+			final CellLayout layoutParent = (CellLayout) workspace
+					.getChildAt(i);
+			layoutParent.removeAllViewsInLayout();
+		}
+		mWidgetsToAdvance.clear();
+	}
+
+	/**
+	 * Bind the items start-end from the list.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {
+		setLoadOnResume();
+
+		// Get the list of added shortcuts and intersect them with the set of
+		// shortcuts here
+		Set<String> newApps = new HashSet<String>();
+		newApps = mSharedPrefs.getStringSet(
+				InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
+
+		Workspace workspace = mWorkspace;
+		for (int i = start; i < end; i++) {
+			final ItemInfo item = shortcuts.get(i);
+
+			// Short circuit if we are loading dock items for a configuration
+			// which has no dock
+			if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
+			) {
+				continue;
+			}
+
+			switch (item.itemType) {
+			case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+			case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+				ShortcutInfo info = (ShortcutInfo) item;
+				String uri = info.intent.toUri(0).toString();
+				View shortcut = createShortcut(info);
+				workspace.addInScreen(shortcut, item.container, item.screen,
+						item.cellX, item.cellY, 1, 1, false);
+				boolean animateIconUp = false;
+				synchronized (newApps) {
+					if (newApps.contains(uri)) {
+						animateIconUp = newApps.remove(uri);
+					}
+				}
+				if (animateIconUp) {
+					// Prepare the view to be animated up
+					shortcut.setAlpha(0f);
+					shortcut.setScaleX(0f);
+					shortcut.setScaleY(0f);
+					mNewShortcutAnimatePage = item.screen;
+					if (!mNewShortcutAnimateViews.contains(shortcut)) {
+						mNewShortcutAnimateViews.add(shortcut);
+					}
+				}
+				break;
+			case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+				FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon,
+						this, (ViewGroup) workspace.getChildAt(workspace
+								.getCurrentPage()), (FolderInfo) item,
+						mIconCache);
+				workspace.addInScreen(newFolder, item.container, item.screen,
+						item.cellX, item.cellY, 1, 1, false);
+				break;
+			}
+		}
+
+		workspace.requestLayout();
+	}
+
+	/**
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindFolders(HashMap<Long, FolderInfo> folders) {
+		setLoadOnResume();
+		sFolders.clear();
+		sFolders.putAll(folders);
+	}
+
+	/**
+	 * Add the views for a widget to the workspace.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindAppWidget(LauncherAppWidgetInfo item) {
+		setLoadOnResume();
+
+		final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
+		if (DEBUG_WIDGETS) {
+			Log.d(TAG, "bindAppWidget: " + item);
+		}
+		final Workspace workspace = mWorkspace;
+
+		final int appWidgetId = item.appWidgetId;
+		final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager
+				.getAppWidgetInfo(appWidgetId);
+		if (DEBUG_WIDGETS) {
+			Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId
+					+ " belongs to component " + appWidgetInfo.provider);
+		}
+
+		item.hostView = mAppWidgetHost.createView(this, appWidgetId,
+				appWidgetInfo);
+
+		item.hostView.setTag(item);
+		item.onBindAppWidget(this);
+
+		workspace.addInScreen(item.hostView, item.container, item.screen,
+				item.cellX, item.cellY, item.spanX, item.spanY, false);
+		addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
+
+		workspace.requestLayout();
+
+		if (DEBUG_WIDGETS) {
+			Log.d(TAG, "bound widget id=" + item.appWidgetId + " in "
+					+ (SystemClock.uptimeMillis() - start) + "ms");
+		}
+	}
+
+	public void onPageBoundSynchronously(int page) {
+		mSynchronouslyBoundPages.add(page);
+	}
+
+	/**
+	 * Callback saying that there aren't any more items to bind.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void finishBindingItems() {
+		setLoadOnResume();
+
+		if (mSavedState != null) {
+			if (!mWorkspace.hasFocus()) {
+				mWorkspace.getChildAt(mWorkspace.getCurrentPage())
+						.requestFocus();
+			}
+			mSavedState = null;
+		}
+
+		mWorkspace.restoreInstanceStateForRemainingPages();
+
+		// If we received the result of any pending adds while the loader was
+		// running (e.g. the
+		// widget configuration forced an orientation change), process them now.
+		for (int i = 0; i < sPendingAddList.size(); i++) {
+			completeAdd(sPendingAddList.get(i));
+		}
+		sPendingAddList.clear();
+
+		// Update the market app icon as necessary (the other icons will be
+		// managed in response to
+		// package changes in bindSearchablesChanged()
+		updateAppMarketIcon();
+
+		// Animate up any icons as necessary
+		if (mVisible || mWorkspaceLoading) {
+			Runnable newAppsRunnable = new Runnable() {
+				@Override
+				public void run() {
+					runNewAppsAnimation(false);
+				}
+			};
+
+			boolean willSnapPage = mNewShortcutAnimatePage > -1
+					&& mNewShortcutAnimatePage != mWorkspace.getCurrentPage();
+			if (canRunNewAppsAnimation()) {
+				// If the user has not interacted recently, then either snap to
+				// the new page to show
+				// the new-apps animation or just run them if they are to appear
+				// on the current page
+				if (willSnapPage) {
+					mWorkspace.snapToPage(mNewShortcutAnimatePage,
+							newAppsRunnable);
+				} else {
+					runNewAppsAnimation(false);
+				}
+			} else {
+				// If the user has interacted recently, then just add the items
+				// in place if they
+				// are on another page (or just normally if they are added to
+				// the current page)
+				runNewAppsAnimation(willSnapPage);
+			}
+		}
+
+		mWorkspaceLoading = false;
+	}
+
+	private boolean canRunNewAppsAnimation() {
+		long diff = System.currentTimeMillis()
+				- mDragController.getLastGestureUpTime();
+		return diff > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000);
+	}
+
+	/**
+	 * Runs a new animation that scales up icons that were added while Launcher
+	 * was in the background.
+	 * 
+	 * @param immediate
+	 *            whether to run the animation or show the results immediately
+	 */
+	private void runNewAppsAnimation(boolean immediate) {
+		AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
+		Collection<Animator> bounceAnims = new ArrayList<Animator>();
+
+		// Order these new views spatially so that they animate in order
+		Collections.sort(mNewShortcutAnimateViews, new Comparator<View>() {
+			@Override
+			public int compare(View a, View b) {
+				CellLayout.LayoutParams alp = (CellLayout.LayoutParams) a
+						.getLayoutParams();
+				CellLayout.LayoutParams blp = (CellLayout.LayoutParams) b
+						.getLayoutParams();
+				int cellCountX = LauncherModel.getCellCountX();
+				return (alp.cellY * cellCountX + alp.cellX)
+						- (blp.cellY * cellCountX + blp.cellX);
+			}
+		});
+
+		// Animate each of the views in place (or show them immediately if
+		// requested)
+		if (immediate) {
+			for (View v : mNewShortcutAnimateViews) {
+				v.setAlpha(1f);
+				v.setScaleX(1f);
+				v.setScaleY(1f);
+			}
+		} else {
+			for (int i = 0; i < mNewShortcutAnimateViews.size(); ++i) {
+				View v = mNewShortcutAnimateViews.get(i);
+				ValueAnimator bounceAnim = LauncherAnimUtils
+						.ofPropertyValuesHolder(v,
+								PropertyValuesHolder.ofFloat("alpha", 1f),
+								PropertyValuesHolder.ofFloat("scaleX", 1f),
+								PropertyValuesHolder.ofFloat("scaleY", 1f));
+				bounceAnim
+						.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
+				bounceAnim.setStartDelay(i
+						* InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
+				bounceAnim
+						.setInterpolator(new SmoothPagedView.OvershootInterpolator());
+				bounceAnims.add(bounceAnim);
+			}
+			anim.playTogether(bounceAnims);
+			anim.addListener(new AnimatorListenerAdapter() {
+				@Override
+				public void onAnimationEnd(Animator animation) {
+					if (mWorkspace != null) {
+						mWorkspace.postDelayed(mBuildLayersRunnable, 500);
+					}
+				}
+			});
+			anim.start();
+		}
+
+		// Clean up
+		mNewShortcutAnimatePage = -1;
+		mNewShortcutAnimateViews.clear();
+		new Thread("clearNewAppsThread") {
+			public void run() {
+				mSharedPrefs
+						.edit()
+						.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1)
+						.putStringSet(
+								InstallShortcutReceiver.NEW_APPS_LIST_KEY, null)
+						.commit();
+			}
+		}.start();
+	}
+
+	@Override
+	public void bindSearchablesChanged() {
+	}
+
+	/**
+	 * Add the icons for all apps.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindAllApplications(final ArrayList<ApplicationInfo> apps) {
+		Runnable setAllAppsRunnable = new Runnable() {
+			public void run() {
+				if (mAppsCustomizeContent != null) {
+					mAppsCustomizeContent.setApps(apps);
+				}
+			}
+		};
+
+		// Remove the progress bar entirely; we could also make it GONE
+		// but better to remove it since we know it's not going to be used
+		View progressBar = mAppsCustomizeTabHost
+				.findViewById(R.id.apps_customize_progress_bar);
+		if (progressBar != null) {
+			((ViewGroup) progressBar.getParent()).removeView(progressBar);
+
+			// We just post the call to setApps so the user sees the progress
+			// bar
+			// disappear-- otherwise, it just looks like the progress bar froze
+			// which doesn't look great
+			mAppsCustomizeTabHost.post(setAllAppsRunnable);
+		} else {
+			// If we did not initialize the spinner in onCreate, then we can
+			// directly set the
+			// list of applications without waiting for any progress bars views
+			// to be hidden.
+			setAllAppsRunnable.run();
+		}
+	}
+
+	/**
+	 * A package was installed.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
+		setLoadOnResume();
+
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.addApps(apps);
+		}
+		ArrayList<String> appsName = new ArrayList<String>();
+
+		for (ApplicationInfo app : apps) {
+			appsName.add(app.getPackageName());
+		}
+
+		// update AppSwitcher
+		updateAppSwitcherData(appsName);
+
+		// update AppSwitcher widget
+		updateAppSwitcherWidgets();
+
+		// save
+		saveAppSwitcherData();
+	}
+
+	/**
+	 * A package was updated.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindAppsUpdated(ArrayList<ApplicationInfo> apps) {
+		setLoadOnResume();
+		if (mWorkspace != null) {
+			mWorkspace.updateShortcuts(apps);
+		}
+
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.updateApps(apps);
+		}
+
+		ArrayList<String> appsName = new ArrayList<String>();
+
+		for (ApplicationInfo app : apps) {
+			appsName.add(app.getPackageName());
+		}
+
+		// update AppSwitcher
+		updateAppSwitcherData(appsName);
+
+		// update AppSwitcher widget
+		updateAppSwitcherWidgets();
+
+		// save
+		saveAppSwitcherData();
+	}
+
+	/**
+	 * A package was uninstalled.
+	 * 
+	 * Implementation of the method from LauncherModel.Callbacks.
+	 */
+	public void bindAppsRemoved(ArrayList<String> packageNames,
+			boolean permanent) {
+		if (permanent) {
+			mWorkspace.removeItems(packageNames);
+		}
+
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.removeApps(packageNames);
+		}
+
+		// Notify the drag controller
+		mDragController.onAppsRemoved(packageNames, this);
+
+		// update AppSwitcher
+		updateAppSwitcherData(packageNames);
+
+		// update AppSwitcher widget
+		updateAppSwitcherWidgets();
+
+		// save
+		saveAppSwitcherData();
+	}
+
+	private void updateAppSwitcherData(ArrayList<String> packageNames) {
+		List<ApplicationRunInformation> allApps = AppDiscoverer.getInstance()
+				.getAllAppRunInfo();
+
+		List<ApplicationRunInformation> appsToRemove = new ArrayList<ApplicationRunInformation>();
+
+		for (ApplicationRunInformation appRunInfo : allApps) {
+			if (packageNames.contains(appRunInfo.getComponentName()
+					.getPackageName())) {
+				appsToRemove.add(appRunInfo);
+			}
+		}
+
+		for (ApplicationRunInformation appToRemove : appsToRemove) {
+			AppDiscoverer.getInstance().applicationRemoved(
+					appToRemove.getComponentName());
+		}
+	}
+
+	/**
+	 * A number of packages were updated.
+	 */
+	public void bindPackagesUpdated() {
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.onPackagesUpdated();
+		}
+	}
+
+	private int mapConfigurationOriActivityInfoOri(int configOri) {
+		final Display d = getWindowManager().getDefaultDisplay();
+		int naturalOri = Configuration.ORIENTATION_LANDSCAPE;
+		switch (d.getRotation()) {
+		case Surface.ROTATION_0:
+		case Surface.ROTATION_180:
+			// We are currently in the same basic orientation as the natural
+			// orientation
+			naturalOri = configOri;
+			break;
+		case Surface.ROTATION_90:
+		case Surface.ROTATION_270:
+			// We are currently in the other basic orientation to the natural
+			// orientation
+			naturalOri = (configOri == Configuration.ORIENTATION_LANDSCAPE) ? Configuration.ORIENTATION_PORTRAIT
+					: Configuration.ORIENTATION_LANDSCAPE;
+			break;
+		}
+
+		int[] oriMap = { ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
+				ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
+				ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
+				ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE };
+		// Since the map starts at portrait, we need to offset if this device's
+		// natural orientation
+		// is landscape.
+		int indexOffset = 0;
+		if (naturalOri == Configuration.ORIENTATION_LANDSCAPE) {
+			indexOffset = 1;
+		}
+		return oriMap[(d.getRotation() + indexOffset) % 4];
+	}
+
+	public boolean isRotationEnabled() {
+		boolean enableRotation = sForceEnableRotation
+				|| getResources().getBoolean(R.bool.allow_rotation);
+		return enableRotation;
+	}
+
+	public void lockScreenOrientation() {
+		if (isRotationEnabled()) {
+			setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
+					.getConfiguration().orientation));
+		}
+	}
+
+	public void unlockScreenOrientation(boolean immediate) {
+		if (isRotationEnabled()) {
+			if (immediate) {
+				setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+			} else {
+				mHandler.postDelayed(new Runnable() {
+					public void run() {
+						setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+					}
+				}, mRestoreScreenOrientationDelay);
+			}
+		}
+	}
+
+	private boolean isClingsEnabled() {
+		return false;
+	}
+
+	private Cling initCling(int clingId, int[] positionData, boolean animate,
+			int delay) {
+		final Cling cling = (Cling) findViewById(clingId);
+		if (cling != null) {
+			cling.init(this, positionData);
+			cling.setVisibility(View.VISIBLE);
+			cling.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+			if (animate) {
+				cling.buildLayer();
+				cling.setAlpha(0f);
+				cling.animate().alpha(1f)
+						.setInterpolator(new AccelerateInterpolator())
+						.setDuration(SHOW_CLING_DURATION).setStartDelay(delay)
+						.start();
+			} else {
+				cling.setAlpha(1f);
+			}
+			cling.setFocusableInTouchMode(true);
+			cling.post(new Runnable() {
+				public void run() {
+					cling.setFocusable(true);
+					cling.requestFocus();
+				}
+			});
+			mHideFromAccessibilityHelper.setImportantForAccessibilityToNo(
+					mDragLayer, clingId == R.id.all_apps_cling);
+		}
+		return cling;
+	}
+
+	private void dismissCling(final Cling cling, final String flag, int duration) {
+		// To catch cases where siblings of top-level views are made invisible,
+		// just check whether
+		// the cling is directly set to GONE before dismissing it.
+		if (cling != null && cling.getVisibility() != View.GONE) {
+			ObjectAnimator anim = LauncherAnimUtils.ofFloat(cling, "alpha", 0f);
+			anim.setDuration(duration);
+			anim.addListener(new AnimatorListenerAdapter() {
+				public void onAnimationEnd(Animator animation) {
+					cling.setVisibility(View.GONE);
+					cling.cleanup();
+					// We should update the shared preferences on a background
+					// thread
+					new Thread("dismissClingThread") {
+						public void run() {
+							SharedPreferences.Editor editor = mSharedPrefs
+									.edit();
+							editor.putBoolean(flag, true);
+							editor.commit();
+						}
+					}.start();
+				};
+			});
+			anim.start();
+			mHideFromAccessibilityHelper
+					.restoreImportantForAccessibility(mDragLayer);
+		}
+	}
+
+	private void removeCling(int id) {
+		final View cling = findViewById(id);
+		if (cling != null) {
+			final ViewGroup parent = (ViewGroup) cling.getParent();
+			parent.post(new Runnable() {
+				@Override
+				public void run() {
+					parent.removeView(cling);
+				}
+			});
+			mHideFromAccessibilityHelper
+					.restoreImportantForAccessibility(mDragLayer);
+		}
+	}
+
+	private boolean skipCustomClingIfNoAccounts() {
+		Cling cling = (Cling) findViewById(R.id.workspace_cling);
+		boolean customCling = cling.getDrawIdentifier().equals(
+				"workspace_custom");
+		if (customCling) {
+			AccountManager am = AccountManager.get(this);
+			Account[] accounts = am.getAccountsByType("com.google");
+			return accounts.length == 0;
+		}
+		return false;
+	}
+
+	public void showFirstRunWorkspaceCling() {
+		// Enable the clings only if they have not been dismissed before
+		if (isClingsEnabled()
+				&& !mSharedPrefs.getBoolean(
+						Cling.WORKSPACE_CLING_DISMISSED_KEY, false)
+				&& !skipCustomClingIfNoAccounts()) {
+			// If we're not using the default workspace layout, replace
+			// workspace cling
+			// with a custom workspace cling (usually specified in an overlay)
+			// For now, only do this on tablets
+			if (mSharedPrefs.getInt(
+					LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0
+					&& getResources().getBoolean(R.bool.config_useCustomClings)) {
+				// Use a custom cling
+				View cling = findViewById(R.id.workspace_cling);
+				ViewGroup clingParent = (ViewGroup) cling.getParent();
+				int clingIndex = clingParent.indexOfChild(cling);
+				clingParent.removeViewAt(clingIndex);
+				View customCling = mInflater.inflate(
+						R.layout.custom_workspace_cling, clingParent, false);
+				clingParent.addView(customCling, clingIndex);
+				customCling.setId(R.id.workspace_cling);
+			}
+			initCling(R.id.workspace_cling, null, false, 0);
+		} else {
+			removeCling(R.id.workspace_cling);
+		}
+	}
+
+	public void showFirstRunAllAppsCling(int[] position) {
+		// Enable the clings only if they have not been dismissed before
+		if (isClingsEnabled()
+				&& !mSharedPrefs.getBoolean(Cling.ALLAPPS_CLING_DISMISSED_KEY,
+						false)) {
+			initCling(R.id.all_apps_cling, position, true, 0);
+		} else {
+			removeCling(R.id.all_apps_cling);
+		}
+	}
+
+	public Cling showFirstRunFoldersCling() {
+		// Enable the clings only if they have not been dismissed before
+		if (isClingsEnabled()
+				&& !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY,
+						false)) {
+			return initCling(R.id.folder_cling, null, true, 0);
+		} else {
+			removeCling(R.id.folder_cling);
+			return null;
+		}
+	}
+
+	public boolean isFolderClingVisible() {
+		Cling cling = (Cling) findViewById(R.id.folder_cling);
+		if (cling != null) {
+			return cling.getVisibility() == View.VISIBLE;
+		}
+		return false;
+	}
+
+	public void dismissWorkspaceCling(View v) {
+		Cling cling = (Cling) findViewById(R.id.workspace_cling);
+		dismissCling(cling, Cling.WORKSPACE_CLING_DISMISSED_KEY,
+				DISMISS_CLING_DURATION);
+	}
+
+	public void dismissAllAppsCling(View v) {
+		Cling cling = (Cling) findViewById(R.id.all_apps_cling);
+		dismissCling(cling, Cling.ALLAPPS_CLING_DISMISSED_KEY,
+				DISMISS_CLING_DURATION);
+	}
+
+	public void dismissFolderCling(View v) {
+		Cling cling = (Cling) findViewById(R.id.folder_cling);
+		dismissCling(cling, Cling.FOLDER_CLING_DISMISSED_KEY,
+				DISMISS_CLING_DURATION);
+	}
+
+	/**
+	 * Prints out out state for debugging.
+	 */
+	public void dumpState() {
+		Log.d(TAG, "BEGIN launcher2 dump state for launcher " + this);
+		Log.d(TAG, "mSavedState=" + mSavedState);
+		Log.d(TAG, "mWorkspaceLoading=" + mWorkspaceLoading);
+		Log.d(TAG, "mRestoring=" + mRestoring);
+		Log.d(TAG, "mWaitingForResult=" + mWaitingForResult);
+		Log.d(TAG, "mSavedInstanceState=" + mSavedInstanceState);
+		Log.d(TAG, "sFolders.size=" + sFolders.size());
+		mModel.dumpState();
+
+		if (mAppsCustomizeContent != null) {
+			mAppsCustomizeContent.dumpState();
+		}
+		Log.d(TAG, "END launcher2 dump state");
+	}
+
+	@Override
+	public void dump(String prefix, FileDescriptor fd, PrintWriter writer,
+			String[] args) {
+		super.dump(prefix, fd, writer, args);
+		writer.println(" ");
+		writer.println("Debug logs: ");
+		for (int i = 0; i < sDumpLogs.size(); i++) {
+			writer.println("  " + sDumpLogs.get(i));
+		}
+	}
+
+	public static void dumpDebugLogsToConsole() {
+		Log.d(TAG, "");
+		Log.d(TAG, "*********************");
+		Log.d(TAG, "Launcher debug logs: ");
+		for (int i = 0; i < sDumpLogs.size(); i++) {
+			Log.d(TAG, "  " + sDumpLogs.get(i));
+		}
+		Log.d(TAG, "*********************");
+		Log.d(TAG, "");
+	}
+
+	public EdgeSwipeInterceptorViewListener getEdgeSwipeListener() {
+		return null;
+	}
+
+	private class ResetDialogFragment extends DialogFragment {
+		@Override
+		public Dialog onCreateDialog(Bundle savedInstanceState) {
+			// Use the Builder class for convenient dialog construction
+			AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+			builder.setMessage(getString(R.string.app_switcher_reset_message))
+					.setPositiveButton(getString(android.R.string.ok),
+							new DialogInterface.OnClickListener() {
+								public void onClick(DialogInterface dialog,
+										int id) {
+									// remove the data
+									AppDiscoverer.getInstance().resetState();
+
+									saveAppSwitcherData();
+
+									updateAppSwitcherWidgets();
+								}
+							})
+					.setNegativeButton(getString(android.R.string.cancel),
+							new DialogInterface.OnClickListener() {
+								public void onClick(DialogInterface dialog,
+										int id) {
+								}
+							});
+			// Create the AlertDialog object and return it
+			return builder.create();
+		}
+	}
+
+	public void startEditFavorites() {
+
+		startActivityForResult(new Intent(this, EditFavoritesActivity.class),
+				REQUEST_EDIT_FAVORITES);
+
+		startOOBEActivityOnFirstUse(SHOW_OOBE_EDIT_FAVORITES,
+				OOBEActivity.OOBE_EDIT_FAVORITES_TUTORIAL);
+	}
+
+	/**
+	 * Shows the stat values of fairphone. If the activity does not exists it
+	 * fails silently.
+	 */
+	private boolean startFairphoneValues() {
+		boolean result = false;
+
+		if (mSharedPrefs.getBoolean(SHOW_VALUES_VIDEO, true)) {
+			Intent launchIntent = getPackageManager()
+					.getLaunchIntentForPackage("org.fairphone.fairphonevalues");
+			if (launchIntent != null) {
+				startActivity(launchIntent);
+				result = true;
+			}
+
+			// disable next view
+			SharedPreferences.Editor editor = mSharedPrefs.edit();
+			editor.putBoolean(SHOW_VALUES_VIDEO, false);
+			editor.commit();
+		}
+
+		return result;
+	}
+	
+	/**
+	 * Show OOBE tutorial on first use of Edge Swipe, Edit Favorites, etc...
+	 * 
+	 * @param oobeToShow
+	 *            Activity identifier: SHOW_OOBE_EDIT_FAVORITES or
+	 *            SHOW_OOBE_EDGE_SWIPE_MENU
+	 * @param oobeTutorial
+	 *            Tutorial to show: OOBEActivity.OOBE_EDIT_FAVORITES_TUTORIAL,
+	 *            OOBEActivity.OOBE_EDGE_SWIPE_TUTORIAL,
+	 *            OOBEActivity.OOBE_FULL_TUTORIAL
+	 */
+	private boolean startOOBEActivityOnFirstUse(String oobeToShow,
+			int oobeTutorial) {
+		boolean result = false;
+
+		if (mSharedPrefs.getBoolean(oobeToShow, true)) {
+			startOOBEActivity(oobeTutorial);
+			SharedPreferences.Editor editor = mSharedPrefs.edit();
+			editor.putBoolean(oobeToShow, false);
+			editor.commit();
+
+			result = true;
+		}
+
+		return result;
+	}
+
+	/**
+	 * Starts the OOBEActivity in the selected tutorial
+	 * 
+	 * @param oobeTutorial
+	 *            Tutorial to show: OOBEActivity.OOBE_EDIT_FAVORITES_TUTORIAL,
+	 *            OOBEActivity.OOBE_EDGE_SWIPE_TUTORIAL,
+	 *            OOBEActivity.OOBE_FULL_TUTORIAL
+	 */
+	private void startOOBEActivity(int oobeTutorial) {
+		Intent oobeEditFavoritesIntent = new Intent(this, OOBEActivity.class);
+		oobeEditFavoritesIntent.putExtra(OOBEActivity.OOBE_TUTORIAL,
+				oobeTutorial);
+		startActivity(oobeEditFavoritesIntent);
+	}
+
+}
+
+interface LauncherTransitionable {
+	View getContent();
+
+	void onLauncherTransitionPrepare(Launcher l, boolean animated,
+			boolean toWorkspace);
+
+	void onLauncherTransitionStart(Launcher l, boolean animated,
+			boolean toWorkspace);
+
+	void onLauncherTransitionStep(Launcher l, float t);
+
+	void onLauncherTransitionEnd(Launcher l, boolean animated,
+			boolean toWorkspace);
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherAnimUtils.java b/FairphoneHome/src/org/fairphone/launcher/LauncherAnimUtils.java
new file mode 100644
index 0000000..5fe805e
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherAnimUtils.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+
+import java.util.HashSet;
+
+public class LauncherAnimUtils {
+    static HashSet<Animator> sAnimators = new HashSet<Animator>();
+    static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() {
+        public void onAnimationStart(Animator animation) {
+        }
+
+        public void onAnimationRepeat(Animator animation) {
+        }
+
+        public void onAnimationEnd(Animator animation) {
+            sAnimators.remove(animation);
+        }
+
+        public void onAnimationCancel(Animator animation) {
+            sAnimators.remove(animation);
+        }
+    };
+
+    public static void cancelOnDestroyActivity(Animator a) {
+        sAnimators.add(a);
+        a.addListener(sEndAnimListener);
+    }
+
+    public static void onDestroyActivity() {
+        HashSet<Animator> animators = new HashSet<Animator>(sAnimators);
+        for (Animator a : animators) {
+            if (a.isRunning()) {
+                a.cancel();
+            } else {
+                sAnimators.remove(a);
+            }
+        }
+    }
+
+    public static AnimatorSet createAnimatorSet() {
+        AnimatorSet anim = new AnimatorSet();
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+
+    public static ValueAnimator ofFloat(float... values) {
+        ValueAnimator anim = new ValueAnimator();
+        anim.setFloatValues(values);
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+
+    public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
+        ObjectAnimator anim = new ObjectAnimator();
+        anim.setTarget(target);
+        anim.setPropertyName(propertyName);
+        anim.setFloatValues(values);
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+
+    public static ObjectAnimator ofPropertyValuesHolder(Object target,
+            PropertyValuesHolder... values) {
+        ObjectAnimator anim = new ObjectAnimator();
+        anim.setTarget(target);
+        anim.setValues(values);
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherAnimatorUpdateListener.java b/FairphoneHome/src/org/fairphone/launcher/LauncherAnimatorUpdateListener.java
new file mode 100644
index 0000000..7c25fd5
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherAnimatorUpdateListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+
+abstract class LauncherAnimatorUpdateListener implements AnimatorUpdateListener {
+    public void onAnimationUpdate(ValueAnimator animation) {
+        final float b = (Float) animation.getAnimatedValue();
+        final float a = 1f - b;
+        onAnimationUpdate(a, b);
+    }
+
+    abstract void onAnimationUpdate(float a, float b);
+}
\ No newline at end of file
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetHost.java b/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetHost.java
new file mode 100644
index 0000000..3af5133
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetHost.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+
+/**
+ * Specific {@link AppWidgetHost} that creates our {@link LauncherAppWidgetHostView}
+ * which correctly captures all long-press events. This ensures that users can
+ * always pick up and move widgets.
+ */
+public class LauncherAppWidgetHost extends AppWidgetHost {
+
+    Launcher mLauncher;
+
+    public LauncherAppWidgetHost(Launcher launcher, int hostId) {
+        super(launcher, hostId);
+        mLauncher = launcher;
+    }
+
+    @Override
+    protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+            AppWidgetProviderInfo appWidget) {
+        return new LauncherAppWidgetHostView(context);
+    }
+
+    @Override
+    public void stopListening() {
+        super.stopListening();
+        clearViews();
+    }
+
+    protected void onProvidersChanged() {
+        // Once we get the message that widget packages are updated, we need to rebind items
+        // in AppsCustomize accordingly.
+        mLauncher.bindPackagesUpdated();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetHostView.java b/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetHostView.java
new file mode 100644
index 0000000..2578963
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetHostView.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.appwidget.AppWidgetHostView;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RemoteViews;
+
+import org.fairphone.launcher.R;
+
+/**
+ * {@inheritDoc}
+ */
+public class LauncherAppWidgetHostView extends AppWidgetHostView {
+    private CheckLongPressHelper mLongPressHelper;
+    private LayoutInflater mInflater;
+    private Context mContext;
+    private int mPreviousOrientation;
+
+    public LauncherAppWidgetHostView(Context context) {
+        super(context);
+        mContext = context;
+        mLongPressHelper = new CheckLongPressHelper(this);
+        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    @Override
+    protected View getErrorView() {
+        return mInflater.inflate(R.layout.appwidget_error, this, false);
+    }
+
+    @Override
+    public void updateAppWidget(RemoteViews remoteViews) {
+        // Store the orientation in which the widget was inflated
+        mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
+        super.updateAppWidget(remoteViews);
+    }
+
+    public boolean orientationChangedSincedInflation() {
+        int orientation = mContext.getResources().getConfiguration().orientation;
+        if (mPreviousOrientation != orientation) {
+           return true;
+       }
+       return false;
+    }
+
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // Consume any touch events for ourselves after longpress is triggered
+        if (mLongPressHelper.hasPerformedLongPress()) {
+            mLongPressHelper.cancelLongPress();
+            return true;
+        }
+
+        // Watch for longpress events at this level to make sure
+        // users can always pick up this widget
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN: {
+                mLongPressHelper.postCheckForLongPress();
+                break;
+            }
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mLongPressHelper.cancelLongPress();
+                break;
+        }
+
+        // Otherwise continue letting touch events fall through to children
+        return false;
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        mLongPressHelper.cancelLongPress();
+    }
+
+    @Override
+    public int getDescendantFocusability() {
+        return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetInfo.java b/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetInfo.java
new file mode 100644
index 0000000..26c30c9
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherAppWidgetInfo.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.appwidget.AppWidgetHostView;
+import android.content.ComponentName;
+import android.content.ContentValues;
+
+/**
+ * Represents a widget (either instantiated or about to be) in the Launcher.
+ */
+class LauncherAppWidgetInfo extends ItemInfo {
+
+    /**
+     * Indicates that the widget hasn't been instantiated yet.
+     */
+    static final int NO_ID = -1;
+
+    /**
+     * Identifier for this widget when talking with
+     * {@link android.appwidget.AppWidgetManager} for updates.
+     */
+    int appWidgetId = NO_ID;
+
+    ComponentName providerName;
+
+    // TODO: Are these necessary here?
+    int minWidth = -1;
+    int minHeight = -1;
+
+    private boolean mHasNotifiedInitialWidgetSizeChanged;
+
+    /**
+     * View that holds this widget after it's been created.  This view isn't created
+     * until Launcher knows it's needed.
+     */
+    AppWidgetHostView hostView = null;
+
+    LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
+        itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+        this.appWidgetId = appWidgetId;
+        this.providerName = providerName;
+
+        // Since the widget isn't instantiated yet, we don't know these values. Set them to -1
+        // to indicate that they should be calculated based on the layout and minWidth/minHeight
+        spanX = -1;
+        spanY = -1;
+    }
+
+    @Override
+    void onAddToDatabase(ContentValues values) {
+        super.onAddToDatabase(values);
+        values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
+    }
+
+    /**
+     * When we bind the widget, we should notify the widget that the size has changed if we have not
+     * done so already (only really for default workspace widgets).
+     */
+    void onBindAppWidget(Launcher launcher) {
+        if (!mHasNotifiedInitialWidgetSizeChanged) {
+            notifyWidgetSizeChanged(launcher);
+        }
+    }
+
+    /**
+     * Trigger an update callback to the widget to notify it that its size has changed.
+     */
+    void notifyWidgetSizeChanged(Launcher launcher) {
+        AppWidgetResizeFrame.updateWidgetSizeRanges(hostView, launcher, spanX, spanY);
+        mHasNotifiedInitialWidgetSizeChanged = true;
+    }
+
+    @Override
+    public String toString() {
+        return "AppWidget(id=" + Integer.toString(appWidgetId) + ")";
+    }
+
+    @Override
+    void unbind() {
+        super.unbind();
+        hostView = null;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherApplication.java b/FairphoneHome/src/org/fairphone/launcher/LauncherApplication.java
new file mode 100644
index 0000000..05a059e
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherApplication.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.app.Application;
+import android.app.SearchManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.util.Log;
+
+import org.fairphone.launcher.R;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Base class for those who need to maintain global application state. You can provide your own implementation by specifying 
+ * its name in your AndroidManifest.xml's <application> tag, which will cause that class to be instantiated for you when the 
+ * process for your application/package is created.
+ *
+ * There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality 
+ * in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function 
+ * to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
+ * 
+ */
+public class LauncherApplication extends Application {
+    public LauncherModel mModel;
+    public IconCache mIconCache;
+    private static boolean sIsScreenLarge;
+    private static float sScreenDensity;
+    private static int sLongPressTimeout = 300;
+    private static final String sSharedPreferencesKey = "com.android.launcher2.prefs";
+    WeakReference<LauncherProvider> mLauncherProvider;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        // set sIsScreenXLarge and sScreenDensity *before* creating icon cache
+        sIsScreenLarge = getResources().getBoolean(R.bool.is_large_screen);
+        sScreenDensity = getResources().getDisplayMetrics().density;
+
+        mIconCache = new IconCache(this);
+        mModel = new LauncherModel(this, mIconCache);
+
+        // Register intent receivers
+        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addDataScheme("package");
+        registerReceiver(mModel, filter);
+        filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
+        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        registerReceiver(mModel, filter);
+        filter = new IntentFilter();
+        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+        registerReceiver(mModel, filter);
+        filter = new IntentFilter();
+        filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
+        registerReceiver(mModel, filter);
+
+        // Register for changes to the favorites
+        ContentResolver resolver = getContentResolver();
+        resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
+                mFavoritesObserver);
+    }
+
+    /**
+     * There's no guarantee that this function is ever called.
+     */
+    @Override
+    public void onTerminate() {
+        super.onTerminate();
+
+        unregisterReceiver(mModel);
+
+        ContentResolver resolver = getContentResolver();
+        resolver.unregisterContentObserver(mFavoritesObserver);
+    }
+
+    /**
+     * Receives notifications whenever the user favorites have changed.
+     */
+    private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            // If the database has ever changed, then we really need to force a reload of the
+            // workspace on the next load
+            mModel.resetLoadedState(false, true);
+            mModel.startLoaderFromBackground();
+        }
+    };
+
+    LauncherModel setLauncher(Launcher launcher) {
+        mModel.initialize(launcher);
+        return mModel;
+    }
+
+    IconCache getIconCache() {
+        return mIconCache;
+    }
+
+    LauncherModel getModel() {
+        return mModel;
+    }
+
+    void setLauncherProvider(LauncherProvider provider) {
+        mLauncherProvider = new WeakReference<LauncherProvider>(provider);
+    }
+
+    LauncherProvider getLauncherProvider() {
+        return mLauncherProvider.get();
+    }
+
+    public static String getSharedPreferencesKey() {
+        return sSharedPreferencesKey;
+    }
+
+    public static boolean isScreenLarge() {
+        return sIsScreenLarge;
+    }
+
+    public static boolean isScreenLandscape(Context context) {
+        return context.getResources().getConfiguration().orientation ==
+            Configuration.ORIENTATION_LANDSCAPE;
+    }
+
+    public static float getScreenDensity() {
+        return sScreenDensity;
+    }
+
+    public static int getLongPressTimeout() {
+        return sLongPressTimeout;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherModel.java b/FairphoneHome/src/org/fairphone/launcher/LauncherModel.java
new file mode 100644
index 0000000..678bf87
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherModel.java
@@ -0,0 +1,2565 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.app.SearchManager;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.Intent.ShortcutIconResource;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import org.fairphone.launcher.R;
+
+import java.lang.ref.WeakReference;
+import java.net.URISyntaxException;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.fairphone.launcher.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
+import org.fairphone.launcher.edgeswipe.edit.AppDiscoverer;
+
+/**
+ * Maintains in-memory state of the Launcher. It is expected that there should be only one
+ * LauncherModel object held in a static. Also provide APIs for updating the database state
+ * for the Launcher.
+ */
+public class LauncherModel extends BroadcastReceiver {
+    static final boolean DEBUG_LOADERS = false;
+    static final String TAG = "Launcher.Model";
+
+    private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
+    private final boolean mAppsCanBeOnExternalStorage;
+    private int mBatchSize; // 0 is all apps at once
+    private int mAllAppsLoadDelay; // milliseconds between batches
+
+    private final LauncherApplication mApp;
+    private final Object mLock = new Object();
+    private DeferredHandler mHandler = new DeferredHandler();
+    private LoaderTask mLoaderTask;
+    private boolean mIsLoaderTaskRunning;
+
+    // Specific runnable types that are run on the main thread deferred handler, this allows us to
+    // clear all queued binding runnables when the Launcher activity is destroyed.
+    private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;
+    private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;
+
+
+    private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
+    static {
+        sWorkerThread.start();
+    }
+    private static final Handler sWorker = new Handler(sWorkerThread.getLooper());
+
+    // We start off with everything not loaded.  After that, we assume that
+    // our monitoring of the package manager provides all updates and we never
+    // need to do a requery.  These are only ever touched from the loader thread.
+    private boolean mWorkspaceLoaded;
+    private boolean mAllAppsLoaded;
+
+    // When we are loading pages synchronously, we can't just post the binding of items on the side
+    // pages as this delays the rotation process.  Instead, we wait for a callback from the first
+    // draw (in Workspace) to initiate the binding of the remaining side pages.  Any time we start
+    // a normal load, we also clear this set of Runnables.
+    static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();
+
+    private WeakReference<Callbacks> mCallbacks;
+
+    // < only access in worker thread >
+    private AllAppsList mBgAllAppsList;
+
+    // The lock that must be acquired before referencing any static bg data structures.  Unlike
+    // other locks, this one can generally be held long-term because we never expect any of these
+    // static data structures to be referenced outside of the worker thread except on the first
+    // load after configuration change.
+    static final Object sBgLock = new Object();
+
+    // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by
+    // LauncherModel to their ids
+    static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();
+
+    // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts
+    //       created by LauncherModel that are directly on the home screen (however, no widgets or
+    //       shortcuts within folders).
+    static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();
+
+    // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()
+    static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets =
+        new ArrayList<LauncherAppWidgetInfo>();
+
+    // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
+    static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();
+
+    // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database
+    static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();
+    // </ only access in worker thread >
+
+    private IconCache mIconCache;
+    private Bitmap mDefaultIcon;
+
+    private static int mCellCountX;
+    private static int mCellCountY;
+
+    protected int mPreviousConfigMcc;
+
+    public interface Callbacks {
+        public boolean setLoadOnResume();
+        public int getCurrentWorkspaceScreen();
+        public void startBinding();
+        public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end);
+        public void bindFolders(HashMap<Long,FolderInfo> folders);
+        public void finishBindingItems();
+        public void bindAppWidget(LauncherAppWidgetInfo info);
+        public void bindAllApplications(ArrayList<ApplicationInfo> apps);
+        public void bindAppsAdded(ArrayList<ApplicationInfo> apps);
+        public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);
+        public void bindAppsRemoved(ArrayList<String> packageNames, boolean permanent);
+        public void bindPackagesUpdated();
+        public boolean isAllAppsVisible();
+        public boolean isAllAppsButtonRank(int rank);
+        public void bindSearchablesChanged();
+        public void onPageBoundSynchronously(int page);
+    }
+
+    LauncherModel(LauncherApplication app, IconCache iconCache) {
+    	// check the external storage
+        mAppsCanBeOnExternalStorage = !Environment.isExternalStorageEmulated();
+        mApp = app;
+        // create a list of apps for the all apps view
+        mBgAllAppsList = new AllAppsList(iconCache);
+        mIconCache = iconCache;
+
+        // generate the default button for apps without icons.
+        mDefaultIcon = Utilities.createIconBitmap(
+                mIconCache.getFullResDefaultActivityIcon(), app);
+
+        // open the resource file see config.xml
+        // http://developer.android.com/reference/android/content/res/Resources.html
+        final Resources res = app.getResources();
+        mAllAppsLoadDelay = res.getInteger(R.integer.config_allAppsBatchLoadDelay); // config.xml
+        mBatchSize = res.getInteger(R.integer.config_allAppsBatchSize); // config.xml
+        // gets the configuration 
+        // http://developer.android.com/reference/android/content/res/Configuration.html
+        Configuration config = res.getConfiguration();
+        // IMSI MCC (Mobile Country Code), corresponding to mcc resource qualifier.
+        mPreviousConfigMcc = config.mcc;
+    }
+
+    /** Runs the specified runnable immediately if called from the main thread, otherwise it is
+     * posted on the main thread handler. */
+    private void runOnMainThread(Runnable r) {
+        runOnMainThread(r, 0);
+    }
+    private void runOnMainThread(Runnable r, int type) {
+        if (sWorkerThread.getThreadId() == Process.myTid()) {
+            // If we are on the worker thread, post onto the main handler
+            mHandler.post(r);
+        } else {
+            r.run();
+        }
+    }
+
+    /** Runs the specified runnable immediately if called from the worker thread, otherwise it is
+     * posted on the worker thread handler. */
+    private static void runOnWorkerThread(Runnable r) {
+        if (sWorkerThread.getThreadId() == Process.myTid()) {
+            r.run();
+        } else {
+            // If we are not on the worker thread, then post to the worker handler
+            sWorker.post(r);
+        }
+    }
+
+    public Bitmap getFallbackIcon() {
+        return Bitmap.createBitmap(mDefaultIcon);
+    }
+
+    public void unbindItemInfosAndClearQueuedBindRunnables() {
+        if (sWorkerThread.getThreadId() == Process.myTid()) {
+            throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +
+                    "main thread");
+        }
+
+        // Clear any deferred bind runnables
+        mDeferredBindRunnables.clear();
+        // Remove any queued bind runnables
+        mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);
+        // Unbind all the workspace items
+        unbindWorkspaceItemsOnMainThread();
+    }
+
+    /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */
+    void unbindWorkspaceItemsOnMainThread() {
+        // Ensure that we don't use the same workspace items data structure on the main thread
+        // by making a copy of workspace items first.
+        final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();
+        final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();
+        synchronized (sBgLock) {
+            tmpWorkspaceItems.addAll(sBgWorkspaceItems);
+            tmpAppWidgets.addAll(sBgAppWidgets);
+        }
+        Runnable r = new Runnable() {
+                @Override
+                public void run() {
+                   for (ItemInfo item : tmpWorkspaceItems) {
+                       item.unbind();
+                   }
+                   for (ItemInfo item : tmpAppWidgets) {
+                       item.unbind();
+                   }
+                }
+            };
+        runOnMainThread(r);
+    }
+
+    /**
+     * Adds an item to the DB if it was not created previously, or move it to a new
+     * <container, screen, cellX, cellY>
+     */
+    static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
+            int screen, int cellX, int cellY) {
+        if (item.container == ItemInfo.NO_ID) {
+            // From all apps
+            addItemToDatabase(context, item, container, screen, cellX, cellY, false);
+        } else {
+            // From somewhere else
+            moveItemInDatabase(context, item, container, screen, cellX, cellY);
+        }
+    }
+
+    static void checkItemInfoLocked(
+            final long itemId, final ItemInfo item, StackTraceElement[] stackTrace) {
+        ItemInfo modelItem = sBgItemsIdMap.get(itemId);
+        if (modelItem != null && item != modelItem) {
+            // check all the data is consistent
+            if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {
+                ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;
+                ShortcutInfo shortcut = (ShortcutInfo) item;
+                if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&
+                        modelShortcut.intent.filterEquals(shortcut.intent) &&
+                        modelShortcut.id == shortcut.id &&
+                        modelShortcut.itemType == shortcut.itemType &&
+                        modelShortcut.container == shortcut.container &&
+                        modelShortcut.screen == shortcut.screen &&
+                        modelShortcut.cellX == shortcut.cellX &&
+                        modelShortcut.cellY == shortcut.cellY &&
+                        modelShortcut.spanX == shortcut.spanX &&
+                        modelShortcut.spanY == shortcut.spanY &&
+                        ((modelShortcut.dropPos == null && shortcut.dropPos == null) ||
+                        (modelShortcut.dropPos != null &&
+                                shortcut.dropPos != null &&
+                                modelShortcut.dropPos[0] == shortcut.dropPos[0] &&
+                        modelShortcut.dropPos[1] == shortcut.dropPos[1]))) {
+                    // For all intents and purposes, this is the same object
+                    return;
+                }
+            }
+
+            // the modelItem needs to match up perfectly with item if our model is
+            // to be consistent with the database-- for now, just require
+            // modelItem == item or the equality check above
+            String msg = "item: " + ((item != null) ? item.toString() : "null") +
+                    "modelItem: " +
+                    ((modelItem != null) ? modelItem.toString() : "null") +
+                    "Error: ItemInfo passed to checkItemInfo doesn't match original";
+            RuntimeException e = new RuntimeException(msg);
+            if (stackTrace != null) {
+                e.setStackTrace(stackTrace);
+            }
+            throw e;
+        }
+    }
+
+    static void checkItemInfo(final ItemInfo item) {
+        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        final long itemId = item.id;
+        Runnable r = new Runnable() {
+            public void run() {
+                synchronized (sBgLock) {
+                    checkItemInfoLocked(itemId, item, stackTrace);
+                }
+            }
+        };
+        runOnWorkerThread(r);
+    }
+
+    static void updateItemInDatabaseHelper(Context context, final ContentValues values,
+            final ItemInfo item, final String callingFunction) {
+        final long itemId = item.id;
+        final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);
+        final ContentResolver cr = context.getContentResolver();
+
+        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        Runnable r = new Runnable() {
+            public void run() {
+                cr.update(uri, values, null, null);
+
+                // Lock on mBgLock *after* the db operation
+                synchronized (sBgLock) {
+                    checkItemInfoLocked(itemId, item, stackTrace);
+
+                    if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                            item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                        // Item is in a folder, make sure this folder exists
+                        if (!sBgFolders.containsKey(item.container)) {
+                            // An items container is being set to a that of an item which is not in
+                            // the list of Folders.
+                            String msg = "item: " + item + " container being set to: " +
+                                    item.container + ", not in the list of folders";
+                            Log.e(TAG, msg);
+                            Launcher.dumpDebugLogsToConsole();
+                        }
+                    }
+
+                    // Items are added/removed from the corresponding FolderInfo elsewhere, such
+                    // as in Workspace.onDrop. Here, we just add/remove them from the list of items
+                    // that are on the desktop, as appropriate
+                    ItemInfo modelItem = sBgItemsIdMap.get(itemId);
+                    if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
+                            modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                        switch (modelItem.itemType) {
+                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                                if (!sBgWorkspaceItems.contains(modelItem)) {
+                                    sBgWorkspaceItems.add(modelItem);
+                                }
+                                break;
+                            default:
+                                break;
+                        }
+                    } else {
+                        sBgWorkspaceItems.remove(modelItem);
+                    }
+                }
+            }
+        };
+        runOnWorkerThread(r);
+    }
+
+    /**
+     * Move an item in the DB to a new <container, screen, cellX, cellY>
+     */
+    static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
+            final int screen, final int cellX, final int cellY) {
+        String transaction = "DbDebug    Modify item (" + item.title + ") in db, id: " + item.id +
+                " (" + item.container + ", " + item.screen + ", " + item.cellX + ", " + item.cellY +
+                ") --> " + "(" + container + ", " + screen + ", " + cellX + ", " + cellY + ")";
+        Launcher.sDumpLogs.add(transaction);
+        Log.d(TAG, transaction);
+        item.container = container;
+        item.cellX = cellX;
+        item.cellY = cellY;
+
+        // We store hotseat items in canonical form which is this orientation invariant position
+        // in the hotseat
+        if (context instanceof Launcher && screen < 0 &&
+                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+        } else {
+            item.screen = screen;
+        }
+
+        final ContentValues values = new ContentValues();
+        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
+        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
+        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
+        values.put(LauncherSettings.Favorites.SCREEN, item.screen);
+
+        updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
+    }
+
+    /**
+     * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>
+     */
+    static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,
+            final int screen, final int cellX, final int cellY, final int spanX, final int spanY) {
+        String transaction = "DbDebug    Modify item (" + item.title + ") in db, id: " + item.id +
+                " (" + item.container + ", " + item.screen + ", " + item.cellX + ", " + item.cellY +
+                ") --> " + "(" + container + ", " + screen + ", " + cellX + ", " + cellY + ")";
+        Launcher.sDumpLogs.add(transaction);
+        Log.d(TAG, transaction);
+        item.cellX = cellX;
+        item.cellY = cellY;
+        item.spanX = spanX;
+        item.spanY = spanY;
+
+        // We store hotseat items in canonical form which is this orientation invariant position
+        // in the hotseat
+        if (context instanceof Launcher && screen < 0 &&
+                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+        } else {
+            item.screen = screen;
+        }
+
+        final ContentValues values = new ContentValues();
+        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
+        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
+        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
+        values.put(LauncherSettings.Favorites.SPANX, item.spanX);
+        values.put(LauncherSettings.Favorites.SPANY, item.spanY);
+        values.put(LauncherSettings.Favorites.SCREEN, item.screen);
+
+        updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");
+    }
+
+    /**
+     * Update an item to the database in a specified container.
+     */
+    static void updateItemInDatabase(Context context, final ItemInfo item) {
+        final ContentValues values = new ContentValues();
+        item.onAddToDatabase(values);
+        item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
+        updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");
+    }
+
+    /**
+     * Returns true if the shortcuts already exists in the database.
+     * we identify a shortcut by its title and intent.
+     */
+    static boolean shortcutExists(Context context, String title, Intent intent) {
+        final ContentResolver cr = context.getContentResolver();
+        Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
+            new String[] { "title", "intent" }, "title=? and intent=?",
+            new String[] { title, intent.toUri(0) }, null);
+        boolean result = false;
+        try {
+            result = c.moveToFirst();
+        } finally {
+            c.close();
+        }
+        return result;
+    }
+
+    /**
+     * Returns an ItemInfo array containing all the items in the LauncherModel.
+     * The ItemInfo.id is not set through this function.
+     */
+    static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {
+        ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
+        final ContentResolver cr = context.getContentResolver();
+        Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {
+                LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,
+                LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
+                LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY }, null, null, null);
+
+        final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+        final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+        final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+        final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+        final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+        final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
+        final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
+
+        try {
+            while (c.moveToNext()) {
+                ItemInfo item = new ItemInfo();
+                item.cellX = c.getInt(cellXIndex);
+                item.cellY = c.getInt(cellYIndex);
+                item.spanX = c.getInt(spanXIndex);
+                item.spanY = c.getInt(spanYIndex);
+                item.container = c.getInt(containerIndex);
+                item.itemType = c.getInt(itemTypeIndex);
+                item.screen = c.getInt(screenIndex);
+
+                items.add(item);
+            }
+        } catch (Exception e) {
+            items.clear();
+        } finally {
+            c.close();
+        }
+
+        return items;
+    }
+
+    /**
+     * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.
+     */
+    FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {
+        final ContentResolver cr = context.getContentResolver();
+        Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
+                "_id=? and (itemType=? or itemType=?)",
+                new String[] { String.valueOf(id),
+                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);
+
+        try {
+            if (c.moveToFirst()) {
+                final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+                final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+                final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+                final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+                final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+                final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+
+                FolderInfo folderInfo = null;
+                switch (c.getInt(itemTypeIndex)) {
+                    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                        folderInfo = findOrMakeFolder(folderList, id);
+                        break;
+                }
+
+                folderInfo.title = c.getString(titleIndex);
+                folderInfo.id = id;
+                folderInfo.container = c.getInt(containerIndex);
+                folderInfo.screen = c.getInt(screenIndex);
+                folderInfo.cellX = c.getInt(cellXIndex);
+                folderInfo.cellY = c.getInt(cellYIndex);
+
+                return folderInfo;
+            }
+        } finally {
+            c.close();
+        }
+
+        return null;
+    }
+
+    /**
+     * Add an item to the database in a specified container. Sets the container, screen, cellX and
+     * cellY fields of the item. Also assigns an ID to the item.
+     */
+    static void addItemToDatabase(Context context, final ItemInfo item, final long container,
+            final int screen, final int cellX, final int cellY, final boolean notify) {
+        item.container = container;
+        item.cellX = cellX;
+        item.cellY = cellY;
+        // We store hotseat items in canonical form which is this orientation invariant position
+        // in the hotseat
+        if (context instanceof Launcher && screen < 0 &&
+                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+        } else {
+            item.screen = screen;
+        }
+
+        final ContentValues values = new ContentValues();
+        final ContentResolver cr = context.getContentResolver();
+        item.onAddToDatabase(values);
+
+        LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+        item.id = app.getLauncherProvider().generateNewId();
+        values.put(LauncherSettings.Favorites._ID, item.id);
+        item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
+
+        Runnable r = new Runnable() {
+            public void run() {
+                String transaction = "DbDebug    Add item (" + item.title + ") to db, id: "
+                        + item.id + " (" + container + ", " + screen + ", " + cellX + ", "
+                        + cellY + ")";
+                Launcher.sDumpLogs.add(transaction);
+                Log.d(TAG, transaction);
+
+                cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
+                        LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
+
+                // Lock on mBgLock *after* the db operation
+                synchronized (sBgLock) {
+                    checkItemInfoLocked(item.id, item, null);
+                    sBgItemsIdMap.put(item.id, item);
+                    switch (item.itemType) {
+                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                            sBgFolders.put(item.id, (FolderInfo) item);
+                            // Fall through
+                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
+                                    item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                                sBgWorkspaceItems.add(item);
+                            } else {
+                                if (!sBgFolders.containsKey(item.container)) {
+                                    // Adding an item to a folder that doesn't exist.
+                                    String msg = "adding item: " + item + " to a folder that " +
+                                            " doesn't exist";
+                                    Log.e(TAG, msg);
+                                    Launcher.dumpDebugLogsToConsole();
+                                }
+                            }
+                            break;
+                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                            sBgAppWidgets.add((LauncherAppWidgetInfo) item);
+                            break;
+                    }
+                }
+            }
+        };
+        runOnWorkerThread(r);
+    }
+
+    /**
+     * Creates a new unique child id, for a given cell span across all layouts.
+     */
+    static int getCellLayoutChildId(
+            long container, int screen, int localCellX, int localCellY, int spanX, int spanY) {
+        return (((int) container & 0xFF) << 24)
+                | (screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
+    }
+
+    static int getCellCountX() {
+        return mCellCountX;
+    }
+
+    static int getCellCountY() {
+        return mCellCountY;
+    }
+
+    /**
+     * Updates the model orientation helper to take into account the current layout dimensions
+     * when performing local/canonical coordinate transformations.
+     */
+    static void updateWorkspaceLayoutCells(int shortAxisCellCount, int longAxisCellCount) {
+        mCellCountX = shortAxisCellCount;
+        mCellCountY = longAxisCellCount;
+    }
+
+    /**
+     * Removes the specified item from the database
+     * @param context
+     * @param item
+     */
+    static void deleteItemFromDatabase(Context context, final ItemInfo item) {
+        final ContentResolver cr = context.getContentResolver();
+        final Uri uriToDelete = LauncherSettings.Favorites.getContentUri(item.id, false);
+
+        Runnable r = new Runnable() {
+            public void run() {
+                String transaction = "DbDebug    Delete item (" + item.title + ") from db, id: "
+                        + item.id + " (" + item.container + ", " + item.screen + ", " + item.cellX +
+                        ", " + item.cellY + ")";
+                Launcher.sDumpLogs.add(transaction);
+                Log.d(TAG, transaction);
+
+                cr.delete(uriToDelete, null, null);
+
+                // Lock on mBgLock *after* the db operation
+                synchronized (sBgLock) {
+                    switch (item.itemType) {
+                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                            sBgFolders.remove(item.id);
+                            for (ItemInfo info: sBgItemsIdMap.values()) {
+                                if (info.container == item.id) {
+                                    // We are deleting a folder which still contains items that
+                                    // think they are contained by that folder.
+                                    String msg = "deleting a folder (" + item + ") which still " +
+                                            "contains items (" + info + ")";
+                                    Log.e(TAG, msg);
+                                    Launcher.dumpDebugLogsToConsole();
+                                }
+                            }
+                            sBgWorkspaceItems.remove(item);
+                            break;
+                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                            sBgWorkspaceItems.remove(item);
+                            break;
+                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                            sBgAppWidgets.remove((LauncherAppWidgetInfo) item);
+                            break;
+                    }
+                    sBgItemsIdMap.remove(item.id);
+                    sBgDbIconCache.remove(item);
+                }
+            }
+        };
+        runOnWorkerThread(r);
+    }
+
+    /**
+     * Remove the contents of the specified folder from the database
+     */
+    static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
+        final ContentResolver cr = context.getContentResolver();
+
+        Runnable r = new Runnable() {
+            public void run() {
+                cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
+                // Lock on mBgLock *after* the db operation
+                synchronized (sBgLock) {
+                    sBgItemsIdMap.remove(info.id);
+                    sBgFolders.remove(info.id);
+                    sBgDbIconCache.remove(info);
+                    sBgWorkspaceItems.remove(info);
+                }
+
+                cr.delete(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
+                        LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
+                // Lock on mBgLock *after* the db operation
+                synchronized (sBgLock) {
+                    for (ItemInfo childInfo : info.contents) {
+                        sBgItemsIdMap.remove(childInfo.id);
+                        sBgDbIconCache.remove(childInfo);
+                    }
+                }
+            }
+        };
+        runOnWorkerThread(r);
+    }
+
+    /**
+     * Set this as the current Launcher activity object for the loader.
+     */
+    public void initialize(Callbacks callbacks) {
+        synchronized (mLock) {
+            mCallbacks = new WeakReference<Callbacks>(callbacks);
+        }
+    }
+
+    /**
+     * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
+     * ACTION_PACKAGE_CHANGED.
+     */
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);
+
+        final String action = intent.getAction();
+
+        if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+                || Intent.ACTION_PACKAGE_REMOVED.equals(action)
+                || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+            final String packageName = intent.getData().getSchemeSpecificPart();
+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+            int op = PackageUpdatedTask.OP_NONE;
+
+            if (packageName == null || packageName.length() == 0) {
+                // they sent us a bad intent
+                return;
+            }
+
+            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+                op = PackageUpdatedTask.OP_UPDATE;
+            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                if (!replacing) {
+                    op = PackageUpdatedTask.OP_REMOVE;
+                }
+                // else, we are replacing the package, so a PACKAGE_ADDED will be sent
+                // later, we will update the package at this time
+            } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                if (!replacing) {
+                    op = PackageUpdatedTask.OP_ADD;
+                } else {
+                    op = PackageUpdatedTask.OP_UPDATE;
+                }
+            }
+
+            if (op != PackageUpdatedTask.OP_NONE) {
+                enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName }));
+            }
+
+        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+            // First, schedule to add these apps back in.
+            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
+            // Then, rebind everything.
+            startLoaderFromBackground();
+        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+            enqueuePackageUpdated(new PackageUpdatedTask(
+                        PackageUpdatedTask.OP_UNAVAILABLE, packages));
+        } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+            // If we have changed locale we need to clear out the labels in all apps/workspace.
+            forceReload();
+        } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+             // Check if configuration change was an mcc/mnc change which would affect app resources
+             // and we would need to clear out the labels in all apps/workspace. Same handling as
+             // above for ACTION_LOCALE_CHANGED
+             Configuration currentConfig = context.getResources().getConfiguration();
+             if (mPreviousConfigMcc != currentConfig.mcc) {
+                   Log.d(TAG, "Reload apps on config change. curr_mcc:"
+                       + currentConfig.mcc + " prevmcc:" + mPreviousConfigMcc);
+                   forceReload();
+             }
+             // Update previousConfig
+             mPreviousConfigMcc = currentConfig.mcc;
+        } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action) ||
+                   SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED.equals(action)) {
+            if (mCallbacks != null) {
+                Callbacks callbacks = mCallbacks.get();
+                if (callbacks != null) {
+                    callbacks.bindSearchablesChanged();
+                }
+            }
+        }
+    }
+
+    private void forceReload() {
+        resetLoadedState(true, true);
+
+        // Do this here because if the launcher activity is running it will be restarted.
+        // If it's not running startLoaderFromBackground will merely tell it that it needs
+        // to reload.
+        startLoaderFromBackground();
+    }
+
+    public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {
+        synchronized (mLock) {
+            // Stop any existing loaders first, so they don't set mAllAppsLoaded or
+            // mWorkspaceLoaded to true later
+            stopLoaderLocked();
+            if (resetAllAppsLoaded) mAllAppsLoaded = false;
+            if (resetWorkspaceLoaded) mWorkspaceLoaded = false;
+        }
+    }
+
+    /**
+     * When the launcher is in the background, it's possible for it to miss paired
+     * configuration changes.  So whenever we trigger the loader from the background
+     * tell the launcher that it needs to re-run the loader when it comes back instead
+     * of doing it now.
+     */
+    public void startLoaderFromBackground() {
+        boolean runLoader = false;
+        if (mCallbacks != null) {
+            Callbacks callbacks = mCallbacks.get();
+            if (callbacks != null) {
+                // Only actually run the loader if they're not paused.
+                if (!callbacks.setLoadOnResume()) {
+                    runLoader = true;
+                }
+            }
+        }
+        if (runLoader) {
+            startLoader(false, -1);
+        }
+    }
+
+    // If there is already a loader task running, tell it to stop.
+    // returns true if isLaunching() was true on the old task
+    private boolean stopLoaderLocked() {
+        boolean isLaunching = false;
+        LoaderTask oldTask = mLoaderTask;
+        if (oldTask != null) {
+            if (oldTask.isLaunching()) {
+                isLaunching = true;
+            }
+            oldTask.stopLocked();
+        }
+        return isLaunching;
+    }
+
+    public void startLoader(boolean isLaunching, int synchronousBindPage) {
+        synchronized (mLock) {
+            if (DEBUG_LOADERS) {
+                Log.d(TAG, "startLoader isLaunching=" + isLaunching);
+            }
+
+            // Clear any deferred bind-runnables from the synchronized load process
+            // We must do this before any loading/binding is scheduled below.
+            mDeferredBindRunnables.clear();
+
+            // Don't bother to start the thread if we know it's not going to do anything
+            if (mCallbacks != null && mCallbacks.get() != null) {
+                // If there is already one running, tell it to stop.
+                // also, don't downgrade isLaunching if we're already running
+                isLaunching = isLaunching || stopLoaderLocked();
+                mLoaderTask = new LoaderTask(mApp, isLaunching);
+                if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {
+                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
+                } else {
+                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
+                    sWorker.post(mLoaderTask);
+                }
+            }
+        }
+    }
+
+    void bindRemainingSynchronousPages() {
+        // Post the remaining side pages to be loaded
+        if (!mDeferredBindRunnables.isEmpty()) {
+            for (final Runnable r : mDeferredBindRunnables) {
+                mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);
+            }
+            mDeferredBindRunnables.clear();
+        }
+    }
+
+    public void stopLoader() {
+        synchronized (mLock) {
+            if (mLoaderTask != null) {
+                mLoaderTask.stopLocked();
+            }
+        }
+    }
+
+    public boolean isAllAppsLoaded() {
+        return mAllAppsLoaded;
+    }
+
+    boolean isLoadingWorkspace() {
+        synchronized (mLock) {
+            if (mLoaderTask != null) {
+                return mLoaderTask.isLoadingWorkspace();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Runnable for the thread that loads the contents of the launcher:
+     *   - workspace icons
+     *   - widgets
+     *   - all apps icons
+     */
+    private class LoaderTask implements Runnable {
+        private Context mContext;
+        private boolean mIsLaunching;
+        private boolean mIsLoadingAndBindingWorkspace;
+        private boolean mStopped;
+        private boolean mLoadAndBindStepFinished;
+
+        private HashMap<Object, CharSequence> mLabelCache;
+
+        LoaderTask(Context context, boolean isLaunching) {
+            mContext = context;
+            mIsLaunching = isLaunching;
+            mLabelCache = new HashMap<Object, CharSequence>();
+        }
+
+        boolean isLaunching() {
+            return mIsLaunching;
+        }
+
+        boolean isLoadingWorkspace() {
+            return mIsLoadingAndBindingWorkspace;
+        }
+
+        private void loadAndBindWorkspace() {
+            mIsLoadingAndBindingWorkspace = true;
+
+            // Load the workspace
+            if (DEBUG_LOADERS) {
+                Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
+            }
+
+            if (!mWorkspaceLoaded) {
+                loadWorkspace();
+                synchronized (LoaderTask.this) {
+                    if (mStopped) {
+                        return;
+                    }
+                    mWorkspaceLoaded = true;
+                }
+            }
+
+            // Bind the workspace
+            bindWorkspace(-1);
+        }
+
+        private void waitForIdle() {
+            // Wait until the either we're stopped or the other threads are done.
+            // This way we don't start loading all apps until the workspace has settled
+            // down.
+            synchronized (LoaderTask.this) {
+                final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+                mHandler.postIdle(new Runnable() {
+                        public void run() {
+                            synchronized (LoaderTask.this) {
+                                mLoadAndBindStepFinished = true;
+                                if (DEBUG_LOADERS) {
+                                    Log.d(TAG, "done with previous binding step");
+                                }
+                                LoaderTask.this.notify();
+                            }
+                        }
+                    });
+
+                while (!mStopped && !mLoadAndBindStepFinished) {
+                    try {
+                        this.wait();
+                    } catch (InterruptedException ex) {
+                        // Ignore
+                    }
+                }
+                if (DEBUG_LOADERS) {
+                    Log.d(TAG, "waited "
+                            + (SystemClock.uptimeMillis()-workspaceWaitTime)
+                            + "ms for previous step to finish binding");
+                }
+            }
+        }
+
+        void runBindSynchronousPage(int synchronousBindPage) {
+            if (synchronousBindPage < 0) {
+                // Ensure that we have a valid page index to load synchronously
+                throw new RuntimeException("Should not call runBindSynchronousPage() without " +
+                        "valid page index");
+            }
+            if (!mAllAppsLoaded || !mWorkspaceLoaded) {
+                // Ensure that we don't try and bind a specified page when the pages have not been
+                // loaded already (we should load everything asynchronously in that case)
+                throw new RuntimeException("Expecting AllApps and Workspace to be loaded");
+            }
+            synchronized (mLock) {
+                if (mIsLoaderTaskRunning) {
+                    // Ensure that we are never running the background loading at this point since
+                    // we also touch the background collections
+                    throw new RuntimeException("Error! Background loading is already running");
+                }
+            }
+
+            // The LauncherModel is static in the LauncherApplication and mHandler may have queued
+            // operations from the previous activity.  We need to ensure that all queued operations
+            // are executed before any synchronous binding work is done.
+            mHandler.flush();
+
+            // Divide the set of loaded items into those that we are binding synchronously, and
+            // everything else that is to be bound normally (asynchronously).
+            bindWorkspace(synchronousBindPage);
+            // continue posting the binding of AllApps as there are other issues that
+            //      arise from that.
+            onlyBindAllApps();
+        }
+
+        public void run() {
+            synchronized (mLock) {
+                mIsLoaderTaskRunning = true;
+            }
+            // Optimize for end-user experience: if the Launcher is up and running with the
+            // All Apps interface in the foreground, load All Apps first. Otherwise, load the
+            // workspace first (default).
+            final Callbacks cbk = mCallbacks.get();
+            final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
+
+            keep_running: {
+                // Elevate priority when Home launches for the first time to avoid
+                // starving at boot time. Staring at a blank home is not cool.
+                synchronized (mLock) {
+                    if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +
+                            (mIsLaunching ? "DEFAULT" : "BACKGROUND"));
+                    android.os.Process.setThreadPriority(mIsLaunching
+                            ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
+                }
+                if (loadWorkspaceFirst) {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
+                    loadAndBindWorkspace();
+                } else {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");
+                    loadAndBindAllApps();
+                }
+
+                if (mStopped) {
+                    break keep_running;
+                }
+
+                // wait until the UI thread has settled down.
+                synchronized (mLock) {
+                    if (mIsLaunching) {
+                        if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");
+                        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                    }
+                }
+                waitForIdle();
+
+                // second step
+                if (loadWorkspaceFirst) {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
+                    loadAndBindAllApps();
+                } else {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
+                    loadAndBindWorkspace();
+                }
+
+                // Restore the default thread priority after we are done loading items
+                synchronized (mLock) {
+                    android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+                }
+            }
+
+
+            // Update the saved icons if necessary
+            if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
+            synchronized (sBgLock) {
+                for (Object key : sBgDbIconCache.keySet()) {
+                    updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));
+                }
+                sBgDbIconCache.clear();
+            }
+
+            // Clear out this reference, otherwise we end up holding it until all of the
+            // callback runnables are done.
+            mContext = null;
+
+            synchronized (mLock) {
+                // If we are still the last one to be scheduled, remove ourselves.
+                if (mLoaderTask == this) {
+                    mLoaderTask = null;
+                }
+                mIsLoaderTaskRunning = false;
+            }
+        }
+
+        public void stopLocked() {
+            synchronized (LoaderTask.this) {
+                mStopped = true;
+                this.notify();
+            }
+        }
+
+        /**
+         * Gets the callbacks object.  If we've been stopped, or if the launcher object
+         * has somehow been garbage collected, return null instead.  Pass in the Callbacks
+         * object that was around when the deferred message was scheduled, and if there's
+         * a new Callbacks object around then also return null.  This will save us from
+         * calling onto it with data that will be ignored.
+         */
+        Callbacks tryGetCallbacks(Callbacks oldCallbacks) {
+            synchronized (mLock) {
+                if (mStopped) {
+                    return null;
+                }
+
+                if (mCallbacks == null) {
+                    return null;
+                }
+
+                final Callbacks callbacks = mCallbacks.get();
+                if (callbacks != oldCallbacks) {
+                    return null;
+                }
+                if (callbacks == null) {
+                    Log.w(TAG, "no mCallbacks");
+                    return null;
+                }
+
+                return callbacks;
+            }
+        }
+
+        // check & update map of what's occupied; used to discard overlapping/invalid items
+        private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
+            int containerIndex = item.screen;
+            if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                // Return early if we detect that an item is under the hotseat button
+                if (mCallbacks == null || mCallbacks.get().isAllAppsButtonRank(item.screen)) {
+                    return false;
+                }
+
+                // We use the last index to refer to the hotseat and the screen as the rank, so
+                // test and update the occupied state accordingly
+                if (occupied[Launcher.SCREEN_COUNT][item.screen][0] != null) {
+                    Log.e(TAG, "Error loading shortcut into hotseat " + item
+                        + " into position (" + item.screen + ":" + item.cellX + "," + item.cellY
+                        + ") occupied by " + occupied[Launcher.SCREEN_COUNT][item.screen][0]);
+                    return false;
+                } else {
+                    occupied[Launcher.SCREEN_COUNT][item.screen][0] = item;
+                    return true;
+                }
+            } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                // Skip further checking if it is not the hotseat or workspace container
+                return true;
+            }
+
+            // Check if any workspace icons overlap with each other
+            for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
+                for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
+                    if (occupied[containerIndex][x][y] != null) {
+                        Log.e(TAG, "Error loading shortcut " + item
+                            + " into cell (" + containerIndex + "-" + item.screen + ":"
+                            + x + "," + y
+                            + ") occupied by "
+                            + occupied[containerIndex][x][y]);
+                        return false;
+                    }
+                }
+            }
+            for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
+                for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
+                    occupied[containerIndex][x][y] = item;
+                }
+            }
+
+            return true;
+        }
+
+        private void loadWorkspace() {
+            final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+            final Context context = mContext;
+            final ContentResolver contentResolver = context.getContentResolver();
+            final PackageManager manager = context.getPackageManager();
+            final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
+            final boolean isSafeMode = manager.isSafeMode();
+
+            // Make sure the default workspace is loaded, if needed
+            mApp.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+
+            synchronized (sBgLock) {
+                sBgWorkspaceItems.clear();
+                sBgAppWidgets.clear();
+                sBgFolders.clear();
+                sBgItemsIdMap.clear();
+                sBgDbIconCache.clear();
+
+                final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
+
+                final Cursor c = contentResolver.query(
+                        LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
+
+                // +1 for the hotseat (it can be larger than the workspace)
+                // Load workspace in reverse order to ensure that latest items are loaded first (and
+                // before any earlier duplicates)
+                final ItemInfo occupied[][][] =
+                        new ItemInfo[Launcher.SCREEN_COUNT + 1][mCellCountX + 1][mCellCountY + 1];
+
+                try {
+                    final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+                    final int intentIndex = c.getColumnIndexOrThrow
+                            (LauncherSettings.Favorites.INTENT);
+                    final int titleIndex = c.getColumnIndexOrThrow
+                            (LauncherSettings.Favorites.TITLE);
+                    final int iconTypeIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.ICON_TYPE);
+                    final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+                    final int iconPackageIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.ICON_PACKAGE);
+                    final int iconResourceIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.ICON_RESOURCE);
+                    final int containerIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.CONTAINER);
+                    final int itemTypeIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.ITEM_TYPE);
+                    final int appWidgetIdIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.APPWIDGET_ID);
+                    final int screenIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.SCREEN);
+                    final int cellXIndex = c.getColumnIndexOrThrow
+                            (LauncherSettings.Favorites.CELLX);
+                    final int cellYIndex = c.getColumnIndexOrThrow
+                            (LauncherSettings.Favorites.CELLY);
+                    final int spanXIndex = c.getColumnIndexOrThrow
+                            (LauncherSettings.Favorites.SPANX);
+                    final int spanYIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.SPANY);
+
+                    ShortcutInfo info;
+                    String intentDescription;
+                    LauncherAppWidgetInfo appWidgetInfo;
+                    int container;
+                    long id;
+                    Intent intent;
+
+                    while (!mStopped && c.moveToNext()) {
+                        try {
+                            int itemType = c.getInt(itemTypeIndex);
+
+                            switch (itemType) {
+                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                                intentDescription = c.getString(intentIndex);
+                                try {
+                                    intent = Intent.parseUri(intentDescription, 0);
+                                } catch (URISyntaxException e) {
+                                    continue;
+                                }
+
+                                if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+                                    info = getShortcutInfo(manager, intent, context, c, iconIndex,
+                                            titleIndex, mLabelCache);
+                                } else {
+                                    info = getShortcutInfo(c, context, iconTypeIndex,
+                                            iconPackageIndex, iconResourceIndex, iconIndex,
+                                            titleIndex);
+
+                                    // App shortcuts that used to be automatically added to Launcher
+                                    // didn't always have the correct intent flags set, so do that
+                                    // here
+                                    if (intent.getAction() != null &&
+                                        intent.getCategories() != null &&
+                                        intent.getAction().equals(Intent.ACTION_MAIN) &&
+                                        intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
+                                        intent.addFlags(
+                                            Intent.FLAG_ACTIVITY_NEW_TASK |
+                                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                                    }
+                                }
+
+                                if (info != null) {
+                                    info.intent = intent;
+                                    info.id = c.getLong(idIndex);
+                                    container = c.getInt(containerIndex);
+                                    info.container = container;
+                                    info.screen = c.getInt(screenIndex);
+                                    info.cellX = c.getInt(cellXIndex);
+                                    info.cellY = c.getInt(cellYIndex);
+
+                                    // check & update map of what's occupied
+                                    if (!checkItemPlacement(occupied, info)) {
+                                        break;
+                                    }
+
+                                    switch (container) {
+                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+                                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
+                                        sBgWorkspaceItems.add(info);
+                                        break;
+                                    default:
+                                        // Item is in a user folder
+                                        FolderInfo folderInfo =
+                                                findOrMakeFolder(sBgFolders, container);
+                                        folderInfo.add(info);
+                                        break;
+                                    }
+                                    sBgItemsIdMap.put(info.id, info);
+
+                                    // now that we've loaded everthing re-save it with the
+                                    // icon in case it disappears somehow.
+                                    queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);
+                                } else {
+                                    // Failed to load the shortcut, probably because the
+                                    // activity manager couldn't resolve it (maybe the app
+                                    // was uninstalled), or the db row was somehow screwed up.
+                                    // Delete it.
+                                    id = c.getLong(idIndex);
+                                    Log.e(TAG, "Error loading shortcut " + id + ", removing it");
+                                    contentResolver.delete(LauncherSettings.Favorites.getContentUri(
+                                                id, false), null, null);
+                                }
+                                break;
+
+                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                                id = c.getLong(idIndex);
+                                FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);
+
+                                folderInfo.title = c.getString(titleIndex);
+                                folderInfo.id = id;
+                                container = c.getInt(containerIndex);
+                                folderInfo.container = container;
+                                folderInfo.screen = c.getInt(screenIndex);
+                                folderInfo.cellX = c.getInt(cellXIndex);
+                                folderInfo.cellY = c.getInt(cellYIndex);
+
+                                // check & update map of what's occupied
+                                if (!checkItemPlacement(occupied, folderInfo)) {
+                                    break;
+                                }
+                                switch (container) {
+                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+                                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
+                                        sBgWorkspaceItems.add(folderInfo);
+                                        break;
+                                }
+
+                                sBgItemsIdMap.put(folderInfo.id, folderInfo);
+                                sBgFolders.put(folderInfo.id, folderInfo);
+                                break;
+
+                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                                // Read all Launcher-specific widget details
+                                int appWidgetId = c.getInt(appWidgetIdIndex);
+                                id = c.getLong(idIndex);
+
+                                final AppWidgetProviderInfo provider =
+                                        widgets.getAppWidgetInfo(appWidgetId);
+
+                                if (!isSafeMode && (provider == null || provider.provider == null ||
+                                        provider.provider.getPackageName() == null)) {
+                                    String log = "Deleting widget that isn't installed anymore: id="
+                                        + id + " appWidgetId=" + appWidgetId;
+                                    Log.e(TAG, log);
+                                    Launcher.sDumpLogs.add(log);
+                                    itemsToRemove.add(id);
+                                } else {
+                                    appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
+                                            provider.provider);
+                                    appWidgetInfo.id = id;
+                                    appWidgetInfo.screen = c.getInt(screenIndex);
+                                    appWidgetInfo.cellX = c.getInt(cellXIndex);
+                                    appWidgetInfo.cellY = c.getInt(cellYIndex);
+                                    appWidgetInfo.spanX = c.getInt(spanXIndex);
+                                    appWidgetInfo.spanY = c.getInt(spanYIndex);
+                                    int[] minSpan = Launcher.getMinSpanForWidget(context, provider);
+                                    appWidgetInfo.minSpanX = minSpan[0];
+                                    appWidgetInfo.minSpanY = minSpan[1];
+
+                                    container = c.getInt(containerIndex);
+                                    if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                                        container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                                        Log.e(TAG, "Widget found where container != " +
+                                            "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
+                                        continue;
+                                    }
+                                    appWidgetInfo.container = c.getInt(containerIndex);
+
+                                    // check & update map of what's occupied
+                                    if (!checkItemPlacement(occupied, appWidgetInfo)) {
+                                        break;
+                                    }
+                                    sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
+                                    sBgAppWidgets.add(appWidgetInfo);
+                                }
+                                break;
+                            }
+                        } catch (Exception e) {
+                            Log.w(TAG, "Desktop items loading interrupted:", e);
+                        }
+                    }
+                } finally {
+                    c.close();
+                }
+
+                if (itemsToRemove.size() > 0) {
+                    ContentProviderClient client = contentResolver.acquireContentProviderClient(
+                                    LauncherSettings.Favorites.CONTENT_URI);
+                    // Remove dead items
+                    for (long id : itemsToRemove) {
+                        if (DEBUG_LOADERS) {
+                            Log.d(TAG, "Removed id = " + id);
+                        }
+                        // Don't notify content observers
+                        try {
+                            client.delete(LauncherSettings.Favorites.getContentUri(id, false),
+                                    null, null);
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Could not remove id = " + id);
+                        }
+                    }
+                }
+
+                if (DEBUG_LOADERS) {
+                    Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
+                    Log.d(TAG, "workspace layout: ");
+                    for (int y = 0; y < mCellCountY; y++) {
+                        String line = "";
+                        for (int s = 0; s < Launcher.SCREEN_COUNT; s++) {
+                            if (s > 0) {
+                                line += " | ";
+                            }
+                            for (int x = 0; x < mCellCountX; x++) {
+                                line += ((occupied[s][x][y] != null) ? "#" : ".");
+                            }
+                        }
+                        Log.d(TAG, "[ " + line + " ]");
+                    }
+                }
+            }
+        }
+
+        /** Filters the set of items who are directly or indirectly (via another container) on the
+         * specified screen. */
+        private void filterCurrentWorkspaceItems(int currentScreen,
+                ArrayList<ItemInfo> allWorkspaceItems,
+                ArrayList<ItemInfo> currentScreenItems,
+                ArrayList<ItemInfo> otherScreenItems) {
+            // Purge any null ItemInfos
+            Iterator<ItemInfo> iter = allWorkspaceItems.iterator();
+            while (iter.hasNext()) {
+                ItemInfo i = iter.next();
+                if (i == null) {
+                    iter.remove();
+                }
+            }
+
+            // If we aren't filtering on a screen, then the set of items to load is the full set of
+            // items given.
+            if (currentScreen < 0) {
+                currentScreenItems.addAll(allWorkspaceItems);
+            }
+
+            // Order the set of items by their containers first, this allows use to walk through the
+            // list sequentially, build up a list of containers that are in the specified screen,
+            // as well as all items in those containers.
+            Set<Long> itemsOnScreen = new HashSet<Long>();
+            Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {
+                @Override
+                public int compare(ItemInfo lhs, ItemInfo rhs) {
+                    return (int) (lhs.container - rhs.container);
+                }
+            });
+            for (ItemInfo info : allWorkspaceItems) {
+                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                    if (info.screen == currentScreen) {
+                        currentScreenItems.add(info);
+                        itemsOnScreen.add(info.id);
+                    } else {
+                        otherScreenItems.add(info);
+                    }
+                } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                    currentScreenItems.add(info);
+                    itemsOnScreen.add(info.id);
+                } else {
+                    if (itemsOnScreen.contains(info.container)) {
+                        currentScreenItems.add(info);
+                        itemsOnScreen.add(info.id);
+                    } else {
+                        otherScreenItems.add(info);
+                    }
+                }
+            }
+        }
+
+        /** Filters the set of widgets which are on the specified screen. */
+        private void filterCurrentAppWidgets(int currentScreen,
+                ArrayList<LauncherAppWidgetInfo> appWidgets,
+                ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,
+                ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {
+            // If we aren't filtering on a screen, then the set of items to load is the full set of
+            // widgets given.
+            if (currentScreen < 0) {
+                currentScreenWidgets.addAll(appWidgets);
+            }
+
+            for (LauncherAppWidgetInfo widget : appWidgets) {
+                if (widget == null) continue;
+                if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                        widget.screen == currentScreen) {
+                    currentScreenWidgets.add(widget);
+                } else {
+                    otherScreenWidgets.add(widget);
+                }
+            }
+        }
+
+        /** Filters the set of folders which are on the specified screen. */
+        private void filterCurrentFolders(int currentScreen,
+                HashMap<Long, ItemInfo> itemsIdMap,
+                HashMap<Long, FolderInfo> folders,
+                HashMap<Long, FolderInfo> currentScreenFolders,
+                HashMap<Long, FolderInfo> otherScreenFolders) {
+            // If we aren't filtering on a screen, then the set of items to load is the full set of
+            // widgets given.
+            if (currentScreen < 0) {
+                currentScreenFolders.putAll(folders);
+            }
+
+            for (long id : folders.keySet()) {
+                ItemInfo info = itemsIdMap.get(id);
+                FolderInfo folder = folders.get(id);
+                if (info == null || folder == null) continue;
+                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                        info.screen == currentScreen) {
+                    currentScreenFolders.put(id, folder);
+                } else {
+                    otherScreenFolders.put(id, folder);
+                }
+            }
+        }
+
+        /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to
+         * right) */
+        private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
+            Collections.sort(workspaceItems, new Comparator<ItemInfo>() {
+                @Override
+                public int compare(ItemInfo lhs, ItemInfo rhs) {
+                    int cellCountX = LauncherModel.getCellCountX();
+                    int cellCountY = LauncherModel.getCellCountY();
+                    int screenOffset = cellCountX * cellCountY;
+                    int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat
+                    long lr = (lhs.container * containerOffset + lhs.screen * screenOffset +
+                            lhs.cellY * cellCountX + lhs.cellX);
+                    long rr = (rhs.container * containerOffset + rhs.screen * screenOffset +
+                            rhs.cellY * cellCountX + rhs.cellX);
+                    return (int) (lr - rr);
+                }
+            });
+        }
+
+        private void bindWorkspaceItems(final Callbacks oldCallbacks,
+                final ArrayList<ItemInfo> workspaceItems,
+                final ArrayList<LauncherAppWidgetInfo> appWidgets,
+                final HashMap<Long, FolderInfo> folders,
+                ArrayList<Runnable> deferredBindRunnables) {
+
+            final boolean postOnMainThread = (deferredBindRunnables != null);
+
+            // Bind the workspace items
+            int N = workspaceItems.size();
+            for (int i = 0; i < N; i += ITEMS_CHUNK) {
+                final int start = i;
+                final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
+                final Runnable r = new Runnable() {
+                    @Override
+                    public void run() {
+                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                        if (callbacks != null) {
+                            callbacks.bindItems(workspaceItems, start, start+chunkSize);
+                        }
+                    }
+                };
+                if (postOnMainThread) {
+                    deferredBindRunnables.add(r);
+                } else {
+                    runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+                }
+            }
+
+            // Bind the folders
+            if (!folders.isEmpty()) {
+                final Runnable r = new Runnable() {
+                    public void run() {
+                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                        if (callbacks != null) {
+                            callbacks.bindFolders(folders);
+                        }
+                    }
+                };
+                if (postOnMainThread) {
+                    deferredBindRunnables.add(r);
+                } else {
+                    runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+                }
+            }
+
+            // Bind the widgets, one at a time
+            N = appWidgets.size();
+            for (int i = 0; i < N; i++) {
+                final LauncherAppWidgetInfo widget = appWidgets.get(i);
+                final Runnable r = new Runnable() {
+                    public void run() {
+                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                        if (callbacks != null) {
+                            callbacks.bindAppWidget(widget);
+                        }
+                    }
+                };
+                if (postOnMainThread) {
+                    deferredBindRunnables.add(r);
+                } else {
+                    runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+                }
+            }
+        }
+
+        /**
+         * Binds all loaded data to actual views on the main thread.
+         */
+        private void bindWorkspace(int synchronizeBindPage) {
+            final long t = SystemClock.uptimeMillis();
+            Runnable r;
+
+            // Don't use these two variables in any of the callback runnables.
+            // Otherwise we hold a reference to them.
+            final Callbacks oldCallbacks = mCallbacks.get();
+            if (oldCallbacks == null) {
+                // This launcher has exited and nobody bothered to tell us.  Just bail.
+                Log.w(TAG, "LoaderTask running with no launcher");
+                return;
+            }
+
+            final boolean isLoadingSynchronously = (synchronizeBindPage > -1);
+            final int currentScreen = isLoadingSynchronously ? synchronizeBindPage :
+                oldCallbacks.getCurrentWorkspaceScreen();
+
+            // Load all the items that are on the current page first (and in the process, unbind
+            // all the existing workspace items before we call startBinding() below.
+            unbindWorkspaceItemsOnMainThread();
+            ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();
+            ArrayList<LauncherAppWidgetInfo> appWidgets =
+                    new ArrayList<LauncherAppWidgetInfo>();
+            HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();
+            HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();
+            synchronized (sBgLock) {
+                workspaceItems.addAll(sBgWorkspaceItems);
+                appWidgets.addAll(sBgAppWidgets);
+                folders.putAll(sBgFolders);
+                itemsIdMap.putAll(sBgItemsIdMap);
+            }
+
+            ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();
+            ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();
+            ArrayList<LauncherAppWidgetInfo> currentAppWidgets =
+                    new ArrayList<LauncherAppWidgetInfo>();
+            ArrayList<LauncherAppWidgetInfo> otherAppWidgets =
+                    new ArrayList<LauncherAppWidgetInfo>();
+            HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();
+            HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();
+
+            // Separate the items that are on the current screen, and all the other remaining items
+            filterCurrentWorkspaceItems(currentScreen, workspaceItems, currentWorkspaceItems,
+                    otherWorkspaceItems);
+            filterCurrentAppWidgets(currentScreen, appWidgets, currentAppWidgets,
+                    otherAppWidgets);
+            filterCurrentFolders(currentScreen, itemsIdMap, folders, currentFolders,
+                    otherFolders);
+            sortWorkspaceItemsSpatially(currentWorkspaceItems);
+            sortWorkspaceItemsSpatially(otherWorkspaceItems);
+
+            // Tell the workspace that we're about to start binding items
+            r = new Runnable() {
+                public void run() {
+                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                    if (callbacks != null) {
+                        callbacks.startBinding();
+                    }
+                }
+            };
+            runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+
+            // Load items on the current page
+            bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
+                    currentFolders, null);
+            if (isLoadingSynchronously) {
+                r = new Runnable() {
+                    public void run() {
+                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                        if (callbacks != null) {
+                            callbacks.onPageBoundSynchronously(currentScreen);
+                        }
+                    }
+                };
+                runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+            }
+
+            // Load all the remaining pages (if we are loading synchronously, we want to defer this
+            // work until after the first render)
+            mDeferredBindRunnables.clear();
+            bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,
+                    (isLoadingSynchronously ? mDeferredBindRunnables : null));
+
+            // Tell the workspace that we're done binding items
+            r = new Runnable() {
+                public void run() {
+                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                    if (callbacks != null) {
+                        callbacks.finishBindingItems();
+                    }
+
+                    // If we're profiling, ensure this is the last thing in the queue.
+                    if (DEBUG_LOADERS) {
+                        Log.d(TAG, "bound workspace in "
+                            + (SystemClock.uptimeMillis()-t) + "ms");
+                    }
+
+                    mIsLoadingAndBindingWorkspace = false;
+                }
+            };
+            if (isLoadingSynchronously) {
+                mDeferredBindRunnables.add(r);
+            } else {
+                runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+            }
+        }
+
+        private void loadAndBindAllApps() {
+            if (DEBUG_LOADERS) {
+                Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
+            }
+            if (!mAllAppsLoaded) {
+                loadAllAppsByBatch();
+                synchronized (LoaderTask.this) {
+                    if (mStopped) {
+                        return;
+                    }
+                    mAllAppsLoaded = true;
+                }
+            } else {
+                onlyBindAllApps();
+            }
+        }
+
+        private void onlyBindAllApps() {
+            final Callbacks oldCallbacks = mCallbacks.get();
+            if (oldCallbacks == null) {
+                // This launcher has exited and nobody bothered to tell us.  Just bail.
+                Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");
+                return;
+            }
+
+            // shallow copy
+            @SuppressWarnings("unchecked")
+            final ArrayList<ApplicationInfo> list
+                    = (ArrayList<ApplicationInfo>) mBgAllAppsList.data.clone();
+            Runnable r = new Runnable() {
+                public void run() {
+                    final long t = SystemClock.uptimeMillis();
+                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                    if (callbacks != null) {
+                        callbacks.bindAllApplications(list);
+                    }
+                    if (DEBUG_LOADERS) {
+                        Log.d(TAG, "bound all " + list.size() + " apps from cache in "
+                                + (SystemClock.uptimeMillis()-t) + "ms");
+                    }
+                }
+            };
+            boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());
+            if (oldCallbacks.isAllAppsVisible() && isRunningOnMainThread) {
+                r.run();
+            } else {
+                mHandler.post(r);
+            }
+        }
+
+        private void loadAllAppsByBatch() {
+            final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+            // Don't use these two variables in any of the callback runnables.
+            // Otherwise we hold a reference to them.
+            final Callbacks oldCallbacks = mCallbacks.get();
+            if (oldCallbacks == null) {
+                // This launcher has exited and nobody bothered to tell us.  Just bail.
+                Log.w(TAG, "LoaderTask running with no launcher (loadAllAppsByBatch)");
+                return;
+            }
+
+            final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+            mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+            final PackageManager packageManager = mContext.getPackageManager();
+            List<ResolveInfo> apps = null;
+
+            int N = Integer.MAX_VALUE;
+
+            int startIndex;
+            int i=0;
+            int batchSize = -1;
+            while (i < N && !mStopped) {
+                if (i == 0) {
+                    mBgAllAppsList.clear();
+                    final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+                    apps = packageManager.queryIntentActivities(mainIntent, 0);
+                    if (DEBUG_LOADERS) {
+                        Log.d(TAG, "queryIntentActivities took "
+                                + (SystemClock.uptimeMillis()-qiaTime) + "ms");
+                    }
+                    if (apps == null) {
+                        return;
+                    }
+                    N = apps.size();
+                    if (DEBUG_LOADERS) {
+                        Log.d(TAG, "queryIntentActivities got " + N + " apps");
+                    }
+                    if (N == 0) {
+                    	//no apps
+                        return;
+                    }
+                    if (mBatchSize == 0) {
+                        batchSize = N;
+                    } else {
+                        batchSize = mBatchSize;
+                    }
+
+                    final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+                    Collections.sort(apps,
+                            new LauncherModel.ShortcutNameComparator(packageManager, mLabelCache));
+                    if (DEBUG_LOADERS) {
+                        Log.d(TAG, "sort took "
+                                + (SystemClock.uptimeMillis()-sortTime) + "ms");
+                    }
+                }
+
+                final long t2 = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+                startIndex = i;
+                for (int j=0; i<N && j<batchSize; j++) {
+                    // This builds the icon bitmaps.
+                    mBgAllAppsList.add(new ApplicationInfo(packageManager, apps.get(i),
+                            mIconCache, mLabelCache));
+                    i++;
+                }
+
+                final boolean first = i <= batchSize;
+                final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                final ArrayList<ApplicationInfo> added = mBgAllAppsList.added;
+                mBgAllAppsList.added = new ArrayList<ApplicationInfo>();
+
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        final long t = SystemClock.uptimeMillis();
+                        if (callbacks != null) {
+                            if (first) {
+                                callbacks.bindAllApplications(added);
+                            } else {
+                                callbacks.bindAppsAdded(added);
+                            }
+                            if (DEBUG_LOADERS) {
+                                Log.d(TAG, "bound " + added.size() + " apps in "
+                                    + (SystemClock.uptimeMillis() - t) + "ms");
+                            }
+                        } else {
+                            Log.i(TAG, "not binding apps: no Launcher activity");
+                        }
+                    }
+                });
+
+                if (DEBUG_LOADERS) {
+                    Log.d(TAG, "batch of " + (i-startIndex) + " icons processed in "
+                            + (SystemClock.uptimeMillis()-t2) + "ms");
+                }
+
+                if (mAllAppsLoadDelay > 0 && i < N) {
+                    try {
+                        if (DEBUG_LOADERS) {
+                            Log.d(TAG, "sleeping for " + mAllAppsLoadDelay + "ms");
+                        }
+                        Thread.sleep(mAllAppsLoadDelay);
+                    } catch (InterruptedException exc) { }
+                }
+            }
+
+            if (DEBUG_LOADERS) {
+                Log.d(TAG, "cached all " + N + " apps in "
+                        + (SystemClock.uptimeMillis()-t) + "ms"
+                        + (mAllAppsLoadDelay > 0 ? " (including delay)" : ""));
+            }
+            
+            AppDiscoverer.getInstance().loadAllApps(mBgAllAppsList.data);
+        }
+
+        public void dumpState() {
+            synchronized (sBgLock) {
+                Log.d(TAG, "mLoaderTask.mContext=" + mContext);
+                Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
+                Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
+                Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
+                Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());
+            }
+        }
+    }
+
+    void enqueuePackageUpdated(PackageUpdatedTask task) {
+        sWorker.post(task);
+    }
+
+    private class PackageUpdatedTask implements Runnable {
+        int mOp;
+        String[] mPackages;
+
+        public static final int OP_NONE = 0;
+        public static final int OP_ADD = 1;
+        public static final int OP_UPDATE = 2;
+        public static final int OP_REMOVE = 3; // uninstalled
+        public static final int OP_UNAVAILABLE = 4; // external media unmounted
+
+
+        public PackageUpdatedTask(int op, String[] packages) {
+            mOp = op;
+            mPackages = packages;
+        }
+
+        public void run() {
+            final Context context = mApp;
+
+            final String[] packages = mPackages;
+            final int N = packages.length;
+            switch (mOp) {
+                case OP_ADD:
+                    for (int i=0; i<N; i++) {
+                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
+                        mBgAllAppsList.addPackage(context, packages[i]);
+                    }
+                    break;
+                case OP_UPDATE:
+                    for (int i=0; i<N; i++) {
+                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
+                        mBgAllAppsList.updatePackage(context, packages[i]);
+                    }
+                    break;
+                case OP_REMOVE:
+                case OP_UNAVAILABLE:
+                    for (int i=0; i<N; i++) {
+                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
+                        mBgAllAppsList.removePackage(packages[i]);
+                    }
+                    break;
+            }
+
+            ArrayList<ApplicationInfo> added = null;
+            ArrayList<ApplicationInfo> modified = null;
+
+            if (mBgAllAppsList.added.size() > 0) {
+                added = new ArrayList<ApplicationInfo>(mBgAllAppsList.added);
+                mBgAllAppsList.added.clear();
+            }
+            if (mBgAllAppsList.modified.size() > 0) {
+                modified = new ArrayList<ApplicationInfo>(mBgAllAppsList.modified);
+                mBgAllAppsList.modified.clear();
+            }
+            // We may be removing packages that have no associated launcher application, so we
+            // pass through the removed package names directly.
+            // NOTE: We flush the icon cache aggressively in removePackage() above.
+            final ArrayList<String> removedPackageNames = new ArrayList<String>();
+            if (mBgAllAppsList.removed.size() > 0) {
+                mBgAllAppsList.removed.clear();
+
+                for (int i = 0; i < N; ++i) {
+                    removedPackageNames.add(packages[i]);
+                }
+            }
+
+            final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+            if (callbacks == null) {
+                Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");
+                return;
+            }
+
+            if (added != null) {
+                final ArrayList<ApplicationInfo> addedFinal = added;
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                        if (callbacks == cb && cb != null) {
+                            callbacks.bindAppsAdded(addedFinal);
+                        }
+                    }
+                });
+            }
+            if (modified != null) {
+                final ArrayList<ApplicationInfo> modifiedFinal = modified;
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                        if (callbacks == cb && cb != null) {
+                            callbacks.bindAppsUpdated(modifiedFinal);
+                        }
+                    }
+                });
+            }
+            if (!removedPackageNames.isEmpty()) {
+                final boolean permanent = mOp != OP_UNAVAILABLE;
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                        if (callbacks == cb && cb != null) {
+                            callbacks.bindAppsRemoved(removedPackageNames, permanent);
+                        }
+                    }
+                });
+            }
+
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                    if (callbacks == cb && cb != null) {
+                        callbacks.bindPackagesUpdated();
+                    }
+                }
+            });
+            
+            // update the new data
+            AppDiscoverer.getInstance().loadAllApps(mBgAllAppsList.data);
+        }
+    }
+
+    /**
+     * This is called from the code that adds shortcuts from the intent receiver.  This
+     * doesn't have a Cursor, but
+     */
+    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {
+        return getShortcutInfo(manager, intent, context, null, -1, -1, null);
+    }
+
+    /**
+     * Make an ShortcutInfo object for a shortcut that is an application.
+     *
+     * If c is not null, then it will be used to fill in missing data like the title and icon.
+     */
+    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,
+            Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {
+        Bitmap icon = null;
+        final ShortcutInfo info = new ShortcutInfo();
+
+        ComponentName componentName = intent.getComponent();
+        if (componentName == null) {
+            return null;
+        }
+
+        try {
+            PackageInfo pi = manager.getPackageInfo(componentName.getPackageName(), 0);
+            if (!pi.applicationInfo.enabled) {
+                // If we return null here, the corresponding item will be removed from the launcher
+                // db and will not appear in the workspace.
+                return null;
+            }
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, "getPackInfo failed for package " + componentName.getPackageName());
+        }
+
+        // the resource -- This may implicitly give us back the fallback icon,
+        // but don't worry about that.  All we're doing with usingFallbackIcon is
+        // to avoid saving lots of copies of that in the database, and most apps
+        // have icons anyway.
+
+        // Attempt to use queryIntentActivities to get the ResolveInfo (with IntentFilter info) and
+        // if that fails, or is ambiguious, fallback to the standard way of getting the resolve info
+        // via resolveActivity().
+        ResolveInfo resolveInfo = null;
+        ComponentName oldComponent = intent.getComponent();
+        Intent newIntent = new Intent(intent.getAction(), null);
+        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        newIntent.setPackage(oldComponent.getPackageName());
+        List<ResolveInfo> infos = manager.queryIntentActivities(newIntent, 0);
+        for (ResolveInfo i : infos) {
+            ComponentName cn = new ComponentName(i.activityInfo.packageName,
+                    i.activityInfo.name);
+            if (cn.equals(oldComponent)) {
+                resolveInfo = i;
+            }
+        }
+        if (resolveInfo == null) {
+            resolveInfo = manager.resolveActivity(intent, 0);
+        }
+        if (resolveInfo != null) {
+            icon = mIconCache.getIcon(componentName, resolveInfo, labelCache);
+        }
+        // the db
+        if (icon == null) {
+            if (c != null) {
+                icon = getIconFromCursor(c, iconIndex, context);
+            }
+        }
+        // the fallback icon
+        if (icon == null) {
+            icon = getFallbackIcon();
+            info.usingFallbackIcon = true;
+        }
+        info.setIcon(icon);
+
+        // from the resource
+        if (resolveInfo != null) {
+            ComponentName key = LauncherModel.getComponentNameFromResolveInfo(resolveInfo);
+            if (labelCache != null && labelCache.containsKey(key)) {
+                info.title = labelCache.get(key);
+            } else {
+                info.title = resolveInfo.activityInfo.loadLabel(manager);
+                if (labelCache != null) {
+                    labelCache.put(key, info.title);
+                }
+            }
+        }
+        // from the db
+        if (info.title == null) {
+            if (c != null) {
+                info.title =  c.getString(titleIndex);
+            }
+        }
+        // fall back to the class name of the activity
+        if (info.title == null) {
+            info.title = componentName.getClassName();
+        }
+        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+        return info;
+    }
+
+    /**
+     * Returns the set of workspace ShortcutInfos with the specified intent.
+     */
+    static ArrayList<ItemInfo> getWorkspaceShortcutItemInfosWithIntent(Intent intent) {
+        ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
+        synchronized (sBgLock) {
+            for (ItemInfo info : sBgWorkspaceItems) {
+                if (info instanceof ShortcutInfo) {
+                    ShortcutInfo shortcut = (ShortcutInfo) info;
+                    if (shortcut.intent.toUri(0).equals(intent.toUri(0))) {
+                        items.add(shortcut);
+                    }
+                }
+            }
+        }
+        return items;
+    }
+
+    /**
+     * Make an ShortcutInfo object for a shortcut that isn't an application.
+     */
+    private ShortcutInfo getShortcutInfo(Cursor c, Context context,
+            int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,
+            int titleIndex) {
+
+        Bitmap icon = null;
+        final ShortcutInfo info = new ShortcutInfo();
+        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+
+        info.title = c.getString(titleIndex);
+
+        int iconType = c.getInt(iconTypeIndex);
+        switch (iconType) {
+        case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
+            String packageName = c.getString(iconPackageIndex);
+            String resourceName = c.getString(iconResourceIndex);
+            PackageManager packageManager = context.getPackageManager();
+            info.customIcon = false;
+            // the resource
+            try {
+                Resources resources = packageManager.getResourcesForApplication(packageName);
+                if (resources != null) {
+                    final int id = resources.getIdentifier(resourceName, null, null);
+                    icon = Utilities.createIconBitmap(
+                            mIconCache.getFullResIcon(resources, id), context);
+                }
+            } catch (Exception e) {
+                // drop this.  we have other places to look for icons
+            }
+            // the db
+            if (icon == null) {
+                icon = getIconFromCursor(c, iconIndex, context);
+            }
+            // the fallback icon
+            if (icon == null) {
+                icon = getFallbackIcon();
+                info.usingFallbackIcon = true;
+            }
+            break;
+        case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
+            icon = getIconFromCursor(c, iconIndex, context);
+            if (icon == null) {
+                icon = getFallbackIcon();
+                info.customIcon = false;
+                info.usingFallbackIcon = true;
+            } else {
+                info.customIcon = true;
+            }
+            break;
+        default:
+            icon = getFallbackIcon();
+            info.usingFallbackIcon = true;
+            info.customIcon = false;
+            break;
+        }
+        info.setIcon(icon);
+        return info;
+    }
+
+    Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {
+        @SuppressWarnings("all") // suppress dead code warning
+        final boolean debug = false;
+        if (debug) {
+            Log.d(TAG, "getIconFromCursor app="
+                    + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));
+        }
+        byte[] data = c.getBlob(iconIndex);
+        try {
+            return Utilities.createIconBitmap(
+                    BitmapFactory.decodeByteArray(data, 0, data.length), context);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,
+            int cellX, int cellY, boolean notify) {
+        final ShortcutInfo info = infoFromShortcutIntent(context, data, null);
+        if (info == null) {
+            return null;
+        }
+        addItemToDatabase(context, info, container, screen, cellX, cellY, notify);
+
+        return info;
+    }
+
+    /**
+     * Attempts to find an AppWidgetProviderInfo that matches the given component.
+     */
+    AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,
+            ComponentName component) {
+        List<AppWidgetProviderInfo> widgets =
+            AppWidgetManager.getInstance(context).getInstalledProviders();
+        for (AppWidgetProviderInfo info : widgets) {
+            if (info.provider.equals(component)) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a list of all the widgets that can handle configuration with a particular mimeType.
+     */
+    List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {
+        final PackageManager packageManager = context.getPackageManager();
+        final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =
+            new ArrayList<WidgetMimeTypeHandlerData>();
+
+        final Intent supportsIntent =
+            new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);
+        supportsIntent.setType(mimeType);
+
+        // Create a set of widget configuration components that we can test against
+        final List<AppWidgetProviderInfo> widgets =
+            AppWidgetManager.getInstance(context).getInstalledProviders();
+        final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =
+            new HashMap<ComponentName, AppWidgetProviderInfo>();
+        for (AppWidgetProviderInfo info : widgets) {
+            configurationComponentToWidget.put(info.configure, info);
+        }
+
+        // Run through each of the intents that can handle this type of clip data, and cross
+        // reference them with the components that are actual configuration components
+        final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,
+                PackageManager.MATCH_DEFAULT_ONLY);
+        for (ResolveInfo info : activities) {
+            final ActivityInfo activityInfo = info.activityInfo;
+            final ComponentName infoComponent = new ComponentName(activityInfo.packageName,
+                    activityInfo.name);
+            if (configurationComponentToWidget.containsKey(infoComponent)) {
+                supportedConfigurationActivities.add(
+                        new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,
+                                configurationComponentToWidget.get(infoComponent)));
+            }
+        }
+        return supportedConfigurationActivities;
+    }
+
+    ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {
+        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+        Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
+
+        if (intent == null) {
+            // If the intent is null, we can't construct a valid ShortcutInfo, so we return null
+            Log.e(TAG, "Can't construct ShorcutInfo with null intent");
+            return null;
+        }
+
+        Bitmap icon = null;
+        boolean customIcon = false;
+        ShortcutIconResource iconResource = null;
+
+        if (bitmap != null && bitmap instanceof Bitmap) {
+            icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
+            customIcon = true;
+        } else {
+            Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
+            if (extra != null && extra instanceof ShortcutIconResource) {
+                try {
+                    iconResource = (ShortcutIconResource) extra;
+                    final PackageManager packageManager = context.getPackageManager();
+                    Resources resources = packageManager.getResourcesForApplication(
+                            iconResource.packageName);
+                    final int id = resources.getIdentifier(iconResource.resourceName, null, null);
+                    icon = Utilities.createIconBitmap(
+                            mIconCache.getFullResIcon(resources, id), context);
+                } catch (Exception e) {
+                    Log.w(TAG, "Could not load shortcut icon: " + extra);
+                }
+            }
+        }
+
+        final ShortcutInfo info = new ShortcutInfo();
+
+        if (icon == null) {
+            if (fallbackIcon != null) {
+                icon = fallbackIcon;
+            } else {
+                icon = getFallbackIcon();
+                info.usingFallbackIcon = true;
+            }
+        }
+        info.setIcon(icon);
+
+        info.title = name;
+        info.intent = intent;
+        info.customIcon = customIcon;
+        info.iconResource = iconResource;
+
+        return info;
+    }
+
+    boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,
+            int iconIndex) {
+        // If apps can't be on SD, don't even bother.
+        if (!mAppsCanBeOnExternalStorage) {
+            return false;
+        }
+        // If this icon doesn't have a custom icon, check to see
+        // what's stored in the DB, and if it doesn't match what
+        // we're going to show, store what we are going to show back
+        // into the DB.  We do this so when we're loading, if the
+        // package manager can't find an icon (for example because
+        // the app is on SD) then we can use that instead.
+        if (!info.customIcon && !info.usingFallbackIcon) {
+            cache.put(info, c.getBlob(iconIndex));
+            return true;
+        }
+        return false;
+    }
+    void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {
+        boolean needSave = false;
+        try {
+            if (data != null) {
+                Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);
+                Bitmap loaded = info.getIcon(mIconCache);
+                needSave = !saved.sameAs(loaded);
+            } else {
+                needSave = true;
+            }
+        } catch (Exception e) {
+            needSave = true;
+        }
+        if (needSave) {
+            Log.d(TAG, "going to save icon bitmap for info=" + info);
+            // This is slower than is ideal, but this only happens once
+            // or when the app is updated with a new icon.
+            updateItemInDatabase(context, info);
+        }
+    }
+
+    /**
+     * Return an existing FolderInfo object if we have encountered this ID previously,
+     * or make a new one.
+     */
+    private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {
+        // See if a placeholder was created for us already
+        FolderInfo folderInfo = folders.get(id);
+        if (folderInfo == null) {
+            // No placeholder -- create a new instance
+            folderInfo = new FolderInfo();
+            folders.put(id, folderInfo);
+        }
+        return folderInfo;
+    }
+
+    public static final Comparator<ApplicationInfo> getAppNameComparator() {
+        final Collator collator = Collator.getInstance();
+        return new Comparator<ApplicationInfo>() {
+            public final int compare(ApplicationInfo a, ApplicationInfo b) {
+                int result = collator.compare(a.title.toString(), b.title.toString());
+                if (result == 0) {
+                    result = a.componentName.compareTo(b.componentName);
+                }
+                return result;
+            }
+        };
+    }
+    public static final Comparator<ApplicationInfo> APP_INSTALL_TIME_COMPARATOR
+            = new Comparator<ApplicationInfo>() {
+        public final int compare(ApplicationInfo a, ApplicationInfo b) {
+            if (a.firstInstallTime < b.firstInstallTime) return 1;
+            if (a.firstInstallTime > b.firstInstallTime) return -1;
+            return 0;
+        }
+    };
+    public static final Comparator<AppWidgetProviderInfo> getWidgetNameComparator() {
+        final Collator collator = Collator.getInstance();
+        return new Comparator<AppWidgetProviderInfo>() {
+            public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
+                return collator.compare(a.label.toString(), b.label.toString());
+            }
+        };
+    }
+    static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {
+        if (info.activityInfo != null) {
+            return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+        } else {
+            return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
+        }
+    }
+    public static class ShortcutNameComparator implements Comparator<ResolveInfo> {
+        private Collator mCollator;
+        private PackageManager mPackageManager;
+        private HashMap<Object, CharSequence> mLabelCache;
+        ShortcutNameComparator(PackageManager pm) {
+            mPackageManager = pm;
+            mLabelCache = new HashMap<Object, CharSequence>();
+            mCollator = Collator.getInstance();
+        }
+        ShortcutNameComparator(PackageManager pm, HashMap<Object, CharSequence> labelCache) {
+            mPackageManager = pm;
+            mLabelCache = labelCache;
+            mCollator = Collator.getInstance();
+        }
+        public final int compare(ResolveInfo a, ResolveInfo b) {
+            CharSequence labelA, labelB;
+            ComponentName keyA = LauncherModel.getComponentNameFromResolveInfo(a);
+            ComponentName keyB = LauncherModel.getComponentNameFromResolveInfo(b);
+            if (mLabelCache.containsKey(keyA)) {
+                labelA = mLabelCache.get(keyA);
+            } else {
+                labelA = a.loadLabel(mPackageManager).toString();
+
+                mLabelCache.put(keyA, labelA);
+            }
+            if (mLabelCache.containsKey(keyB)) {
+                labelB = mLabelCache.get(keyB);
+            } else {
+                labelB = b.loadLabel(mPackageManager).toString();
+
+                mLabelCache.put(keyB, labelB);
+            }
+            return mCollator.compare(labelA, labelB);
+        }
+    };
+    public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
+        private Collator mCollator;
+        private PackageManager mPackageManager;
+        private HashMap<Object, String> mLabelCache;
+        WidgetAndShortcutNameComparator(PackageManager pm) {
+            mPackageManager = pm;
+            mLabelCache = new HashMap<Object, String>();
+            mCollator = Collator.getInstance();
+        }
+        public final int compare(Object a, Object b) {
+            String labelA, labelB;
+            if (mLabelCache.containsKey(a)) {
+                labelA = mLabelCache.get(a);
+            } else {
+                labelA = (a instanceof AppWidgetProviderInfo) ?
+                    ((AppWidgetProviderInfo) a).label :
+                    ((ResolveInfo) a).loadLabel(mPackageManager).toString();
+                mLabelCache.put(a, labelA);
+            }
+            if (mLabelCache.containsKey(b)) {
+                labelB = mLabelCache.get(b);
+            } else {
+                labelB = (b instanceof AppWidgetProviderInfo) ?
+                    ((AppWidgetProviderInfo) b).label :
+                    ((ResolveInfo) b).loadLabel(mPackageManager).toString();
+                mLabelCache.put(b, labelB);
+            }
+            return mCollator.compare(labelA, labelB);
+        }
+    };
+
+    public void dumpState() {
+        Log.d(TAG, "mCallbacks=" + mCallbacks);
+        ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);
+        ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);
+        ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);
+        ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);
+        if (mLoaderTask != null) {
+            mLoaderTask.dumpState();
+        } else {
+            Log.d(TAG, "mLoaderTask=null");
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherProvider.java b/FairphoneHome/src/org/fairphone/launcher/LauncherProvider.java
new file mode 100644
index 0000000..f5595d2
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherProvider.java
@@ -0,0 +1,1190 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.app.SearchManager;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.database.sqlite.SQLiteStatement;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.fairphone.launcher.R;
+
+import org.fairphone.launcher.LauncherSettings.Favorites;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class LauncherProvider extends ContentProvider {
+    private static final String TAG = "Launcher.LauncherProvider";
+    private static final boolean LOGD = false;
+
+    private static final String DATABASE_NAME = "launcher.db";
+
+    private static final int DATABASE_VERSION = 12;
+
+    static final String AUTHORITY = "org.fairphone.launcher.settings";
+
+    static final String TABLE_FAVORITES = "favorites";
+    static final String PARAMETER_NOTIFY = "notify";
+    static final String DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED =
+            "DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED";
+    static final String DEFAULT_WORKSPACE_RESOURCE_ID =
+            "DEFAULT_WORKSPACE_RESOURCE_ID";
+
+    private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
+            "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
+
+    /**
+     * {@link Uri} triggered at any registered {@link android.database.ContentObserver} when
+     * {@link AppWidgetHost#deleteHost()} is called during database creation.
+     * Use this to recall {@link AppWidgetHost#startListening()} if needed.
+     */
+    static final Uri CONTENT_APPWIDGET_RESET_URI =
+            Uri.parse("content://" + AUTHORITY + "/appWidgetReset");
+
+    private DatabaseHelper mOpenHelper;
+
+    @Override
+    public boolean onCreate() {
+        mOpenHelper = new DatabaseHelper(getContext());
+        ((LauncherApplication) getContext()).setLauncherProvider(this);
+        return true;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        SqlArguments args = new SqlArguments(uri, null, null);
+        if (TextUtils.isEmpty(args.where)) {
+            return "vnd.android.cursor.dir/" + args.table;
+        } else {
+            return "vnd.android.cursor.item/" + args.table;
+        }
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+
+        SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
+        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+        qb.setTables(args.table);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        Cursor result = qb.query(db, projection, args.where, args.args, null, null, sortOrder);
+        result.setNotificationUri(getContext().getContentResolver(), uri);
+
+        return result;
+    }
+
+    private static long dbInsertAndCheck(DatabaseHelper helper,
+            SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
+        if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+            throw new RuntimeException("Error: attempting to add item without specifying an id");
+        }
+        return db.insert(table, nullColumnHack, values);
+    }
+
+    private static void deleteId(SQLiteDatabase db, long id) {
+        Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
+        SqlArguments args = new SqlArguments(uri, null, null);
+        db.delete(args.table, args.where, args.args);
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues initialValues) {
+        SqlArguments args = new SqlArguments(uri);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        final long rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
+        if (rowId <= 0) return null;
+
+        uri = ContentUris.withAppendedId(uri, rowId);
+        sendNotify(uri);
+
+        return uri;
+    }
+
+    @Override
+    public int bulkInsert(Uri uri, ContentValues[] values) {
+        SqlArguments args = new SqlArguments(uri);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.beginTransaction();
+        try {
+            int numValues = values.length;
+            for (int i = 0; i < numValues; i++) {
+                if (dbInsertAndCheck(mOpenHelper, db, args.table, null, values[i]) < 0) {
+                    return 0;
+                }
+            }
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+        sendNotify(uri);
+        return values.length;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        int count = db.delete(args.table, args.where, args.args);
+        if (count > 0) sendNotify(uri);
+
+        return count;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        int count = db.update(args.table, values, args.where, args.args);
+        if (count > 0) sendNotify(uri);
+
+        return count;
+    }
+
+    private void sendNotify(Uri uri) {
+        String notify = uri.getQueryParameter(PARAMETER_NOTIFY);
+        if (notify == null || "true".equals(notify)) {
+            getContext().getContentResolver().notifyChange(uri, null);
+        }
+    }
+
+    public long generateNewId() {
+        return mOpenHelper.generateNewId();
+    }
+
+    /**
+     * @param workspaceResId that can be 0 to use default or non-zero for specific resource
+     */
+    synchronized public void loadDefaultFavoritesIfNecessary(int origWorkspaceResId) {
+        String spKey = LauncherApplication.getSharedPreferencesKey();
+        SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        if (sp.getBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, false)) {
+            int workspaceResId = origWorkspaceResId;
+
+            // Use default workspace resource if none provided
+            if (workspaceResId == 0) {
+                workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace);
+            }
+
+            // Populate favorites table with initial favorites
+            SharedPreferences.Editor editor = sp.edit();
+            editor.remove(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED);
+            if (origWorkspaceResId != 0) {
+                editor.putInt(DEFAULT_WORKSPACE_RESOURCE_ID, origWorkspaceResId);
+            }
+            mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), workspaceResId);
+            editor.commit();
+        }
+    }
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+        private static final String TAG_FAVORITES = "favorites";
+        private static final String TAG_FAVORITE = "favorite";
+        private static final String TAG_CLOCK = "clock";
+        private static final String TAG_SEARCH = "search";
+        private static final String TAG_APPWIDGET = "appwidget";
+        private static final String TAG_SHORTCUT = "shortcut";
+        private static final String TAG_FOLDER = "folder";
+        private static final String TAG_EXTRA = "extra";
+
+        private final Context mContext;
+        private final AppWidgetHost mAppWidgetHost;
+        private long mMaxId = -1;
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+            mContext = context;
+            mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
+
+            // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
+            // the DB here
+            if (mMaxId == -1) {
+                mMaxId = initializeMaxId(getWritableDatabase());
+            }
+        }
+
+        /**
+         * Send notification that we've deleted the {@link AppWidgetHost},
+         * probably as part of the initial database creation. The receiver may
+         * want to re-call {@link AppWidgetHost#startListening()} to ensure
+         * callbacks are correctly set.
+         */
+        private void sendAppWidgetResetNotify() {
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.notifyChange(CONTENT_APPWIDGET_RESET_URI, null);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            if (LOGD) Log.d(TAG, "creating new launcher database");
+
+            mMaxId = 1;
+
+            db.execSQL("CREATE TABLE favorites (" +
+                    "_id INTEGER PRIMARY KEY," +
+                    "title TEXT," +
+                    "intent TEXT," +
+                    "container INTEGER," +
+                    "screen INTEGER," +
+                    "cellX INTEGER," +
+                    "cellY INTEGER," +
+                    "spanX INTEGER," +
+                    "spanY INTEGER," +
+                    "itemType INTEGER," +
+                    "appWidgetId INTEGER NOT NULL DEFAULT -1," +
+                    "isShortcut INTEGER," +
+                    "iconType INTEGER," +
+                    "iconPackage TEXT," +
+                    "iconResource TEXT," +
+                    "icon BLOB," +
+                    "uri TEXT," +
+                    "displayMode INTEGER" +
+                    ");");
+
+            // Database was just created, so wipe any previous widgets
+            if (mAppWidgetHost != null) {
+                mAppWidgetHost.deleteHost();
+                sendAppWidgetResetNotify();
+            }
+
+            if (!convertDatabase(db)) {
+                // Set a shared pref so that we know we need to load the default workspace later
+                setFlagToLoadDefaultWorkspaceLater();
+            }
+        }
+
+        private void setFlagToLoadDefaultWorkspaceLater() {
+            String spKey = LauncherApplication.getSharedPreferencesKey();
+            SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+            SharedPreferences.Editor editor = sp.edit();
+            editor.putBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, true);
+            editor.commit();
+        }
+
+        private boolean convertDatabase(SQLiteDatabase db) {
+            if (LOGD) Log.d(TAG, "converting database from an older format, but not onUpgrade");
+            boolean converted = false;
+
+            final Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
+                    "/old_favorites?notify=true");
+            final ContentResolver resolver = mContext.getContentResolver();
+            Cursor cursor = null;
+
+            try {
+                cursor = resolver.query(uri, null, null, null, null);
+            } catch (Exception e) {
+                // Ignore
+            }
+
+            // We already have a favorites database in the old provider
+            if (cursor != null && cursor.getCount() > 0) {
+                try {
+                    converted = copyFromCursor(db, cursor) > 0;
+                } finally {
+                    cursor.close();
+                }
+
+                if (converted) {
+                    resolver.delete(uri, null, null);
+                }
+            }
+
+            if (converted) {
+                // Convert widgets from this import into widgets
+                if (LOGD) Log.d(TAG, "converted and now triggering widget upgrade");
+                convertWidgets(db);
+            }
+
+            return converted;
+        }
+
+        private int copyFromCursor(SQLiteDatabase db, Cursor c) {
+            final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+            final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+            final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+            final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+            final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+            final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+            final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+            final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+            final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+            final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+            final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+            final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+            final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
+            final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
+
+            ContentValues[] rows = new ContentValues[c.getCount()];
+            int i = 0;
+            while (c.moveToNext()) {
+                ContentValues values = new ContentValues(c.getColumnCount());
+                values.put(LauncherSettings.Favorites._ID, c.getLong(idIndex));
+                values.put(LauncherSettings.Favorites.INTENT, c.getString(intentIndex));
+                values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex));
+                values.put(LauncherSettings.Favorites.ICON_TYPE, c.getInt(iconTypeIndex));
+                values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex));
+                values.put(LauncherSettings.Favorites.ICON_PACKAGE, c.getString(iconPackageIndex));
+                values.put(LauncherSettings.Favorites.ICON_RESOURCE, c.getString(iconResourceIndex));
+                values.put(LauncherSettings.Favorites.CONTAINER, c.getInt(containerIndex));
+                values.put(LauncherSettings.Favorites.ITEM_TYPE, c.getInt(itemTypeIndex));
+                values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1);
+                values.put(LauncherSettings.Favorites.SCREEN, c.getInt(screenIndex));
+                values.put(LauncherSettings.Favorites.CELLX, c.getInt(cellXIndex));
+                values.put(LauncherSettings.Favorites.CELLY, c.getInt(cellYIndex));
+                values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
+                values.put(LauncherSettings.Favorites.DISPLAY_MODE, c.getInt(displayModeIndex));
+                rows[i++] = values;
+            }
+
+            db.beginTransaction();
+            int total = 0;
+            try {
+                int numValues = rows.length;
+                for (i = 0; i < numValues; i++) {
+                    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) {
+                        return 0;
+                    } else {
+                        total++;
+                    }
+                }
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+
+            return total;
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            if (LOGD) Log.d(TAG, "onUpgrade triggered");
+
+            int version = oldVersion;
+            if (version < 3) {
+                // upgrade 1,2 -> 3 added appWidgetId column
+                db.beginTransaction();
+                try {
+                    // Insert new column for holding appWidgetIds
+                    db.execSQL("ALTER TABLE favorites " +
+                        "ADD COLUMN appWidgetId INTEGER NOT NULL DEFAULT -1;");
+                    db.setTransactionSuccessful();
+                    version = 3;
+                } catch (SQLException ex) {
+                    // Old version remains, which means we wipe old data
+                    Log.e(TAG, ex.getMessage(), ex);
+                } finally {
+                    db.endTransaction();
+                }
+
+                // Convert existing widgets only if table upgrade was successful
+                if (version == 3) {
+                    convertWidgets(db);
+                }
+            }
+
+            if (version < 4) {
+                version = 4;
+            }
+
+            // Where's version 5?
+            // - Donut and sholes on 2.0 shipped with version 4 of launcher1.
+            // - Passion shipped on 2.1 with version 6 of launcher2
+            // - Sholes shipped on 2.1r1 (aka Mr. 3) with version 5 of launcher 1
+            //   but version 5 on there was the updateContactsShortcuts change
+            //   which was version 6 in launcher 2 (first shipped on passion 2.1r1).
+            // The updateContactsShortcuts change is idempotent, so running it twice
+            // is okay so we'll do that when upgrading the devices that shipped with it.
+            if (version < 6) {
+                // We went from 3 to 5 screens. Move everything 1 to the right
+                db.beginTransaction();
+                try {
+                    db.execSQL("UPDATE favorites SET screen=(screen + 1);");
+                    db.setTransactionSuccessful();
+                } catch (SQLException ex) {
+                    // Old version remains, which means we wipe old data
+                    Log.e(TAG, ex.getMessage(), ex);
+                } finally {
+                    db.endTransaction();
+                }
+
+               // We added the fast track.
+                if (updateContactsShortcuts(db)) {
+                    version = 6;
+                }
+            }
+
+            if (version < 7) {
+                // Version 7 gets rid of the special search widget.
+                convertWidgets(db);
+                version = 7;
+            }
+
+            if (version < 8) {
+                // Version 8 (froyo) has the icons all normalized.  This should
+                // already be the case in practice, but we now rely on it and don't
+                // resample the images each time.
+                normalizeIcons(db);
+                version = 8;
+            }
+
+            if (version < 9) {
+                // The max id is not yet set at this point (onUpgrade is triggered in the ctor
+                // before it gets a change to get set, so we need to read it here when we use it)
+                if (mMaxId == -1) {
+                    mMaxId = initializeMaxId(db);
+                }
+
+                // Add default hotseat icons
+                loadFavorites(db, R.xml.update_workspace);
+                version = 9;
+            }
+
+            // We bumped the version three time during JB, once to update the launch flags, once to
+            // update the override for the default launch animation and once to set the mimetype
+            // to improve startup performance
+            if (version < 12) {
+                // Contact shortcuts need a different set of flags to be launched now
+                // The updateContactsShortcuts change is idempotent, so we can keep using it like
+                // back in the Donut days
+                updateContactsShortcuts(db);
+                version = 12;
+            }
+
+            if (version != DATABASE_VERSION) {
+                Log.w(TAG, "Destroying all old data.");
+                db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
+                onCreate(db);
+            }
+        }
+
+        private boolean updateContactsShortcuts(SQLiteDatabase db) {
+            final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE,
+                    new int[] { Favorites.ITEM_TYPE_SHORTCUT });
+
+            Cursor c = null;
+            final String actionQuickContact = "com.android.contacts.action.QUICK_CONTACT";
+            db.beginTransaction();
+            try {
+                // Select and iterate through each matching widget
+                c = db.query(TABLE_FAVORITES,
+                        new String[] { Favorites._ID, Favorites.INTENT },
+                        selectWhere, null, null, null, null);
+                if (c == null) return false;
+
+                if (LOGD) Log.d(TAG, "found upgrade cursor count=" + c.getCount());
+
+                final int idIndex = c.getColumnIndex(Favorites._ID);
+                final int intentIndex = c.getColumnIndex(Favorites.INTENT);
+
+                while (c.moveToNext()) {
+                    long favoriteId = c.getLong(idIndex);
+                    final String intentUri = c.getString(intentIndex);
+                    if (intentUri != null) {
+                        try {
+                            final Intent intent = Intent.parseUri(intentUri, 0);
+                            android.util.Log.d("Home", intent.toString());
+                            final Uri uri = intent.getData();
+                            if (uri != null) {
+                                final String data = uri.toString();
+                                if ((Intent.ACTION_VIEW.equals(intent.getAction()) ||
+                                        actionQuickContact.equals(intent.getAction())) &&
+                                        (data.startsWith("content://contacts/people/") ||
+                                        data.startsWith("content://com.android.contacts/" +
+                                                "contacts/lookup/"))) {
+
+                                    final Intent newIntent = new Intent(actionQuickContact);
+                                    // When starting from the launcher, start in a new, cleared task
+                                    // CLEAR_WHEN_TASK_RESET cannot reset the root of a task, so we
+                                    // clear the whole thing preemptively here since
+                                    // QuickContactActivity will finish itself when launching other
+                                    // detail activities.
+                                    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                                            Intent.FLAG_ACTIVITY_CLEAR_TASK);
+                                    newIntent.putExtra(
+                                            Launcher.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true);
+                                    newIntent.setData(uri);
+                                    // Determine the type and also put that in the shortcut
+                                    // (that can speed up launch a bit)
+                                    newIntent.setDataAndType(uri, newIntent.resolveType(mContext));
+
+                                    final ContentValues values = new ContentValues();
+                                    values.put(LauncherSettings.Favorites.INTENT,
+                                            newIntent.toUri(0));
+
+                                    String updateWhere = Favorites._ID + "=" + favoriteId;
+                                    db.update(TABLE_FAVORITES, values, updateWhere, null);
+                                }
+                            }
+                        } catch (RuntimeException ex) {
+                            Log.e(TAG, "Problem upgrading shortcut", ex);
+                        } catch (URISyntaxException e) {
+                            Log.e(TAG, "Problem upgrading shortcut", e);
+                        }
+                    }
+                }
+
+                db.setTransactionSuccessful();
+            } catch (SQLException ex) {
+                Log.w(TAG, "Problem while upgrading contacts", ex);
+                return false;
+            } finally {
+                db.endTransaction();
+                if (c != null) {
+                    c.close();
+                }
+            }
+
+            return true;
+        }
+
+        private void normalizeIcons(SQLiteDatabase db) {
+            Log.d(TAG, "normalizing icons");
+
+            db.beginTransaction();
+            Cursor c = null;
+            SQLiteStatement update = null;
+            try {
+                boolean logged = false;
+                update = db.compileStatement("UPDATE favorites "
+                        + "SET icon=? WHERE _id=?");
+
+                c = db.rawQuery("SELECT _id, icon FROM favorites WHERE iconType=" +
+                        Favorites.ICON_TYPE_BITMAP, null);
+
+                final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
+                final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON);
+
+                while (c.moveToNext()) {
+                    long id = c.getLong(idIndex);
+                    byte[] data = c.getBlob(iconIndex);
+                    try {
+                        Bitmap bitmap = Utilities.resampleIconBitmap(
+                                BitmapFactory.decodeByteArray(data, 0, data.length),
+                                mContext);
+                        if (bitmap != null) {
+                            update.bindLong(1, id);
+                            data = ItemInfo.flattenBitmap(bitmap);
+                            if (data != null) {
+                                update.bindBlob(2, data);
+                                update.execute();
+                            }
+                            bitmap.recycle();
+                        }
+                    } catch (Exception e) {
+                        if (!logged) {
+                            Log.e(TAG, "Failed normalizing icon " + id, e);
+                        } else {
+                            Log.e(TAG, "Also failed normalizing icon " + id);
+                        }
+                        logged = true;
+                    }
+                }
+                db.setTransactionSuccessful();
+            } catch (SQLException ex) {
+                Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
+            } finally {
+                db.endTransaction();
+                if (update != null) {
+                    update.close();
+                }
+                if (c != null) {
+                    c.close();
+                }
+            }
+        }
+
+        // Generates a new ID to use for an object in your database. This method should be only
+        // called from the main UI thread. As an exception, we do call it when we call the
+        // constructor from the worker thread; however, this doesn't extend until after the
+        // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
+        // after that point
+        public long generateNewId() {
+            if (mMaxId < 0) {
+                throw new RuntimeException("Error: max id was not initialized");
+            }
+            mMaxId += 1;
+            return mMaxId;
+        }
+
+        private long initializeMaxId(SQLiteDatabase db) {
+            Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
+
+            // get the result
+            final int maxIdIndex = 0;
+            long id = -1;
+            if (c != null && c.moveToNext()) {
+                id = c.getLong(maxIdIndex);
+            }
+            if (c != null) {
+                c.close();
+            }
+
+            if (id == -1) {
+                throw new RuntimeException("Error: could not query max id");
+            }
+
+            return id;
+        }
+
+        /**
+         * Upgrade existing clock and photo frame widgets into their new widget
+         * equivalents.
+         */
+        private void convertWidgets(SQLiteDatabase db) {
+            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+            final int[] bindSources = new int[] {
+                    Favorites.ITEM_TYPE_WIDGET_CLOCK,
+                    Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME,
+                    Favorites.ITEM_TYPE_WIDGET_SEARCH,
+            };
+
+            final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE, bindSources);
+
+            Cursor c = null;
+
+            db.beginTransaction();
+            try {
+                // Select and iterate through each matching widget
+                c = db.query(TABLE_FAVORITES, new String[] { Favorites._ID, Favorites.ITEM_TYPE },
+                        selectWhere, null, null, null, null);
+
+                if (LOGD) Log.d(TAG, "found upgrade cursor count=" + c.getCount());
+
+                final ContentValues values = new ContentValues();
+                while (c != null && c.moveToNext()) {
+                    long favoriteId = c.getLong(0);
+                    int favoriteType = c.getInt(1);
+
+                    // Allocate and update database with new appWidgetId
+                    try {
+                        int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+
+                        if (LOGD) {
+                            Log.d(TAG, "allocated appWidgetId=" + appWidgetId
+                                    + " for favoriteId=" + favoriteId);
+                        }
+                        values.clear();
+                        values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
+                        values.put(Favorites.APPWIDGET_ID, appWidgetId);
+
+                        // Original widgets might not have valid spans when upgrading
+                        if (favoriteType == Favorites.ITEM_TYPE_WIDGET_SEARCH) {
+                            values.put(LauncherSettings.Favorites.SPANX, 4);
+                            values.put(LauncherSettings.Favorites.SPANY, 1);
+                        } else {
+                            values.put(LauncherSettings.Favorites.SPANX, 2);
+                            values.put(LauncherSettings.Favorites.SPANY, 2);
+                        }
+
+                        String updateWhere = Favorites._ID + "=" + favoriteId;
+                        db.update(TABLE_FAVORITES, values, updateWhere, null);
+
+                        if (favoriteType == Favorites.ITEM_TYPE_WIDGET_CLOCK) {
+                            appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
+                                    new ComponentName("com.android.alarmclock",
+                                    "com.android.alarmclock.AnalogAppWidgetProvider"));
+                        } else if (favoriteType == Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) {
+                            appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
+                                    new ComponentName("com.android.camera",
+                                    "com.android.camera.PhotoAppWidgetProvider"));
+                        } else if (favoriteType == Favorites.ITEM_TYPE_WIDGET_SEARCH) {
+                            appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
+                                    getSearchWidgetProvider());
+                        }
+                    } catch (RuntimeException ex) {
+                        Log.e(TAG, "Problem allocating appWidgetId", ex);
+                    }
+                }
+
+                db.setTransactionSuccessful();
+            } catch (SQLException ex) {
+                Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
+            } finally {
+                db.endTransaction();
+                if (c != null) {
+                    c.close();
+                }
+            }
+        }
+
+        private static final void beginDocument(XmlPullParser parser, String firstElementName)
+                throws XmlPullParserException, IOException {
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                ;
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException("No start tag found");
+            }
+
+            if (!parser.getName().equals(firstElementName)) {
+                throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
+                        ", expected " + firstElementName);
+            }
+        }
+
+        /**
+         * Loads the default set of favorite packages from an xml file.
+         *
+         * @param db The database to write the values into
+         * @param filterContainerId The specific container id of items to load
+         */
+        private int loadFavorites(SQLiteDatabase db, int workspaceResourceId) {
+            Intent intent = new Intent(Intent.ACTION_MAIN, null);
+            intent.addCategory(Intent.CATEGORY_LAUNCHER);
+            ContentValues values = new ContentValues();
+
+            PackageManager packageManager = mContext.getPackageManager();
+            int allAppsButtonRank =
+                    mContext.getResources().getInteger(R.integer.hotseat_all_apps_index);
+            int i = 0;
+            try {
+                XmlResourceParser parser = mContext.getResources().getXml(workspaceResourceId);
+                AttributeSet attrs = Xml.asAttributeSet(parser);
+                beginDocument(parser, TAG_FAVORITES);
+
+                final int depth = parser.getDepth();
+
+                int type;
+                while (((type = parser.next()) != XmlPullParser.END_TAG ||
+                        parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+
+                    if (type != XmlPullParser.START_TAG) {
+                        continue;
+                    }
+
+                    boolean added = false;
+                    final String name = parser.getName();
+
+                    TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite);
+
+                    long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+                    if (a.hasValue(R.styleable.Favorite_container)) {
+                        container = Long.valueOf(a.getString(R.styleable.Favorite_container));
+                    }
+
+                    String screen = a.getString(R.styleable.Favorite_screen);
+                    String x = a.getString(R.styleable.Favorite_x);
+                    String y = a.getString(R.styleable.Favorite_y);
+
+                    // If we are adding to the hotseat, the screen is used as the position in the
+                    // hotseat. This screen can't be at position 0 because AllApps is in the
+                    // zeroth position.
+                    if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
+                            && Integer.valueOf(screen) == allAppsButtonRank) {
+                        throw new RuntimeException("Invalid screen position for hotseat item");
+                    }
+
+                    values.clear();
+                    values.put(LauncherSettings.Favorites.CONTAINER, container);
+                    values.put(LauncherSettings.Favorites.SCREEN, screen);
+                    values.put(LauncherSettings.Favorites.CELLX, x);
+                    values.put(LauncherSettings.Favorites.CELLY, y);
+
+                    if (TAG_FAVORITE.equals(name)) {
+                        long id = addAppShortcut(db, values, a, packageManager, intent);
+                        added = id >= 0;
+                    } else if (TAG_SEARCH.equals(name)) {
+                        added = addSearchWidget(db, values);
+                    } else if (TAG_CLOCK.equals(name)) {
+                        added = addClockWidget(db, values);
+                    } else if (TAG_APPWIDGET.equals(name)) {
+                        added = addAppWidget(parser, attrs, type, db, values, a, packageManager);
+                    } else if (TAG_SHORTCUT.equals(name)) {
+                        long id = addUriShortcut(db, values, a);
+                        added = id >= 0;
+                    } else if (TAG_FOLDER.equals(name)) {
+                        String title;
+                        int titleResId =  a.getResourceId(R.styleable.Favorite_title, -1);
+                        if (titleResId != -1) {
+                            title = mContext.getResources().getString(titleResId);
+                        } else {
+                            title = mContext.getResources().getString(R.string.folder_name);
+                        }
+                        values.put(LauncherSettings.Favorites.TITLE, title);
+                        long folderId = addFolder(db, values);
+                        added = folderId >= 0;
+
+                        ArrayList<Long> folderItems = new ArrayList<Long>();
+
+                        int folderDepth = parser.getDepth();
+                        while ((type = parser.next()) != XmlPullParser.END_TAG ||
+                                parser.getDepth() > folderDepth) {
+                            if (type != XmlPullParser.START_TAG) {
+                                continue;
+                            }
+                            final String folder_item_name = parser.getName();
+
+                            TypedArray ar = mContext.obtainStyledAttributes(attrs,
+                                    R.styleable.Favorite);
+                            values.clear();
+                            values.put(LauncherSettings.Favorites.CONTAINER, folderId);
+
+                            if (TAG_FAVORITE.equals(folder_item_name) && folderId >= 0) {
+                                long id =
+                                    addAppShortcut(db, values, ar, packageManager, intent);
+                                if (id >= 0) {
+                                    folderItems.add(id);
+                                }
+                            } else if (TAG_SHORTCUT.equals(folder_item_name) && folderId >= 0) {
+                                long id = addUriShortcut(db, values, ar);
+                                if (id >= 0) {
+                                    folderItems.add(id);
+                                }
+                            } else {
+                                throw new RuntimeException("Folders can " +
+                                        "contain only shortcuts");
+                            }
+                            ar.recycle();
+                        }
+                        // We can only have folders with >= 2 items, so we need to remove the
+                        // folder and clean up if less than 2 items were included, or some
+                        // failed to add, and less than 2 were actually added
+                        if (folderItems.size() < 2 && folderId >= 0) {
+                            // We just delete the folder and any items that made it
+                            deleteId(db, folderId);
+                            if (folderItems.size() > 0) {
+                                deleteId(db, folderItems.get(0));
+                            }
+                            added = false;
+                        }
+                    }
+                    if (added) i++;
+                    a.recycle();
+                }
+            } catch (XmlPullParserException e) {
+                Log.w(TAG, "Got exception parsing favorites.", e);
+            } catch (IOException e) {
+                Log.w(TAG, "Got exception parsing favorites.", e);
+            } catch (RuntimeException e) {
+                Log.w(TAG, "Got exception parsing favorites.", e);
+            }
+
+            return i;
+        }
+
+        private long addAppShortcut(SQLiteDatabase db, ContentValues values, TypedArray a,
+                PackageManager packageManager, Intent intent) {
+            long id = -1;
+            ActivityInfo info;
+            String packageName = a.getString(R.styleable.Favorite_packageName);
+            String className = a.getString(R.styleable.Favorite_className);
+            try {
+                ComponentName cn;
+                try {
+                    cn = new ComponentName(packageName, className);
+                    info = packageManager.getActivityInfo(cn, 0);
+                } catch (PackageManager.NameNotFoundException nnfe) {
+                    String[] packages = packageManager.currentToCanonicalPackageNames(
+                        new String[] { packageName });
+                    cn = new ComponentName(packages[0], className);
+                    info = packageManager.getActivityInfo(cn, 0);
+                }
+                id = generateNewId();
+                intent.setComponent(cn);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                values.put(Favorites.INTENT, intent.toUri(0));
+                values.put(Favorites.TITLE, info.loadLabel(packageManager).toString());
+                values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
+                values.put(Favorites.SPANX, 1);
+                values.put(Favorites.SPANY, 1);
+                values.put(Favorites._ID, generateNewId());
+                if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
+                    return -1;
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Unable to add favorite: " + packageName +
+                        "/" + className, e);
+            }
+            return id;
+        }
+
+        private long addFolder(SQLiteDatabase db, ContentValues values) {
+            values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER);
+            values.put(Favorites.SPANX, 1);
+            values.put(Favorites.SPANY, 1);
+            long id = generateNewId();
+            values.put(Favorites._ID, id);
+            if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) <= 0) {
+                return -1;
+            } else {
+                return id;
+            }
+        }
+
+        private ComponentName getSearchWidgetProvider() {
+            SearchManager searchManager =
+                    (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+            ComponentName searchComponent = searchManager.getGlobalSearchActivity();
+            if (searchComponent == null) return null;
+            return getProviderInPackage(searchComponent.getPackageName());
+        }
+
+        /**
+         * Gets an appwidget provider from the given package. If the package contains more than
+         * one appwidget provider, an arbitrary one is returned.
+         */
+        private ComponentName getProviderInPackage(String packageName) {
+            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+            List<AppWidgetProviderInfo> providers = appWidgetManager.getInstalledProviders();
+            if (providers == null) return null;
+            final int providerCount = providers.size();
+            for (int i = 0; i < providerCount; i++) {
+                ComponentName provider = providers.get(i).provider;
+                if (provider != null && provider.getPackageName().equals(packageName)) {
+                    return provider;
+                }
+            }
+            return null;
+        }
+
+        private boolean addSearchWidget(SQLiteDatabase db, ContentValues values) {
+            ComponentName cn = getSearchWidgetProvider();
+            return addAppWidget(db, values, cn, 4, 1, null);
+        }
+
+        private boolean addClockWidget(SQLiteDatabase db, ContentValues values) {
+            ComponentName cn = new ComponentName("com.android.alarmclock",
+                    "com.android.alarmclock.AnalogAppWidgetProvider");
+            return addAppWidget(db, values, cn, 2, 2, null);
+        }
+
+        private boolean addAppWidget(XmlResourceParser parser, AttributeSet attrs, int type,
+                SQLiteDatabase db, ContentValues values, TypedArray a,
+                PackageManager packageManager) throws XmlPullParserException, IOException {
+
+            String packageName = a.getString(R.styleable.Favorite_packageName);
+            String className = a.getString(R.styleable.Favorite_className);
+
+            if (packageName == null || className == null) {
+                return false;
+            }
+
+            boolean hasPackage = true;
+            ComponentName cn = new ComponentName(packageName, className);
+            try {
+                packageManager.getReceiverInfo(cn, 0);
+            } catch (Exception e) {
+                String[] packages = packageManager.currentToCanonicalPackageNames(
+                        new String[] { packageName });
+                cn = new ComponentName(packages[0], className);
+                try {
+                    packageManager.getReceiverInfo(cn, 0);
+                } catch (Exception e1) {
+                    hasPackage = false;
+                }
+            }
+
+            if (hasPackage) {
+                int spanX = a.getInt(R.styleable.Favorite_spanX, 0);
+                int spanY = a.getInt(R.styleable.Favorite_spanY, 0);
+
+                // Read the extras
+                Bundle extras = new Bundle();
+                int widgetDepth = parser.getDepth();
+                while ((type = parser.next()) != XmlPullParser.END_TAG ||
+                        parser.getDepth() > widgetDepth) {
+                    if (type != XmlPullParser.START_TAG) {
+                        continue;
+                    }
+
+                    TypedArray ar = mContext.obtainStyledAttributes(attrs, R.styleable.Extra);
+                    if (TAG_EXTRA.equals(parser.getName())) {
+                        String key = ar.getString(R.styleable.Extra_key);
+                        String value = ar.getString(R.styleable.Extra_value);
+                        if (key != null && value != null) {
+                            extras.putString(key, value);
+                        } else {
+                            throw new RuntimeException("Widget extras must have a key and value");
+                        }
+                    } else {
+                        throw new RuntimeException("Widgets can contain only extras");
+                    }
+                    ar.recycle();
+                }
+
+                return addAppWidget(db, values, cn, spanX, spanY, extras);
+            }
+
+            return false;
+        }
+
+        private boolean addAppWidget(SQLiteDatabase db, ContentValues values, ComponentName cn,
+                int spanX, int spanY, Bundle extras) {
+            boolean allocatedAppWidgets = false;
+            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+
+            try {
+                int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+
+                values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
+                values.put(Favorites.SPANX, spanX);
+                values.put(Favorites.SPANY, spanY);
+                values.put(Favorites.APPWIDGET_ID, appWidgetId);
+                values.put(Favorites._ID, generateNewId());
+                dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
+
+                allocatedAppWidgets = true;
+
+                appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn);
+
+                // Send a broadcast to configure the widget
+                if (extras != null && !extras.isEmpty()) {
+                    Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE);
+                    intent.setComponent(cn);
+                    intent.putExtras(extras);
+                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+                    mContext.sendBroadcast(intent);
+                }
+            } catch (RuntimeException ex) {
+                Log.e(TAG, "Problem allocating appWidgetId", ex);
+            }
+
+            return allocatedAppWidgets;
+        }
+
+        private long addUriShortcut(SQLiteDatabase db, ContentValues values,
+                TypedArray a) {
+            Resources r = mContext.getResources();
+
+            final int iconResId = a.getResourceId(R.styleable.Favorite_icon, 0);
+            final int titleResId = a.getResourceId(R.styleable.Favorite_title, 0);
+
+            Intent intent;
+            String uri = null;
+            try {
+                uri = a.getString(R.styleable.Favorite_uri);
+                intent = Intent.parseUri(uri, 0);
+            } catch (URISyntaxException e) {
+                Log.w(TAG, "Shortcut has malformed uri: " + uri);
+                return -1; // Oh well
+            }
+
+            if (iconResId == 0 || titleResId == 0) {
+                Log.w(TAG, "Shortcut is missing title or icon resource ID");
+                return -1;
+            }
+
+            long id = generateNewId();
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            values.put(Favorites.INTENT, intent.toUri(0));
+            values.put(Favorites.TITLE, r.getString(titleResId));
+            values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_SHORTCUT);
+            values.put(Favorites.SPANX, 1);
+            values.put(Favorites.SPANY, 1);
+            values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
+            values.put(Favorites.ICON_PACKAGE, mContext.getPackageName());
+            values.put(Favorites.ICON_RESOURCE, r.getResourceName(iconResId));
+            values.put(Favorites._ID, id);
+
+            if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
+                return -1;
+            }
+            return id;
+        }
+    }
+
+    /**
+     * Build a query string that will match any row where the column matches
+     * anything in the values list.
+     */
+    static String buildOrWhereString(String column, int[] values) {
+        StringBuilder selectWhere = new StringBuilder();
+        for (int i = values.length - 1; i >= 0; i--) {
+            selectWhere.append(column).append("=").append(values[i]);
+            if (i > 0) {
+                selectWhere.append(" OR ");
+            }
+        }
+        return selectWhere.toString();
+    }
+
+    static class SqlArguments {
+        public final String table;
+        public final String where;
+        public final String[] args;
+
+        SqlArguments(Uri url, String where, String[] args) {
+            if (url.getPathSegments().size() == 1) {
+                this.table = url.getPathSegments().get(0);
+                this.where = where;
+                this.args = args;
+            } else if (url.getPathSegments().size() != 2) {
+                throw new IllegalArgumentException("Invalid URI: " + url);
+            } else if (!TextUtils.isEmpty(where)) {
+                throw new UnsupportedOperationException("WHERE clause not supported: " + url);
+            } else {
+                this.table = url.getPathSegments().get(0);
+                this.where = "_id=" + ContentUris.parseId(url);
+                this.args = null;
+            }
+        }
+
+        SqlArguments(Uri url) {
+            if (url.getPathSegments().size() == 1) {
+                table = url.getPathSegments().get(0);
+                where = null;
+                args = null;
+            } else {
+                throw new IllegalArgumentException("Invalid URI: " + url);
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherSettings.java b/FairphoneHome/src/org/fairphone/launcher/LauncherSettings.java
new file mode 100644
index 0000000..eea3d35
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherSettings.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Settings related utilities.
+ */
+class LauncherSettings {
+    static interface BaseLauncherColumns extends BaseColumns {
+        /**
+         * Descriptive name of the gesture that can be displayed to the user.
+         * <P>Type: TEXT</P>
+         */
+        static final String TITLE = "title";
+
+        /**
+         * The Intent URL of the gesture, describing what it points to. This
+         * value is given to {@link android.content.Intent#parseUri(String, int)} to create
+         * an Intent that can be launched.
+         * <P>Type: TEXT</P>
+         */
+        static final String INTENT = "intent";
+
+        /**
+         * The type of the gesture
+         *
+         * <P>Type: INTEGER</P>
+         */
+        static final String ITEM_TYPE = "itemType";
+
+        /**
+         * The gesture is an application
+         */
+        static final int ITEM_TYPE_APPLICATION = 0;
+
+        /**
+         * The gesture is an application created shortcut
+         */
+        static final int ITEM_TYPE_SHORTCUT = 1;
+
+        /**
+         * The icon type.
+         * <P>Type: INTEGER</P>
+         */
+        static final String ICON_TYPE = "iconType";
+
+        /**
+         * The icon is a resource identified by a package name and an integer id.
+         */
+        static final int ICON_TYPE_RESOURCE = 0;
+
+        /**
+         * The icon is a bitmap.
+         */
+        static final int ICON_TYPE_BITMAP = 1;
+
+        /**
+         * The icon package name, if icon type is ICON_TYPE_RESOURCE.
+         * <P>Type: TEXT</P>
+         */
+        static final String ICON_PACKAGE = "iconPackage";
+
+        /**
+         * The icon resource id, if icon type is ICON_TYPE_RESOURCE.
+         * <P>Type: TEXT</P>
+         */
+        static final String ICON_RESOURCE = "iconResource";
+
+        /**
+         * The custom icon bitmap, if icon type is ICON_TYPE_BITMAP.
+         * <P>Type: BLOB</P>
+         */
+        static final String ICON = "icon";
+    }
+
+    /**
+     * Favorites.
+     */
+    static final class Favorites implements BaseLauncherColumns {
+        /**
+         * The content:// style URL for this table
+         */
+        static final Uri CONTENT_URI = Uri.parse("content://" +
+                LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
+                "?" + LauncherProvider.PARAMETER_NOTIFY + "=true");
+
+        /**
+         * The content:// style URL for this table. When this Uri is used, no notification is
+         * sent if the content changes.
+         */
+        static final Uri CONTENT_URI_NO_NOTIFICATION = Uri.parse("content://" +
+                LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_FAVORITES +
+                "?" + LauncherProvider.PARAMETER_NOTIFY + "=false");
+
+        /**
+         * The content:// style URL for a given row, identified by its id.
+         *
+         * @param id The row id.
+         * @param notify True to send a notification is the content changes.
+         *
+         * @return The unique content URL for the specified row.
+         */
+        static Uri getContentUri(long id, boolean notify) {
+            return Uri.parse("content://" + LauncherProvider.AUTHORITY +
+                    "/" + LauncherProvider.TABLE_FAVORITES + "/" + id + "?" +
+                    LauncherProvider.PARAMETER_NOTIFY + "=" + notify);
+        }
+
+        /**
+         * The container holding the favorite
+         * <P>Type: INTEGER</P>
+         */
+        static final String CONTAINER = "container";
+
+        /**
+         * The icon is a resource identified by a package name and an integer id.
+         */
+        static final int CONTAINER_DESKTOP = -100;
+        static final int CONTAINER_HOTSEAT = -101;
+
+        /**
+         * The screen holding the favorite (if container is CONTAINER_DESKTOP)
+         * <P>Type: INTEGER</P>
+         */
+        static final String SCREEN = "screen";
+
+        /**
+         * The X coordinate of the cell holding the favorite
+         * (if container is CONTAINER_HOTSEAT or CONTAINER_HOTSEAT)
+         * <P>Type: INTEGER</P>
+         */
+        static final String CELLX = "cellX";
+
+        /**
+         * The Y coordinate of the cell holding the favorite
+         * (if container is CONTAINER_DESKTOP)
+         * <P>Type: INTEGER</P>
+         */
+        static final String CELLY = "cellY";
+
+        /**
+         * The X span of the cell holding the favorite
+         * <P>Type: INTEGER</P>
+         */
+        static final String SPANX = "spanX";
+
+        /**
+         * The Y span of the cell holding the favorite
+         * <P>Type: INTEGER</P>
+         */
+        static final String SPANY = "spanY";
+
+        /**
+         * The favorite is a user created folder
+         */
+        static final int ITEM_TYPE_FOLDER = 2;
+
+        /**
+        * The favorite is a live folder
+        *
+        * Note: live folders can no longer be added to Launcher, and any live folders which
+        * exist within the launcher database will be ignored when loading.  That said, these
+        * entries in the database may still exist, and are not automatically stripped.
+        */
+        static final int ITEM_TYPE_LIVE_FOLDER = 3;
+
+        /**
+         * The favorite is a widget
+         */
+        static final int ITEM_TYPE_APPWIDGET = 4;
+
+        /**
+         * The favorite is a clock
+         */
+        static final int ITEM_TYPE_WIDGET_CLOCK = 1000;
+
+        /**
+         * The favorite is a search widget
+         */
+        static final int ITEM_TYPE_WIDGET_SEARCH = 1001;
+
+        /**
+         * The favorite is a photo frame
+         */
+        static final int ITEM_TYPE_WIDGET_PHOTO_FRAME = 1002;
+
+        /**
+         * The appWidgetId of the widget
+         *
+         * <P>Type: INTEGER</P>
+         */
+        static final String APPWIDGET_ID = "appWidgetId";
+        
+        /**
+         * Indicates whether this favorite is an application-created shortcut or not.
+         * If the value is 0, the favorite is not an application-created shortcut, if the
+         * value is 1, it is an application-created shortcut.
+         * <P>Type: INTEGER</P>
+         */
+        @Deprecated
+        static final String IS_SHORTCUT = "isShortcut";
+
+        /**
+         * The URI associated with the favorite. It is used, for instance, by
+         * live folders to find the content provider.
+         * <P>Type: TEXT</P>
+         */
+        static final String URI = "uri";
+
+        /**
+         * The display mode if the item is a live folder.
+         * <P>Type: INTEGER</P>
+         *
+         * @see android.provider.LiveFolders#DISPLAY_MODE_GRID
+         * @see android.provider.LiveFolders#DISPLAY_MODE_LIST
+         */
+        static final String DISPLAY_MODE = "displayMode";
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/LauncherViewPropertyAnimator.java b/FairphoneHome/src/org/fairphone/launcher/LauncherViewPropertyAnimator.java
new file mode 100644
index 0000000..4e2124c
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/LauncherViewPropertyAnimator.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.TimeInterpolator;
+import android.view.ViewPropertyAnimator;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+
+public class LauncherViewPropertyAnimator extends Animator implements AnimatorListener {
+    enum Properties {
+            TRANSLATION_X,
+            TRANSLATION_Y,
+            SCALE_X,
+            SCALE_Y,
+            ROTATION_Y,
+            ALPHA,
+            START_DELAY,
+            DURATION,
+            INTERPOLATOR
+    }
+    EnumSet<Properties> mPropertiesToSet = EnumSet.noneOf(Properties.class);
+    ViewPropertyAnimator mViewPropertyAnimator;
+    View mTarget;
+
+    float mTranslationX;
+    float mTranslationY;
+    float mScaleX;
+    float mScaleY;
+    float mRotationY;
+    float mAlpha;
+    long mStartDelay;
+    long mDuration;
+    TimeInterpolator mInterpolator;
+    ArrayList<Animator.AnimatorListener> mListeners;
+    boolean mRunning = false;
+
+    public LauncherViewPropertyAnimator(View target) {
+        mTarget = target;
+        mListeners = new ArrayList<Animator.AnimatorListener>();
+    }
+
+    @Override
+    public void addListener(Animator.AnimatorListener listener) {
+        mListeners.add(listener);
+    }
+
+    @Override
+    public void cancel() {
+        if (mViewPropertyAnimator != null) {
+            mViewPropertyAnimator.cancel();
+        }
+    }
+
+    @Override
+    public Animator clone() {
+        throw new RuntimeException("Not implemented");
+    }
+
+    @Override
+    public void end() {
+        throw new RuntimeException("Not implemented");
+    }
+
+    @Override
+    public long getDuration() {
+        return mDuration;
+    }
+
+    @Override
+    public ArrayList<Animator.AnimatorListener> getListeners() {
+        return mListeners;
+    }
+
+    @Override
+    public long getStartDelay() {
+        return mStartDelay;
+    }
+
+    @Override
+    public void onAnimationCancel(Animator animation) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            Animator.AnimatorListener listener = mListeners.get(i);
+            listener.onAnimationCancel(this);
+        }
+        mRunning = false;
+    }
+
+    @Override
+    public void onAnimationEnd(Animator animation) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            Animator.AnimatorListener listener = mListeners.get(i);
+            listener.onAnimationEnd(this);
+        }
+        mRunning = false;
+    }
+
+    @Override
+    public void onAnimationRepeat(Animator animation) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            Animator.AnimatorListener listener = mListeners.get(i);
+            listener.onAnimationRepeat(this);
+        }
+    }
+
+    @Override
+    public void onAnimationStart(Animator animation) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            Animator.AnimatorListener listener = mListeners.get(i);
+            listener.onAnimationStart(this);
+        }
+        mRunning = true;
+    }
+
+    @Override
+    public boolean isRunning() {
+        return mRunning;
+    }
+
+    @Override
+    public boolean isStarted() {
+        return mViewPropertyAnimator != null;
+    }
+
+    @Override
+    public void removeAllListeners() {
+        mListeners.clear();
+    }
+
+    @Override
+    public void removeListener(Animator.AnimatorListener listener) {
+        mListeners.remove(listener);
+    }
+
+    @Override
+    public Animator setDuration(long duration) {
+        mPropertiesToSet.add(Properties.DURATION);
+        mDuration = duration;
+        return this;
+    }
+
+    @Override
+    public void setInterpolator(TimeInterpolator value) {
+        mPropertiesToSet.add(Properties.INTERPOLATOR);
+        mInterpolator = value;
+    }
+
+    @Override
+    public void setStartDelay(long startDelay) {
+        mPropertiesToSet.add(Properties.START_DELAY);
+        mStartDelay = startDelay;
+    }
+
+    @Override
+    public void setTarget(Object target) {
+        throw new RuntimeException("Not implemented");
+    }
+
+    @Override
+    public void setupEndValues() {
+
+    }
+
+    @Override
+    public void setupStartValues() {
+    }
+
+    @Override
+    public void start() {
+        mViewPropertyAnimator = mTarget.animate();
+        if (mPropertiesToSet.contains(Properties.TRANSLATION_X)) {
+            mViewPropertyAnimator.translationX(mTranslationX);
+        }
+        if (mPropertiesToSet.contains(Properties.TRANSLATION_Y)) {
+            mViewPropertyAnimator.translationY(mTranslationY);
+        }
+        if (mPropertiesToSet.contains(Properties.SCALE_X)) {
+            mViewPropertyAnimator.scaleX(mScaleX);
+        }
+        if (mPropertiesToSet.contains(Properties.ROTATION_Y)) {
+            mViewPropertyAnimator.rotationY(mRotationY);
+        }
+        if (mPropertiesToSet.contains(Properties.SCALE_Y)) {
+            mViewPropertyAnimator.scaleY(mScaleY);
+        }
+        if (mPropertiesToSet.contains(Properties.ALPHA)) {
+            mViewPropertyAnimator.alpha(mAlpha);
+        }
+        if (mPropertiesToSet.contains(Properties.START_DELAY)) {
+            mViewPropertyAnimator.setStartDelay(mStartDelay);
+        }
+        if (mPropertiesToSet.contains(Properties.DURATION)) {
+            mViewPropertyAnimator.setDuration(mDuration);
+        }
+        if (mPropertiesToSet.contains(Properties.INTERPOLATOR)) {
+            mViewPropertyAnimator.setInterpolator(mInterpolator);
+        }
+        mViewPropertyAnimator.setListener(this);
+        mViewPropertyAnimator.start();
+        LauncherAnimUtils.cancelOnDestroyActivity(this);
+    }
+
+    public LauncherViewPropertyAnimator translationX(float value) {
+        mPropertiesToSet.add(Properties.TRANSLATION_X);
+        mTranslationX = value;
+        return this;
+    }
+
+    public LauncherViewPropertyAnimator translationY(float value) {
+        mPropertiesToSet.add(Properties.TRANSLATION_Y);
+        mTranslationY = value;
+        return this;
+    }
+
+    public LauncherViewPropertyAnimator scaleX(float value) {
+        mPropertiesToSet.add(Properties.SCALE_X);
+        mScaleX = value;
+        return this;
+    }
+
+    public LauncherViewPropertyAnimator scaleY(float value) {
+        mPropertiesToSet.add(Properties.SCALE_Y);
+        mScaleY = value;
+        return this;
+    }
+
+    public LauncherViewPropertyAnimator rotationY(float value) {
+        mPropertiesToSet.add(Properties.ROTATION_Y);
+        mRotationY = value;
+        return this;
+    }
+
+    public LauncherViewPropertyAnimator alpha(float value) {
+        mPropertiesToSet.add(Properties.ALPHA);
+        mAlpha = value;
+        return this;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedView.java b/FairphoneHome/src/org/fairphone/launcher/PagedView.java
new file mode 100644
index 0000000..785a86d
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedView.java
@@ -0,0 +1,1929 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+import org.fairphone.launcher.R;
+
+import java.util.ArrayList;
+
+/**
+ * An abstraction of the original Workspace which supports browsing through a
+ * sequential list of "pages"
+ */
+public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
+    private static final String TAG = "PagedView";
+    private static final boolean DEBUG = false;
+    protected static final int INVALID_PAGE = -1;
+
+    // the min drag distance for a fling to register, to prevent random page shifts
+    private static final int MIN_LENGTH_FOR_FLING = 25;
+
+    protected static final int PAGE_SNAP_ANIMATION_DURATION = 550;
+    protected static final int MAX_PAGE_SNAP_DURATION = 750;
+    protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
+    protected static final float NANOTIME_DIV = 1000000000.0f;
+
+    private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
+    private static final float OVERSCROLL_DAMP_FACTOR = 0.14f;
+
+    private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
+    // The page is moved more than halfway, automatically move to the next page on touch up.
+    private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f;
+
+    // The following constants need to be scaled based on density. The scaled versions will be
+    // assigned to the corresponding member variables below.
+    private static final int FLING_THRESHOLD_VELOCITY = 500;
+    private static final int MIN_SNAP_VELOCITY = 1500;
+    private static final int MIN_FLING_VELOCITY = 250;
+
+    static final int AUTOMATIC_PAGE_SPACING = -1;
+
+    protected int mFlingThresholdVelocity;
+    protected int mMinFlingVelocity;
+    protected int mMinSnapVelocity;
+
+    protected float mDensity;
+    protected float mSmoothingTime;
+    protected float mTouchX;
+
+    protected boolean mFirstLayout = true;
+
+    protected int mCurrentPage;
+    protected int mNextPage = INVALID_PAGE;
+    protected int mMaxScrollX;
+    protected Scroller mScroller;
+    private VelocityTracker mVelocityTracker;
+
+    private float mDownMotionX;
+    protected float mLastMotionX;
+    protected float mLastMotionXRemainder;
+    protected float mLastMotionY;
+    protected float mTotalMotionX;
+    private int mLastScreenCenter = -1;
+    private int[] mChildOffsets;
+    private int[] mChildRelativeOffsets;
+    private int[] mChildOffsetsWithLayoutScale;
+
+    protected final static int TOUCH_STATE_REST = 0;
+    protected final static int TOUCH_STATE_SCROLLING = 1;
+    protected final static int TOUCH_STATE_PREV_PAGE = 2;
+    protected final static int TOUCH_STATE_NEXT_PAGE = 3;
+    protected final static float ALPHA_QUANTIZE_LEVEL = 0.0001f;
+
+    protected int mTouchState = TOUCH_STATE_REST;
+    protected boolean mForceScreenScrolled = false;
+
+    protected OnLongClickListener mLongClickListener;
+
+    protected boolean mAllowLongPress = true;
+
+    protected int mTouchSlop;
+    private int mPagingTouchSlop;
+    private int mMaximumVelocity;
+    private int mMinimumWidth;
+    protected int mPageSpacing;
+    protected int mPageLayoutPaddingTop;
+    protected int mPageLayoutPaddingBottom;
+    protected int mPageLayoutPaddingLeft;
+    protected int mPageLayoutPaddingRight;
+    protected int mPageLayoutWidthGap;
+    protected int mPageLayoutHeightGap;
+    protected int mCellCountX = 0;
+    protected int mCellCountY = 0;
+    protected boolean mCenterPagesVertically;
+    protected boolean mAllowOverScroll = true;
+    protected int mUnboundedScrollX;
+    protected int[] mTempVisiblePagesRange = new int[2];
+    protected boolean mForceDrawAllChildrenNextFrame;
+
+    // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. Otherwise
+    // it is equal to the scaled overscroll position. We use a separate value so as to prevent
+    // the screens from continuing to translate beyond the normal bounds.
+    protected int mOverScrollX;
+
+    // parameter that adjusts the layout to be optimized for pages with that scale factor
+    protected float mLayoutScale = 1.0f;
+
+    protected static final int INVALID_POINTER = -1;
+
+    protected int mActivePointerId = INVALID_POINTER;
+
+    private PageSwitchListener mPageSwitchListener;
+
+    protected ArrayList<Boolean> mDirtyPageContent;
+
+    // If true, syncPages and syncPageItems will be called to refresh pages
+    protected boolean mContentIsRefreshable = true;
+
+    // If true, modify alpha of neighboring pages as user scrolls left/right
+    protected boolean mFadeInAdjacentScreens = true;
+
+    // It true, use a different slop parameter (pagingTouchSlop = 2 * touchSlop) for deciding
+    // to switch to a new page
+    protected boolean mUsePagingTouchSlop = true;
+
+    // If true, the subclass should directly update scrollX itself in its computeScroll method
+    // (SmoothPagedView does this)
+    protected boolean mDeferScrollUpdate = false;
+
+    protected boolean mIsPageMoving = false;
+
+    // All syncs and layout passes are deferred until data is ready.
+    protected boolean mIsDataReady = false;
+
+    // Scrolling indicator
+    private ValueAnimator mScrollIndicatorAnimator;
+    private View mScrollIndicator;
+    private int mScrollIndicatorPaddingLeft;
+    private int mScrollIndicatorPaddingRight;
+    private boolean mHasScrollIndicator = true;
+    private boolean mShouldShowScrollIndicator = false;
+    private boolean mShouldShowScrollIndicatorImmediately = false;
+    protected static final int sScrollIndicatorFadeInDuration = 150;
+    protected static final int sScrollIndicatorFadeOutDuration = 650;
+    protected static final int sScrollIndicatorFlashDuration = 650;
+    private boolean mScrollingPaused = false;
+
+    // If set, will defer loading associated pages until the scrolling settles
+    private boolean mDeferLoadAssociatedPagesUntilScrollCompletes;
+
+    public interface PageSwitchListener {
+        void onPageSwitch(View newPage, int newPageIndex);
+    }
+
+    public PagedView(Context context) {
+        this(context, null);
+    }
+
+    public PagedView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PagedView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.PagedView, defStyle, 0);
+        setPageSpacing(a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0));
+        mPageLayoutPaddingTop = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingTop, 0);
+        mPageLayoutPaddingBottom = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingBottom, 0);
+        mPageLayoutPaddingLeft = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingLeft, 0);
+        mPageLayoutPaddingRight = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingRight, 0);
+        mPageLayoutWidthGap = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutWidthGap, 0);
+        mPageLayoutHeightGap = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutHeightGap, 0);
+        mScrollIndicatorPaddingLeft =
+            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);
+        mScrollIndicatorPaddingRight =
+            a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
+        a.recycle();
+
+        setHapticFeedbackEnabled(false);
+        init();
+    }
+
+    /**
+     * Initializes various states for this workspace.
+     */
+    protected void init() {
+        mDirtyPageContent = new ArrayList<Boolean>();
+        mDirtyPageContent.ensureCapacity(32);
+        mScroller = new Scroller(getContext(), new ScrollInterpolator());
+        mCurrentPage = 0;
+        mCenterPagesVertically = true;
+
+        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+        mTouchSlop = configuration.getScaledTouchSlop();
+        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
+        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+        mDensity = getResources().getDisplayMetrics().density;
+
+        mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+        mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
+        mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
+        setOnHierarchyChangeListener(this);
+    }
+
+    public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
+        mPageSwitchListener = pageSwitchListener;
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
+        }
+    }
+
+    /**
+     * Called by subclasses to mark that data is ready, and that we can begin loading and laying
+     * out pages.
+     */
+    protected void setDataIsReady() {
+        mIsDataReady = true;
+    }
+    protected boolean isDataReady() {
+        return mIsDataReady;
+    }
+
+    /**
+     * Returns the index of the currently displayed page.
+     *
+     * @return The index of the currently displayed page.
+     */
+    int getCurrentPage() {
+        return mCurrentPage;
+    }
+    int getNextPage() {
+        return (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
+    }
+
+    int getPageCount() {
+        return getChildCount();
+    }
+
+    View getPageAt(int index) {
+        return getChildAt(index);
+    }
+
+    protected int indexToPage(int index) {
+        return index;
+    }
+
+    /**
+     * Updates the scroll of the current page immediately to its final scroll position.  We use this
+     * in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
+     * the previous tab page.
+     */
+    protected void updateCurrentPageScroll() {
+        // If the current page is invalid, just reset the scroll position to zero
+        int newX = 0;
+        if (0 <= mCurrentPage && mCurrentPage < getPageCount()) {
+            int offset = getChildOffset(mCurrentPage);
+            int relOffset = getRelativeChildOffset(mCurrentPage);
+            newX = offset - relOffset;
+        }
+        scrollTo(newX, 0);
+        mScroller.setFinalX(newX);
+        mScroller.forceFinished(true);
+    }
+
+    /**
+     * Called during AllApps/Home transitions to avoid unnecessary work. When that other animation
+     * ends, {@link #resumeScrolling()} should be called, along with
+     * {@link #updateCurrentPageScroll()} to correctly set the final state and re-enable scrolling.
+     */
+    void pauseScrolling() {
+        mScroller.forceFinished(true);
+        cancelScrollingIndicatorAnimations();
+        mScrollingPaused = true;
+    }
+
+    /**
+     * Enables scrolling again.
+     * @see #pauseScrolling()
+     */
+    void resumeScrolling() {
+        mScrollingPaused = false;
+    }
+    /**
+     * Sets the current page.
+     */
+    void setCurrentPage(int currentPage) {
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+        }
+        // don't introduce any checks like mCurrentPage == currentPage here-- if we change the
+        // the default
+        if (getChildCount() == 0) {
+            return;
+        }
+
+
+        mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
+        updateCurrentPageScroll();
+        updateScrollingIndicator();
+        notifyPageSwitchListener();
+        invalidate();
+    }
+
+    protected void notifyPageSwitchListener() {
+        if (mPageSwitchListener != null) {
+            mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
+        }
+    }
+
+    protected void pageBeginMoving() {
+        if (!mIsPageMoving) {
+            mIsPageMoving = true;
+            onPageBeginMoving();
+        }
+    }
+
+    protected void pageEndMoving() {
+        if (mIsPageMoving) {
+            mIsPageMoving = false;
+            onPageEndMoving();
+        }
+    }
+
+    protected boolean isPageMoving() {
+        return mIsPageMoving;
+    }
+
+    // a method that subclasses can override to add behavior
+    protected void onPageBeginMoving() {
+    }
+
+    // a method that subclasses can override to add behavior
+    protected void onPageEndMoving() {
+    }
+
+    /**
+     * Registers the specified listener on each page contained in this workspace.
+     *
+     * @param l The listener used to respond to long clicks.
+     */
+    @Override
+    public void setOnLongClickListener(OnLongClickListener l) {
+        mLongClickListener = l;
+        final int count = getPageCount();
+        for (int i = 0; i < count; i++) {
+            getPageAt(i).setOnLongClickListener(l);
+        }
+    }
+
+    @Override
+    public void scrollBy(int x, int y) {
+        scrollTo(mUnboundedScrollX + x, getScrollY() + y);
+    }
+
+    @Override
+    public void scrollTo(int x, int y) {
+        mUnboundedScrollX = x;
+
+        if (x < 0) {
+            super.scrollTo(0, y);
+            if (mAllowOverScroll) {
+                overScroll(x);
+            }
+        } else if (x > mMaxScrollX) {
+            super.scrollTo(mMaxScrollX, y);
+            if (mAllowOverScroll) {
+                overScroll(x - mMaxScrollX);
+            }
+        } else {
+            mOverScrollX = x;
+            super.scrollTo(x, y);
+        }
+
+        mTouchX = x;
+        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+    }
+
+    // we moved this functionality to a helper function so SmoothPagedView can reuse it
+    protected boolean computeScrollHelper() {
+        if (mScroller.computeScrollOffset()) {
+            // Don't bother scrolling if the page does not need to be moved
+            if (getScrollX() != mScroller.getCurrX()
+                || getScrollY() != mScroller.getCurrY()
+                || mOverScrollX != mScroller.getCurrX()) {
+                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
+            }
+            invalidate();
+            return true;
+        } else if (mNextPage != INVALID_PAGE) {
+            mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1));
+            mNextPage = INVALID_PAGE;
+            notifyPageSwitchListener();
+
+            // Load the associated pages if necessary
+            if (mDeferLoadAssociatedPagesUntilScrollCompletes) {
+                loadAssociatedPages(mCurrentPage);
+                mDeferLoadAssociatedPagesUntilScrollCompletes = false;
+            }
+
+            // We don't want to trigger a page end moving unless the page has settled
+            // and the user has stopped scrolling
+            if (mTouchState == TOUCH_STATE_REST) {
+                pageEndMoving();
+            }
+
+            // Notify the user when the page changes
+            AccessibilityManager accessibilityManager = (AccessibilityManager)
+                    getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+            if (accessibilityManager.isEnabled()) {
+                AccessibilityEvent ev =
+                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+                ev.getText().add(getCurrentPageDescription());
+                sendAccessibilityEventUnchecked(ev);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void computeScroll() {
+        computeScrollHelper();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (!mIsDataReady) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        if (widthMode != MeasureSpec.EXACTLY) {
+            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
+        }
+
+        // Return early if we aren't given a proper dimension
+        if (widthSize <= 0 || heightSize <= 0) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
+        /* Allow the height to be set as WRAP_CONTENT. This allows the particular case
+         * of the All apps view on XLarge displays to not take up more space then it needs. Width
+         * is still not allowed to be set as WRAP_CONTENT since many parts of the code expect
+         * each page to have the same width.
+         */
+        int maxChildHeight = 0;
+
+        final int verticalPadding = getPaddingTop() + getPaddingBottom();
+        final int horizontalPadding = getPaddingLeft() + getPaddingRight();
+
+
+        // The children are given the same width and height as the workspace
+        // unless they were set to WRAP_CONTENT
+        if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            // disallowing padding in paged view (just pass 0)
+            final View child = getPageAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+            int childWidthMode;
+            if (lp.width == LayoutParams.WRAP_CONTENT) {
+                childWidthMode = MeasureSpec.AT_MOST;
+            } else {
+                childWidthMode = MeasureSpec.EXACTLY;
+            }
+
+            int childHeightMode;
+            if (lp.height == LayoutParams.WRAP_CONTENT) {
+                childHeightMode = MeasureSpec.AT_MOST;
+            } else {
+                childHeightMode = MeasureSpec.EXACTLY;
+            }
+
+            final int childWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(widthSize - horizontalPadding, childWidthMode);
+            final int childHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode);
+
+            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+            maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
+            if (DEBUG) Log.d(TAG, "\tmeasure-child" + i + ": " + child.getMeasuredWidth() + ", "
+                    + child.getMeasuredHeight());
+        }
+
+        if (heightMode == MeasureSpec.AT_MOST) {
+            heightSize = maxChildHeight + verticalPadding;
+        }
+
+        setMeasuredDimension(widthSize, heightSize);
+
+        // We can't call getChildOffset/getRelativeChildOffset until we set the measured dimensions.
+        // We also wait until we set the measured dimensions before flushing the cache as well, to
+        // ensure that the cache is filled with good values.
+        invalidateCachedOffsets();
+
+        if (childCount > 0) {
+            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                    + getChildWidth(0));
+
+            // Calculate the variable page spacing if necessary
+            if (mPageSpacing == AUTOMATIC_PAGE_SPACING) {
+                // The gap between pages in the PagedView should be equal to the gap from the page
+                // to the edge of the screen (so it is not visible in the current screen).  To
+                // account for unequal padding on each side of the paged view, we take the maximum
+                // of the left/right gap and use that as the gap between each page.
+                int offset = getRelativeChildOffset(0);
+                int spacing = Math.max(offset, widthSize - offset -
+                        getChildAt(0).getMeasuredWidth());
+                setPageSpacing(spacing);
+            }
+        }
+
+        updateScrollingIndicatorPosition();
+
+        if (childCount > 0) {
+            mMaxScrollX = getChildOffset(childCount - 1) - getRelativeChildOffset(childCount - 1);
+        } else {
+            mMaxScrollX = 0;
+        }
+    }
+
+    protected void scrollToNewPageWithoutMovingPages(int newCurrentPage) {
+        int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
+        int delta = newX - getScrollX();
+
+        final int pageCount = getChildCount();
+        for (int i = 0; i < pageCount; i++) {
+            View page = (View) getPageAt(i);
+            page.setX(page.getX() + delta);
+        }
+        setCurrentPage(newCurrentPage);
+    }
+
+    // A layout scale of 1.0f assumes that the pages, in their unshrunken state, have a
+    // scale of 1.0f. A layout scale of 0.8f assumes the pages have a scale of 0.8f, and
+    // tightens the layout accordingly
+    public void setLayoutScale(float childrenScale) {
+        mLayoutScale = childrenScale;
+        invalidateCachedOffsets();
+
+        // Now we need to do a re-layout, but preserving absolute X and Y coordinates
+        int childCount = getChildCount();
+        float childrenX[] = new float[childCount];
+        float childrenY[] = new float[childCount];
+        for (int i = 0; i < childCount; i++) {
+            final View child = getPageAt(i);
+            childrenX[i] = child.getX();
+            childrenY[i] = child.getY();
+        }
+        // Trigger a full re-layout (never just call onLayout directly!)
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY);
+        requestLayout();
+        measure(widthSpec, heightSpec);
+        layout(getLeft(), getTop(), getRight(), getBottom());
+        for (int i = 0; i < childCount; i++) {
+            final View child = getPageAt(i);
+            child.setX(childrenX[i]);
+            child.setY(childrenY[i]);
+        }
+
+        // Also, the page offset has changed  (since the pages are now smaller);
+        // update the page offset, but again preserving absolute X and Y coordinates
+        scrollToNewPageWithoutMovingPages(mCurrentPage);
+    }
+
+    public void setPageSpacing(int pageSpacing) {
+        mPageSpacing = pageSpacing;
+        invalidateCachedOffsets();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (!mIsDataReady) {
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
+        final int verticalPadding = getPaddingTop() + getPaddingBottom();
+        final int childCount = getChildCount();
+        int childLeft = getRelativeChildOffset(0);
+
+        for (int i = 0; i < childCount; i++) {
+            final View child = getPageAt(i);
+            if (child.getVisibility() != View.GONE) {
+                final int childWidth = getScaledMeasuredWidth(child);
+                final int childHeight = child.getMeasuredHeight();
+                int childTop = getPaddingTop();
+                if (mCenterPagesVertically) {
+                    childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2;
+                }
+
+                if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
+                child.layout(childLeft, childTop,
+                        childLeft + child.getMeasuredWidth(), childTop + childHeight);
+                childLeft += childWidth + mPageSpacing;
+            }
+        }
+
+        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
+            setHorizontalScrollBarEnabled(false);
+            updateCurrentPageScroll();
+            setHorizontalScrollBarEnabled(true);
+            mFirstLayout = false;
+        }
+    }
+
+    protected void screenScrolled(int screenCenter) {
+        if (isScrollingIndicatorEnabled()) {
+            updateScrollingIndicator();
+        }
+        boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
+
+        if (mFadeInAdjacentScreens && !isInOverscroll) {
+            for (int i = 0; i < getChildCount(); i++) {
+                View child = getChildAt(i);
+                if (child != null) {
+                    float scrollProgress = getScrollProgress(screenCenter, child, i);
+                    float alpha = 1 - Math.abs(scrollProgress);
+                    child.setAlpha(alpha);
+                }
+            }
+            invalidate();
+        }
+    }
+
+    @Override
+    public void onChildViewAdded(View parent, View child) {
+        // This ensures that when children are added, they get the correct transforms / alphas
+        // in accordance with any scroll effects.
+        mForceScreenScrolled = true;
+        invalidate();
+        invalidateCachedOffsets();
+    }
+
+    @Override
+    public void onChildViewRemoved(View parent, View child) {
+    }
+
+    protected void invalidateCachedOffsets() {
+        int count = getChildCount();
+        if (count == 0) {
+            mChildOffsets = null;
+            mChildRelativeOffsets = null;
+            mChildOffsetsWithLayoutScale = null;
+            return;
+        }
+
+        mChildOffsets = new int[count];
+        mChildRelativeOffsets = new int[count];
+        mChildOffsetsWithLayoutScale = new int[count];
+        for (int i = 0; i < count; i++) {
+            mChildOffsets[i] = -1;
+            mChildRelativeOffsets[i] = -1;
+            mChildOffsetsWithLayoutScale[i] = -1;
+        }
+    }
+
+    protected int getChildOffset(int index) {
+        int[] childOffsets = Float.compare(mLayoutScale, 1f) == 0 ?
+                mChildOffsets : mChildOffsetsWithLayoutScale;
+
+        if (childOffsets != null && childOffsets[index] != -1) {
+            return childOffsets[index];
+        } else {
+            if (getChildCount() == 0)
+                return 0;
+
+            int offset = getRelativeChildOffset(0);
+            for (int i = 0; i < index; ++i) {
+                offset += getScaledMeasuredWidth(getPageAt(i)) + mPageSpacing;
+            }
+            if (childOffsets != null) {
+                childOffsets[index] = offset;
+            }
+            return offset;
+        }
+    }
+
+    protected int getRelativeChildOffset(int index) {
+        if (mChildRelativeOffsets != null && mChildRelativeOffsets[index] != -1) {
+            return mChildRelativeOffsets[index];
+        } else {
+            final int padding = getPaddingLeft() + getPaddingRight();
+            final int offset = getPaddingLeft() +
+                    (getMeasuredWidth() - padding - getChildWidth(index)) / 2;
+            if (mChildRelativeOffsets != null) {
+                mChildRelativeOffsets[index] = offset;
+            }
+            return offset;
+        }
+    }
+
+    protected int getScaledMeasuredWidth(View child) {
+        // This functions are called enough times that it actually makes a difference in the
+        // profiler -- so just inline the max() here
+        final int measuredWidth = child.getMeasuredWidth();
+        final int minWidth = mMinimumWidth;
+        final int maxWidth = (minWidth > measuredWidth) ? minWidth : measuredWidth;
+        return (int) (maxWidth * mLayoutScale + 0.5f);
+    }
+
+    protected void getVisiblePages(int[] range) {
+        final int pageCount = getChildCount();
+
+        if (pageCount > 0) {
+            final int screenWidth = getMeasuredWidth();
+            int leftScreen = 0;
+            int rightScreen = 0;
+            View currPage = getPageAt(leftScreen);
+            while (leftScreen < pageCount - 1 &&
+                    currPage.getX() + currPage.getWidth() -
+                    currPage.getPaddingRight() < getScrollX()) {
+                leftScreen++;
+                currPage = getPageAt(leftScreen);
+            }
+            rightScreen = leftScreen;
+            currPage = getPageAt(rightScreen + 1);
+            while (rightScreen < pageCount - 1 &&
+                    currPage.getX() - currPage.getPaddingLeft() < getScrollX() + screenWidth) {
+                rightScreen++;
+                currPage = getPageAt(rightScreen + 1);
+            }
+            range[0] = leftScreen;
+            range[1] = rightScreen;
+        } else {
+            range[0] = -1;
+            range[1] = -1;
+        }
+    }
+
+    protected boolean shouldDrawChild(View child) {
+        return child.getAlpha() > 0;
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        int halfScreenSize = getMeasuredWidth() / 2;
+        // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
+        // Otherwise it is equal to the scaled overscroll position.
+        int screenCenter = mOverScrollX + halfScreenSize;
+
+        if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
+            // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
+            // set it for the next frame
+            mForceScreenScrolled = false;
+            screenScrolled(screenCenter);
+            mLastScreenCenter = screenCenter;
+        }
+
+        // Find out which screens are visible; as an optimization we only call draw on them
+        final int pageCount = getChildCount();
+        if (pageCount > 0) {
+            getVisiblePages(mTempVisiblePagesRange);
+            final int leftScreen = mTempVisiblePagesRange[0];
+            final int rightScreen = mTempVisiblePagesRange[1];
+            if (leftScreen != -1 && rightScreen != -1) {
+                final long drawingTime = getDrawingTime();
+                // Clip to the bounds
+                canvas.save();
+                canvas.clipRect(getScrollX(), getScrollY(), getScrollX() + getRight() - getLeft(),
+                        getScrollY() + getBottom() - getTop());
+
+                for (int i = getChildCount() - 1; i >= 0; i--) {
+                    final View v = getPageAt(i);
+                    if (mForceDrawAllChildrenNextFrame ||
+                               (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
+                        drawChild(canvas, v, drawingTime);
+                    }
+                }
+                mForceDrawAllChildrenNextFrame = false;
+                canvas.restore();
+            }
+        }
+    }
+
+    @Override
+    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
+        int page = indexToPage(indexOfChild(child));
+        if (page != mCurrentPage || !mScroller.isFinished()) {
+            snapToPage(page);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        int focusablePage;
+        if (mNextPage != INVALID_PAGE) {
+            focusablePage = mNextPage;
+        } else {
+            focusablePage = mCurrentPage;
+        }
+        View v = getPageAt(focusablePage);
+        if (v != null) {
+            return v.requestFocus(direction, previouslyFocusedRect);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean dispatchUnhandledMove(View focused, int direction) {
+        if (direction == View.FOCUS_LEFT) {
+            if (getCurrentPage() > 0) {
+                snapToPage(getCurrentPage() - 1);
+                return true;
+            }
+        } else if (direction == View.FOCUS_RIGHT) {
+            if (getCurrentPage() < getPageCount() - 1) {
+                snapToPage(getCurrentPage() + 1);
+                return true;
+            }
+        }
+        return super.dispatchUnhandledMove(focused, direction);
+    }
+
+    @Override
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        if (mCurrentPage >= 0 && mCurrentPage < getPageCount()) {
+            getPageAt(mCurrentPage).addFocusables(views, direction, focusableMode);
+        }
+        if (direction == View.FOCUS_LEFT) {
+            if (mCurrentPage > 0) {
+                getPageAt(mCurrentPage - 1).addFocusables(views, direction, focusableMode);
+            }
+        } else if (direction == View.FOCUS_RIGHT){
+            if (mCurrentPage < getPageCount() - 1) {
+                getPageAt(mCurrentPage + 1).addFocusables(views, direction, focusableMode);
+            }
+        }
+    }
+
+    /**
+     * If one of our descendant views decides that it could be focused now, only
+     * pass that along if it's on the current page.
+     *
+     * This happens when live folders requery, and if they're off page, they
+     * end up calling requestFocus, which pulls it on page.
+     */
+    @Override
+    public void focusableViewAvailable(View focused) {
+        View current = getPageAt(mCurrentPage);
+        View v = focused;
+        while (true) {
+            if (v == current) {
+                super.focusableViewAvailable(focused);
+                return;
+            }
+            if (v == this) {
+                return;
+            }
+            ViewParent parent = v.getParent();
+            if (parent instanceof View) {
+                v = (View)v.getParent();
+            } else {
+                return;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+        if (disallowIntercept) {
+            // We need to make sure to cancel our long press if
+            // a scrollable widget takes over touch events
+            final View currentPage = getPageAt(mCurrentPage);
+            currentPage.cancelLongPress();
+        }
+        super.requestDisallowInterceptTouchEvent(disallowIntercept);
+    }
+
+    /**
+     * Return true if a tap at (x, y) should trigger a flip to the previous page.
+     */
+    protected boolean hitsPreviousPage(float x, float y) {
+        return (x < getRelativeChildOffset(mCurrentPage) - mPageSpacing);
+    }
+
+    /**
+     * Return true if a tap at (x, y) should trigger a flip to the next page.
+     */
+    protected boolean hitsNextPage(float x, float y) {
+        return  (x > (getMeasuredWidth() - getRelativeChildOffset(mCurrentPage) + mPageSpacing));
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        /*
+         * This method JUST determines whether we want to intercept the motion.
+         * If we return true, onTouchEvent will be called and we do the actual
+         * scrolling there.
+         */
+        acquireVelocityTrackerAndAddMovement(ev);
+
+        // Skip touch handling if there are no pages to swipe
+        if (getChildCount() <= 0) return super.onInterceptTouchEvent(ev);
+
+        /*
+         * Shortcut the most recurring case: the user is in the dragging
+         * state and he is moving his finger.  We want to intercept this
+         * motion.
+         */
+        final int action = ev.getAction();
+        if ((action == MotionEvent.ACTION_MOVE) &&
+                (mTouchState == TOUCH_STATE_SCROLLING)) {
+            return true;
+        }
+
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_MOVE: {
+                /*
+                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
+                 * whether the user has moved far enough from his original down touch.
+                 */
+                if (mActivePointerId != INVALID_POINTER) {
+                    determineScrollingStart(ev);
+                    break;
+                }
+                // if mActivePointerId is INVALID_POINTER, then we must have missed an ACTION_DOWN
+                // event. in that case, treat the first occurence of a move event as a ACTION_DOWN
+                // i.e. fall through to the next case (don't break)
+                // (We sometimes miss ACTION_DOWN events in Workspace because it ignores all events
+                // while it's small- this was causing a crash before we checked for INVALID_POINTER)
+            }
+
+            case MotionEvent.ACTION_DOWN: {
+                final float x = ev.getX();
+                final float y = ev.getY();
+                // Remember location of down touch
+                mDownMotionX = x;
+                mLastMotionX = x;
+                mLastMotionY = y;
+                mLastMotionXRemainder = 0;
+                mTotalMotionX = 0;
+                mActivePointerId = ev.getPointerId(0);
+                mAllowLongPress = true;
+
+                /*
+                 * If being flinged and user touches the screen, initiate drag;
+                 * otherwise don't.  mScroller.isFinished should be false when
+                 * being flinged.
+                 */
+                final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
+                final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop);
+                if (finishedScrolling) {
+                    mTouchState = TOUCH_STATE_REST;
+                    mScroller.abortAnimation();
+                } else {
+                    mTouchState = TOUCH_STATE_SCROLLING;
+                }
+
+                // check if this can be the beginning of a tap on the side of the pages
+                // to scroll the current page
+                if (mTouchState != TOUCH_STATE_PREV_PAGE && mTouchState != TOUCH_STATE_NEXT_PAGE) {
+                    if (getChildCount() > 0) {
+                        if (hitsPreviousPage(x, y)) {
+                            mTouchState = TOUCH_STATE_PREV_PAGE;
+                        } else if (hitsNextPage(x, y)) {
+                            mTouchState = TOUCH_STATE_NEXT_PAGE;
+                        }
+                    }
+                }
+                break;
+            }
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mTouchState = TOUCH_STATE_REST;
+                mAllowLongPress = false;
+                mActivePointerId = INVALID_POINTER;
+                releaseVelocityTracker();
+                break;
+
+            case MotionEvent.ACTION_POINTER_UP:
+                onSecondaryPointerUp(ev);
+                releaseVelocityTracker();
+                break;
+        }
+
+        /*
+         * The only time we want to intercept motion events is if we are in the
+         * drag mode.
+         */
+        return mTouchState != TOUCH_STATE_REST;
+    }
+
+    protected void determineScrollingStart(MotionEvent ev) {
+        determineScrollingStart(ev, 1.0f);
+    }
+
+    /*
+     * Determines if we should change the touch state to start scrolling after the
+     * user moves their touch point too far.
+     */
+    protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
+        /*
+         * Locally do absolute value. mLastMotionX is set to the y value
+         * of the down event.
+         */
+        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        if (pointerIndex == -1) {
+            return;
+        }
+        final float x = ev.getX(pointerIndex);
+        final float y = ev.getY(pointerIndex);
+        final int xDiff = (int) Math.abs(x - mLastMotionX);
+        final int yDiff = (int) Math.abs(y - mLastMotionY);
+
+        final int touchSlop = Math.round(touchSlopScale * mTouchSlop);
+        boolean xPaged = xDiff > mPagingTouchSlop;
+        boolean xMoved = xDiff > touchSlop;
+        boolean yMoved = yDiff > touchSlop;
+
+        if (xMoved || xPaged || yMoved) {
+            if (mUsePagingTouchSlop ? xPaged : xMoved) {
+                // Scroll if the user moved far enough along the X axis
+                mTouchState = TOUCH_STATE_SCROLLING;
+                mTotalMotionX += Math.abs(mLastMotionX - x);
+                mLastMotionX = x;
+                mLastMotionXRemainder = 0;
+                mTouchX = getScrollX();
+                mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                pageBeginMoving();
+            }
+            // Either way, cancel any pending longpress
+            cancelCurrentPageLongPress();
+        }
+    }
+
+    protected void cancelCurrentPageLongPress() {
+        if (mAllowLongPress) {
+            mAllowLongPress = false;
+            // Try canceling the long press. It could also have been scheduled
+            // by a distant descendant, so use the mAllowLongPress flag to block
+            // everything
+            final View currentPage = getPageAt(mCurrentPage);
+            if (currentPage != null) {
+                currentPage.cancelLongPress();
+            }
+        }
+    }
+
+    protected float getScrollProgress(int screenCenter, View v, int page) {
+        final int halfScreenSize = getMeasuredWidth() / 2;
+
+        int totalDistance = getScaledMeasuredWidth(v) + mPageSpacing;
+        int delta = screenCenter - (getChildOffset(page) -
+                getRelativeChildOffset(page) + halfScreenSize);
+
+        float scrollProgress = delta / (totalDistance * 1.0f);
+        scrollProgress = Math.min(scrollProgress, 1.0f);
+        scrollProgress = Math.max(scrollProgress, -1.0f);
+        return scrollProgress;
+    }
+
+    // This curve determines how the effect of scrolling over the limits of the page dimishes
+    // as the user pulls further and further from the bounds
+    private float overScrollInfluenceCurve(float f) {
+        f -= 1.0f;
+        return f * f * f + 1.0f;
+    }
+
+    protected void acceleratedOverScroll(float amount) {
+        int screenSize = getMeasuredWidth();
+
+        // We want to reach the max over scroll effect when the user has
+        // over scrolled half the size of the screen
+        float f = OVERSCROLL_ACCELERATE_FACTOR * (amount / screenSize);
+
+        if (f == 0) return;
+
+        // Clamp this factor, f, to -1 < f < 1
+        if (Math.abs(f) >= 1) {
+            f /= Math.abs(f);
+        }
+
+        int overScrollAmount = (int) Math.round(f * screenSize);
+        if (amount < 0) {
+            mOverScrollX = overScrollAmount;
+            super.scrollTo(0, getScrollY());
+        } else {
+            mOverScrollX = mMaxScrollX + overScrollAmount;
+            super.scrollTo(mMaxScrollX, getScrollY());
+        }
+        invalidate();
+    }
+
+    protected void dampedOverScroll(float amount) {
+        int screenSize = getMeasuredWidth();
+
+        float f = (amount / screenSize);
+
+        if (f == 0) return;
+        f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+
+        // Clamp this factor, f, to -1 < f < 1
+        if (Math.abs(f) >= 1) {
+            f /= Math.abs(f);
+        }
+
+        int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
+        if (amount < 0) {
+            mOverScrollX = overScrollAmount;
+            super.scrollTo(0, getScrollY());
+        } else {
+            mOverScrollX = mMaxScrollX + overScrollAmount;
+            super.scrollTo(mMaxScrollX, getScrollY());
+        }
+        invalidate();
+    }
+
+    protected void overScroll(float amount) {
+        dampedOverScroll(amount);
+    }
+
+    protected float maxOverScroll() {
+        // Using the formula in overScroll, assuming that f = 1.0 (which it should generally not
+        // exceed). Used to find out how much extra wallpaper we need for the over scroll effect
+        float f = 1.0f;
+        f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+        return OVERSCROLL_DAMP_FACTOR * f;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        // Skip touch handling if there are no pages to swipe
+        if (getChildCount() <= 0) return super.onTouchEvent(ev);
+
+        acquireVelocityTrackerAndAddMovement(ev);
+
+        final int action = ev.getAction();
+
+        switch (action & MotionEvent.ACTION_MASK) {
+        case MotionEvent.ACTION_DOWN:
+            /*
+             * If being flinged and user touches, stop the fling. isFinished
+             * will be false if being flinged.
+             */
+            if (!mScroller.isFinished()) {
+                mScroller.abortAnimation();
+            }
+
+            // Remember where the motion event started
+            mDownMotionX = mLastMotionX = ev.getX();
+            mLastMotionXRemainder = 0;
+            mTotalMotionX = 0;
+            mActivePointerId = ev.getPointerId(0);
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                pageBeginMoving();
+            }
+            break;
+
+        case MotionEvent.ACTION_MOVE:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                // Scroll to follow the motion event
+                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+                final float x = ev.getX(pointerIndex);
+                final float deltaX = mLastMotionX + mLastMotionXRemainder - x;
+
+                mTotalMotionX += Math.abs(deltaX);
+
+                // Only scroll and update mLastMotionX if we have moved some discrete amount.  We
+                // keep the remainder because we are actually testing if we've moved from the last
+                // scrolled position (which is discrete).
+                if (Math.abs(deltaX) >= 1.0f) {
+                    mTouchX += deltaX;
+                    mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+                    if (!mDeferScrollUpdate) {
+                        scrollBy((int) deltaX, 0);
+                        if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
+                    } else {
+                        invalidate();
+                    }
+                    mLastMotionX = x;
+                    mLastMotionXRemainder = deltaX - (int) deltaX;
+                } else {
+                    awakenScrollBars();
+                }
+            } else {
+                determineScrollingStart(ev);
+            }
+            break;
+
+        case MotionEvent.ACTION_UP:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                final int activePointerId = mActivePointerId;
+                final int pointerIndex = ev.findPointerIndex(activePointerId);
+                final float x = ev.getX(pointerIndex);
+                final VelocityTracker velocityTracker = mVelocityTracker;
+                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                int velocityX = (int) velocityTracker.getXVelocity(activePointerId);
+                final int deltaX = (int) (x - mDownMotionX);
+                final int pageWidth = getScaledMeasuredWidth(getPageAt(mCurrentPage));
+                boolean isSignificantMove = Math.abs(deltaX) > pageWidth *
+                        SIGNIFICANT_MOVE_THRESHOLD;
+
+                mTotalMotionX += Math.abs(mLastMotionX + mLastMotionXRemainder - x);
+
+                boolean isFling = mTotalMotionX > MIN_LENGTH_FOR_FLING &&
+                        Math.abs(velocityX) > mFlingThresholdVelocity;
+
+                // In the case that the page is moved far to one direction and then is flung
+                // in the opposite direction, we use a threshold to determine whether we should
+                // just return to the starting page, or if we should skip one further.
+                boolean returnToOriginalPage = false;
+                if (Math.abs(deltaX) > pageWidth * RETURN_TO_ORIGINAL_PAGE_THRESHOLD &&
+                        Math.signum(velocityX) != Math.signum(deltaX) && isFling) {
+                    returnToOriginalPage = true;
+                }
+
+                int finalPage;
+                // We give flings precedence over large moves, which is why we short-circuit our
+                // test for a large move if a fling has been registered. That is, a large
+                // move to the left and fling to the right will register as a fling to the right.
+                if (((isSignificantMove && deltaX > 0 && !isFling) ||
+                        (isFling && velocityX > 0)) && mCurrentPage > 0) {
+                    finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
+                    snapToPageWithVelocity(finalPage, velocityX);
+                } else if (((isSignificantMove && deltaX < 0 && !isFling) ||
+                        (isFling && velocityX < 0)) &&
+                        mCurrentPage < getChildCount() - 1) {
+                    finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage + 1;
+                    snapToPageWithVelocity(finalPage, velocityX);
+                } else {
+                    snapToDestination();
+                }
+            } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
+                // at this point we have not moved beyond the touch slop
+                // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
+                // we can just page
+                int nextPage = Math.max(0, mCurrentPage - 1);
+                if (nextPage != mCurrentPage) {
+                    snapToPage(nextPage);
+                } else {
+                    snapToDestination();
+                }
+            } else if (mTouchState == TOUCH_STATE_NEXT_PAGE) {
+                // at this point we have not moved beyond the touch slop
+                // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
+                // we can just page
+                int nextPage = Math.min(getChildCount() - 1, mCurrentPage + 1);
+                if (nextPage != mCurrentPage) {
+                    snapToPage(nextPage);
+                } else {
+                    snapToDestination();
+                }
+            } else {
+                onUnhandledTap(ev);
+            }
+            mTouchState = TOUCH_STATE_REST;
+            mActivePointerId = INVALID_POINTER;
+            releaseVelocityTracker();
+            break;
+
+        case MotionEvent.ACTION_CANCEL:
+            if (mTouchState == TOUCH_STATE_SCROLLING) {
+                snapToDestination();
+            }
+            mTouchState = TOUCH_STATE_REST;
+            mActivePointerId = INVALID_POINTER;
+            releaseVelocityTracker();
+            break;
+
+        case MotionEvent.ACTION_POINTER_UP:
+            onSecondaryPointerUp(ev);
+            break;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_SCROLL: {
+                    // Handle mouse (or ext. device) by shifting the page depending on the scroll
+                    final float vscroll;
+                    final float hscroll;
+                    if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
+                        vscroll = 0;
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                    } else {
+                        vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+                    }
+                    if (hscroll != 0 || vscroll != 0) {
+                        if (hscroll > 0 || vscroll > 0) {
+                            scrollRight();
+                        } else {
+                            scrollLeft();
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        return super.onGenericMotionEvent(event);
+    }
+
+    private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+        mVelocityTracker.addMovement(ev);
+    }
+
+    private void releaseVelocityTracker() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+    }
+
+    private void onSecondaryPointerUp(MotionEvent ev) {
+        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+        final int pointerId = ev.getPointerId(pointerIndex);
+        if (pointerId == mActivePointerId) {
+            // This was our active pointer going up. Choose a new
+            // active pointer and adjust accordingly.
+            // TODO: Make this decision more intelligent.
+            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+            mLastMotionX = mDownMotionX = ev.getX(newPointerIndex);
+            mLastMotionY = ev.getY(newPointerIndex);
+            mLastMotionXRemainder = 0;
+            mActivePointerId = ev.getPointerId(newPointerIndex);
+            if (mVelocityTracker != null) {
+                mVelocityTracker.clear();
+            }
+        }
+    }
+
+    protected void onUnhandledTap(MotionEvent ev) {}
+
+    @Override
+    public void requestChildFocus(View child, View focused) {
+        super.requestChildFocus(child, focused);
+        int page = indexToPage(indexOfChild(child));
+        if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
+            snapToPage(page);
+        }
+    }
+
+    protected int getChildIndexForRelativeOffset(int relativeOffset) {
+        final int childCount = getChildCount();
+        int left;
+        int right;
+        for (int i = 0; i < childCount; ++i) {
+            left = getRelativeChildOffset(i);
+            right = (left + getScaledMeasuredWidth(getPageAt(i)));
+            if (left <= relativeOffset && relativeOffset <= right) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    protected int getChildWidth(int index) {
+        // This functions are called enough times that it actually makes a difference in the
+        // profiler -- so just inline the max() here
+        final int measuredWidth = getPageAt(index).getMeasuredWidth();
+        final int minWidth = mMinimumWidth;
+        return (minWidth > measuredWidth) ? minWidth : measuredWidth;
+    }
+
+    int getPageNearestToCenterOfScreen() {
+        int minDistanceFromScreenCenter = Integer.MAX_VALUE;
+        int minDistanceFromScreenCenterIndex = -1;
+        int screenCenter = getScrollX() + (getMeasuredWidth() / 2);
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            View layout = (View) getPageAt(i);
+            int childWidth = getScaledMeasuredWidth(layout);
+            int halfChildWidth = (childWidth / 2);
+            int childCenter = getChildOffset(i) + halfChildWidth;
+            int distanceFromScreenCenter = Math.abs(childCenter - screenCenter);
+            if (distanceFromScreenCenter < minDistanceFromScreenCenter) {
+                minDistanceFromScreenCenter = distanceFromScreenCenter;
+                minDistanceFromScreenCenterIndex = i;
+            }
+        }
+        return minDistanceFromScreenCenterIndex;
+    }
+
+    protected void snapToDestination() {
+        snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
+    }
+
+    private static class ScrollInterpolator implements Interpolator {
+        public ScrollInterpolator() {
+        }
+
+        public float getInterpolation(float t) {
+            t -= 1.0f;
+            return t*t*t*t*t + 1;
+        }
+    }
+
+    // We want the duration of the page snap animation to be influenced by the distance that
+    // the screen has to travel, however, we don't want this duration to be effected in a
+    // purely linear fashion. Instead, we use this method to moderate the effect that the distance
+    // of travel has on the overall snap duration.
+    float distanceInfluenceForSnapDuration(float f) {
+        f -= 0.5f; // center the values about 0.
+        f *= 0.3f * Math.PI / 2.0f;
+        return (float) Math.sin(f);
+    }
+
+    protected void snapToPageWithVelocity(int whichPage, int velocity) {
+        whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
+        int halfScreenSize = getMeasuredWidth() / 2;
+
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+                + getMeasuredWidth() + ", " + getChildWidth(whichPage));
+        final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+        int delta = newX - mUnboundedScrollX;
+        int duration = 0;
+
+        if (Math.abs(velocity) < mMinFlingVelocity) {
+            // If the velocity is low enough, then treat this more as an automatic page advance
+            // as opposed to an apparent physical response to flinging
+            snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+            return;
+        }
+
+        // Here we compute a "distance" that will be used in the computation of the overall
+        // snap duration. This is a function of the actual distance that needs to be traveled;
+        // we keep this value close to half screen size in order to reduce the variance in snap
+        // duration as a function of the distance the page needs to travel.
+        float distanceRatio = Math.min(1f, 1.0f * Math.abs(delta) / (2 * halfScreenSize));
+        float distance = halfScreenSize + halfScreenSize *
+                distanceInfluenceForSnapDuration(distanceRatio);
+
+        velocity = Math.abs(velocity);
+        velocity = Math.max(mMinSnapVelocity, velocity);
+
+        // we want the page's snap velocity to approximately match the velocity at which the
+        // user flings, so we scale the duration by a value near to the derivative of the scroll
+        // interpolator at zero, ie. 5. We use 4 to make it a little slower.
+        duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
+        duration = Math.min(duration, MAX_PAGE_SNAP_DURATION);
+
+        snapToPage(whichPage, delta, duration);
+    }
+
+    protected void snapToPage(int whichPage) {
+        snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+    }
+
+    protected void snapToPage(int whichPage, int duration) {
+        whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
+
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPage.getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                + getChildWidth(whichPage));
+        int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+        final int sX = mUnboundedScrollX;
+        final int delta = newX - sX;
+        snapToPage(whichPage, delta, duration);
+    }
+
+    protected void snapToPage(int whichPage, int delta, int duration) {
+        mNextPage = whichPage;
+
+        View focusedChild = getFocusedChild();
+        if (focusedChild != null && whichPage != mCurrentPage &&
+                focusedChild == getPageAt(mCurrentPage)) {
+            focusedChild.clearFocus();
+        }
+
+        pageBeginMoving();
+        awakenScrollBars(duration);
+        if (duration == 0) {
+            duration = Math.abs(delta);
+        }
+
+        if (!mScroller.isFinished()) mScroller.abortAnimation();
+        mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
+
+        // Load associated pages immediately if someone else is handling the scroll, otherwise defer
+        // loading associated pages until the scroll settles
+        if (mDeferScrollUpdate) {
+            loadAssociatedPages(mNextPage);
+        } else {
+            mDeferLoadAssociatedPagesUntilScrollCompletes = true;
+        }
+        notifyPageSwitchListener();
+        invalidate();
+    }
+
+    public void scrollLeft() {
+        if (mScroller.isFinished()) {
+            if (mCurrentPage > 0) snapToPage(mCurrentPage - 1);
+        } else {
+            if (mNextPage > 0) snapToPage(mNextPage - 1);
+        }
+    }
+
+    public void scrollRight() {
+        if (mScroller.isFinished()) {
+            if (mCurrentPage < getChildCount() -1) snapToPage(mCurrentPage + 1);
+        } else {
+            if (mNextPage < getChildCount() -1) snapToPage(mNextPage + 1);
+        }
+    }
+
+    public int getPageForView(View v) {
+        int result = -1;
+        if (v != null) {
+            ViewParent vp = v.getParent();
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                if (vp == getPageAt(i)) {
+                    return i;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @return True is long presses are still allowed for the current touch
+     */
+    public boolean allowLongPress() {
+        return mAllowLongPress;
+    }
+
+    /**
+     * Set true to allow long-press events to be triggered, usually checked by
+     * {@link Launcher} to accept or block dpad-initiated long-presses.
+     */
+    public void setAllowLongPress(boolean allowLongPress) {
+        mAllowLongPress = allowLongPress;
+    }
+
+    public static class SavedState extends BaseSavedState {
+        int currentPage = -1;
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            currentPage = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(currentPage);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+    protected void loadAssociatedPages(int page) {
+        loadAssociatedPages(page, false);
+    }
+    protected void loadAssociatedPages(int page, boolean immediateAndOnly) {
+        if (mContentIsRefreshable) {
+            final int count = getChildCount();
+            if (page < count) {
+                int lowerPageBound = getAssociatedLowerPageBound(page);
+                int upperPageBound = getAssociatedUpperPageBound(page);
+                if (DEBUG) Log.d(TAG, "loadAssociatedPages: " + lowerPageBound + "/"
+                        + upperPageBound);
+                // First, clear any pages that should no longer be loaded
+                for (int i = 0; i < count; ++i) {
+                    Page layout = (Page) getPageAt(i);
+                    if ((i < lowerPageBound) || (i > upperPageBound)) {
+                        if (layout.getPageChildCount() > 0) {
+                            layout.removeAllViewsOnPage();
+                        }
+                        mDirtyPageContent.set(i, true);
+                    }
+                }
+                // Next, load any new pages
+                for (int i = 0; i < count; ++i) {
+                    if ((i != page) && immediateAndOnly) {
+                        continue;
+                    }
+                    if (lowerPageBound <= i && i <= upperPageBound) {
+                        if (mDirtyPageContent.get(i)) {
+                            syncPageItems(i, (i == page) && immediateAndOnly);
+                            mDirtyPageContent.set(i, false);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    protected int getAssociatedLowerPageBound(int page) {
+        return Math.max(0, page - 1);
+    }
+    protected int getAssociatedUpperPageBound(int page) {
+        final int count = getChildCount();
+        return Math.min(page + 1, count - 1);
+    }
+
+    /**
+     * This method is called ONLY to synchronize the number of pages that the paged view has.
+     * To actually fill the pages with information, implement syncPageItems() below.  It is
+     * guaranteed that syncPageItems() will be called for a particular page before it is shown,
+     * and therefore, individual page items do not need to be updated in this method.
+     */
+    public abstract void syncPages();
+
+    /**
+     * This method is called to synchronize the items that are on a particular page.  If views on
+     * the page can be reused, then they should be updated within this method.
+     */
+    public abstract void syncPageItems(int page, boolean immediate);
+
+    protected void invalidatePageData() {
+        invalidatePageData(-1, false);
+    }
+    protected void invalidatePageData(int currentPage) {
+        invalidatePageData(currentPage, false);
+    }
+    protected void invalidatePageData(int currentPage, boolean immediateAndOnly) {
+        if (!mIsDataReady) {
+            return;
+        }
+
+        if (mContentIsRefreshable) {
+            // Force all scrolling-related behavior to end
+            mScroller.forceFinished(true);
+            mNextPage = INVALID_PAGE;
+
+            // Update all the pages
+            syncPages();
+
+            // We must force a measure after we've loaded the pages to update the content width and
+            // to determine the full scroll width
+            measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+
+            // Set a new page as the current page if necessary
+            if (currentPage > -1) {
+                setCurrentPage(Math.min(getPageCount() - 1, currentPage));
+            }
+
+            // Mark each of the pages as dirty
+            final int count = getChildCount();
+            mDirtyPageContent.clear();
+            for (int i = 0; i < count; ++i) {
+                mDirtyPageContent.add(true);
+            }
+
+            // Load any pages that are necessary for the current window of views
+            loadAssociatedPages(mCurrentPage, immediateAndOnly);
+            requestLayout();
+        }
+    }
+
+    protected View getScrollingIndicator() {
+        // We use mHasScrollIndicator to prevent future lookups if there is no sibling indicator
+        // found
+        if (mHasScrollIndicator && mScrollIndicator == null) {
+            ViewGroup parent = (ViewGroup) getParent();
+            if (parent != null) {
+                mScrollIndicator = (View) (parent.findViewById(R.id.paged_view_indicator));
+                mHasScrollIndicator = mScrollIndicator != null;
+                if (mHasScrollIndicator) {
+                    mScrollIndicator.setVisibility(View.VISIBLE);
+                }
+            }
+        }
+        return mScrollIndicator;
+    }
+
+    protected boolean isScrollingIndicatorEnabled() {
+        return true;
+    }
+
+    Runnable hideScrollingIndicatorRunnable = new Runnable() {
+        @Override
+        public void run() {
+            hideScrollingIndicator(false);
+        }
+    };
+    protected void flashScrollingIndicator(boolean animated) {
+        removeCallbacks(hideScrollingIndicatorRunnable);
+        showScrollingIndicator(!animated);
+        postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
+    }
+
+    protected void showScrollingIndicator(boolean immediately) {
+        mShouldShowScrollIndicator = true;
+        mShouldShowScrollIndicatorImmediately = true;
+        if (getChildCount() <= 1) return;
+        if (!isScrollingIndicatorEnabled()) return;
+
+        mShouldShowScrollIndicator = false;
+        getScrollingIndicator();
+        if (mScrollIndicator != null) {
+            // Fade the indicator in
+            updateScrollingIndicatorPosition();
+            mScrollIndicator.setVisibility(View.VISIBLE);
+            cancelScrollingIndicatorAnimations();
+            if (immediately || mScrollingPaused) {
+                mScrollIndicator.setAlpha(1f);
+            } else {
+                mScrollIndicatorAnimator = LauncherAnimUtils.ofFloat(mScrollIndicator, "alpha", 1f);
+                mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
+                mScrollIndicatorAnimator.start();
+            }
+        }
+    }
+
+    protected void cancelScrollingIndicatorAnimations() {
+        if (mScrollIndicatorAnimator != null) {
+            mScrollIndicatorAnimator.cancel();
+        }
+    }
+
+    protected void hideScrollingIndicator(boolean immediately) {
+        if (getChildCount() <= 1) return;
+        if (!isScrollingIndicatorEnabled()) return;
+
+        getScrollingIndicator();
+        if (mScrollIndicator != null) {
+            // Fade the indicator out
+            updateScrollingIndicatorPosition();
+            cancelScrollingIndicatorAnimations();
+            if (immediately || mScrollingPaused) {
+                mScrollIndicator.setVisibility(View.INVISIBLE);
+                mScrollIndicator.setAlpha(0f);
+            } else {
+                mScrollIndicatorAnimator = LauncherAnimUtils.ofFloat(mScrollIndicator, "alpha", 0f);
+                mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
+                mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
+                    private boolean cancelled = false;
+                    @Override
+                    public void onAnimationCancel(android.animation.Animator animation) {
+                        cancelled = true;
+                    }
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        if (!cancelled) {
+                            mScrollIndicator.setVisibility(View.INVISIBLE);
+                        }
+                    }
+                });
+                mScrollIndicatorAnimator.start();
+            }
+        }
+    }
+
+    /**
+     * To be overridden by subclasses to determine whether the scroll indicator should stretch to
+     * fill its space on the track or not.
+     */
+    protected boolean hasElasticScrollIndicator() {
+        return true;
+    }
+
+    private void updateScrollingIndicator() {
+        if (getChildCount() <= 1) return;
+        if (!isScrollingIndicatorEnabled()) return;
+
+        getScrollingIndicator();
+        if (mScrollIndicator != null) {
+            updateScrollingIndicatorPosition();
+        }
+        if (mShouldShowScrollIndicator) {
+            showScrollingIndicator(mShouldShowScrollIndicatorImmediately);
+        }
+    }
+
+    private void updateScrollingIndicatorPosition() {
+        if (!isScrollingIndicatorEnabled()) return;
+        if (mScrollIndicator == null) return;
+        int numPages = getChildCount();
+        int pageWidth = getMeasuredWidth();
+        int lastChildIndex = Math.max(0, getChildCount() - 1);
+        int maxScrollX = getChildOffset(lastChildIndex) - getRelativeChildOffset(lastChildIndex);
+        int trackWidth = pageWidth - mScrollIndicatorPaddingLeft - mScrollIndicatorPaddingRight;
+        int indicatorWidth = mScrollIndicator.getMeasuredWidth() -
+                mScrollIndicator.getPaddingLeft() - mScrollIndicator.getPaddingRight();
+
+        float offset = Math.max(0f, Math.min(1f, (float) getScrollX() / maxScrollX));
+        int indicatorSpace = trackWidth / numPages;
+        int indicatorPos = (int) (offset * (trackWidth - indicatorSpace)) + mScrollIndicatorPaddingLeft;
+        if (hasElasticScrollIndicator()) {
+            if (mScrollIndicator.getMeasuredWidth() != indicatorSpace) {
+                mScrollIndicator.getLayoutParams().width = indicatorSpace;
+                mScrollIndicator.requestLayout();
+            }
+        } else {
+            int indicatorCenterOffset = indicatorSpace / 2 - indicatorWidth / 2;
+            indicatorPos += indicatorCenterOffset;
+        }
+        mScrollIndicator.setTranslationX(indicatorPos);
+    }
+
+    public void showScrollIndicatorTrack() {
+    }
+
+    public void hideScrollIndicatorTrack() {
+    }
+
+    /* Accessibility */
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(getPageCount() > 1);
+        if (getCurrentPage() < getPageCount() - 1) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+        }
+        if (getCurrentPage() > 0) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            event.setFromIndex(mCurrentPage);
+            event.setToIndex(mCurrentPage);
+            event.setItemCount(getChildCount());
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                if (getCurrentPage() < getPageCount() - 1) {
+                    scrollRight();
+                    return true;
+                }
+            } break;
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                if (getCurrentPage() > 0) {
+                    scrollLeft();
+                    return true;
+                }
+            } break;
+        }
+        return false;
+    }
+
+    protected String getCurrentPageDescription() {
+        return String.format(getContext().getString(R.string.default_scroll_format),
+                 getNextPage() + 1, getChildCount());
+    }
+
+    @Override
+    public boolean onHoverEvent(android.view.MotionEvent event) {
+        return true;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewCellLayout.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewCellLayout.java
new file mode 100644
index 0000000..9854d8e
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewCellLayout.java
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+
+import org.fairphone.launcher.R;
+
+/**
+ * An abstraction of the original CellLayout which supports laying out items
+ * which span multiple cells into a grid-like layout.  Also supports dimming
+ * to give a preview of its contents.
+ */
+public class PagedViewCellLayout extends ViewGroup implements Page {
+    static final String TAG = "PagedViewCellLayout";
+
+    private int mCellCountX;
+    private int mCellCountY;
+    private int mOriginalCellWidth;
+    private int mOriginalCellHeight;
+    private int mCellWidth;
+    private int mCellHeight;
+    private int mOriginalWidthGap;
+    private int mOriginalHeightGap;
+    private int mWidthGap;
+    private int mHeightGap;
+    private int mMaxGap;
+    protected PagedViewCellLayoutChildren mChildren;
+
+    public PagedViewCellLayout(Context context) {
+        this(context, null);
+    }
+
+    public PagedViewCellLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PagedViewCellLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        setAlwaysDrawnWithCacheEnabled(false);
+
+        // setup default cell parameters
+        Resources resources = context.getResources();
+        mOriginalCellWidth = mCellWidth =
+            resources.getDimensionPixelSize(R.dimen.apps_customize_cell_width);
+        mOriginalCellHeight = mCellHeight =
+            resources.getDimensionPixelSize(R.dimen.apps_customize_cell_height);
+        mCellCountX = LauncherModel.getCellCountX();
+        mCellCountY = LauncherModel.getCellCountY();
+        mOriginalWidthGap = mOriginalHeightGap = mWidthGap = mHeightGap = -1;
+        mMaxGap = resources.getDimensionPixelSize(R.dimen.apps_customize_max_gap);
+
+        mChildren = new PagedViewCellLayoutChildren(context);
+        mChildren.setCellDimensions(mCellWidth, mCellHeight);
+        mChildren.setGap(mWidthGap, mHeightGap);
+
+        addView(mChildren);
+    }
+
+    public int getCellWidth() {
+        return mCellWidth;
+    }
+
+    public int getCellHeight() {
+        return mCellHeight;
+    }
+
+    void destroyHardwareLayers() {
+        // called when a page is no longer visible (triggered by loadAssociatedPages ->
+        // removeAllViewsOnPage)
+        setLayerType(LAYER_TYPE_NONE, null);
+    }
+
+    void createHardwareLayers() {
+        // called when a page is visible (triggered by loadAssociatedPages -> syncPageItems)
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        // Cancel long press for all children
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.cancelLongPress();
+        }
+    }
+
+    public boolean addViewToCellLayout(View child, int index, int childId,
+            PagedViewCellLayout.LayoutParams params) {
+        final PagedViewCellLayout.LayoutParams lp = params;
+
+        // Generate an id for each view, this assumes we have at most 256x256 cells
+        // per workspace screen
+        if (lp.cellX >= 0 && lp.cellX <= (mCellCountX - 1) &&
+                lp.cellY >= 0 && (lp.cellY <= mCellCountY - 1)) {
+            // If the horizontal or vertical span is set to -1, it is taken to
+            // mean that it spans the extent of the CellLayout
+            if (lp.cellHSpan < 0) lp.cellHSpan = mCellCountX;
+            if (lp.cellVSpan < 0) lp.cellVSpan = mCellCountY;
+
+            child.setId(childId);
+            mChildren.addView(child, index, lp);
+
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void removeAllViewsOnPage() {
+        mChildren.removeAllViews();
+        destroyHardwareLayers();
+    }
+
+    @Override
+    public void removeViewOnPageAt(int index) {
+        mChildren.removeViewAt(index);
+    }
+
+    /**
+     * Clears all the key listeners for the individual icons.
+     */
+    public void resetChildrenOnKeyListeners() {
+        int childCount = mChildren.getChildCount();
+        for (int j = 0; j < childCount; ++j) {
+            mChildren.getChildAt(j).setOnKeyListener(null);
+        }
+    }
+
+    @Override
+    public int getPageChildCount() {
+        return mChildren.getChildCount();
+    }
+
+    public PagedViewCellLayoutChildren getChildrenLayout() {
+        return mChildren;
+    }
+
+    @Override
+    public View getChildOnPageAt(int i) {
+        return mChildren.getChildAt(i);
+    }
+
+    @Override
+    public int indexOfChildOnPage(View v) {
+        return mChildren.indexOfChild(v);
+    }
+
+    public int getCellCountX() {
+        return mCellCountX;
+    }
+
+    public int getCellCountY() {
+        return mCellCountY;
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+
+        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
+
+        if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
+            throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
+        }
+
+        int numWidthGaps = mCellCountX - 1;
+        int numHeightGaps = mCellCountY - 1;
+
+        if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
+            int hSpace = widthSpecSize - getPaddingLeft() - getPaddingRight();
+            int vSpace = heightSpecSize - getPaddingTop() - getPaddingBottom();
+            int hFreeSpace = hSpace - (mCellCountX * mOriginalCellWidth);
+            int vFreeSpace = vSpace - (mCellCountY * mOriginalCellHeight);
+            mWidthGap = Math.min(mMaxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
+            mHeightGap = Math.min(mMaxGap,numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
+
+            mChildren.setGap(mWidthGap, mHeightGap);
+        } else {
+            mWidthGap = mOriginalWidthGap;
+            mHeightGap = mOriginalHeightGap;
+        }
+
+        // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
+        int newWidth = widthSpecSize;
+        int newHeight = heightSpecSize;
+        if (widthSpecMode == MeasureSpec.AT_MOST) {
+            newWidth = getPaddingLeft() + getPaddingRight() + (mCellCountX * mCellWidth) +
+                ((mCellCountX - 1) * mWidthGap);
+            newHeight = getPaddingTop() + getPaddingBottom() + (mCellCountY * mCellHeight) +
+                ((mCellCountY - 1) * mHeightGap);
+            setMeasuredDimension(newWidth, newHeight);
+        }
+
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            int childWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(newWidth - getPaddingLeft() -
+                        getPaddingRight(), MeasureSpec.EXACTLY);
+            int childheightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(newHeight - getPaddingTop() -
+                        getPaddingBottom(), MeasureSpec.EXACTLY);
+            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+        }
+
+        setMeasuredDimension(newWidth, newHeight);
+    }
+
+    int getContentWidth() {
+        return getWidthBeforeFirstLayout() + getPaddingLeft() + getPaddingRight();
+    }
+
+    int getContentHeight() {
+        if (mCellCountY > 0) {
+            return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
+        }
+        return 0;
+    }
+
+    int getWidthBeforeFirstLayout() {
+        if (mCellCountX > 0) {
+            return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
+        }
+        return 0;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            child.layout(getPaddingLeft(), getPaddingTop(),
+                r - l - getPaddingRight(), b - t - getPaddingBottom());
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        boolean result = super.onTouchEvent(event);
+        int count = getPageChildCount();
+        if (count > 0) {
+            // We only intercept the touch if we are tapping in empty space after the final row
+            View child = getChildOnPageAt(count - 1);
+            int bottom = child.getBottom();
+            int numRows = (int) Math.ceil((float) getPageChildCount() / getCellCountX());
+            if (numRows < getCellCountY()) {
+                // Add a little bit of buffer if there is room for another row
+                bottom += mCellHeight / 2;
+            }
+            result = result || (event.getY() < bottom);
+        }
+        return result;
+    }
+
+    public void enableCenteredContent(boolean enabled) {
+        mChildren.enableCenteredContent(enabled);
+    }
+
+    @Override
+    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
+        mChildren.setChildrenDrawingCacheEnabled(enabled);
+    }
+
+    public void setCellCount(int xCount, int yCount) {
+        mCellCountX = xCount;
+        mCellCountY = yCount;
+        requestLayout();
+    }
+
+    public void setGap(int widthGap, int heightGap) {
+        mOriginalWidthGap = mWidthGap = widthGap;
+        mOriginalHeightGap = mHeightGap = heightGap;
+        mChildren.setGap(widthGap, heightGap);
+    }
+
+    public int[] getCellCountForDimensions(int width, int height) {
+        // Always assume we're working with the smallest span to make sure we
+        // reserve enough space in both orientations
+        int smallerSize = Math.min(mCellWidth, mCellHeight);
+
+        // Always round up to next largest cell
+        int spanX = (width + smallerSize) / smallerSize;
+        int spanY = (height + smallerSize) / smallerSize;
+
+        return new int[] { spanX, spanY };
+    }
+
+    /**
+     * Start dragging the specified child
+     *
+     * @param child The child that is being dragged
+     */
+    void onDragChild(View child) {
+        PagedViewCellLayout.LayoutParams lp = (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
+        lp.isDragging = true;
+    }
+
+    /**
+     * Estimates the number of cells that the specified width would take up.
+     */
+    public int estimateCellHSpan(int width) {
+        // We don't show the next/previous pages any more, so we use the full width, minus the
+        // padding
+        int availWidth = width - (getPaddingLeft() + getPaddingRight());
+
+        // We know that we have to fit N cells with N-1 width gaps, so we just juggle to solve for N
+        int n = Math.max(1, (availWidth + mWidthGap) / (mCellWidth + mWidthGap));
+
+        // We don't do anything fancy to determine if we squeeze another row in.
+        return n;
+    }
+
+    /**
+     * Estimates the number of cells that the specified height would take up.
+     */
+    public int estimateCellVSpan(int height) {
+        // The space for a page is the height - top padding (current page) - bottom padding (current
+        // page)
+        int availHeight = height - (getPaddingTop() + getPaddingBottom());
+
+        // We know that we have to fit N cells with N-1 height gaps, so we juggle to solve for N
+        int n = Math.max(1, (availHeight + mHeightGap) / (mCellHeight + mHeightGap));
+
+        // We don't do anything fancy to determine if we squeeze another row in.
+        return n;
+    }
+
+    /** Returns an estimated center position of the cell at the specified index */
+    public int[] estimateCellPosition(int x, int y) {
+        return new int[] {
+                getPaddingLeft() + (x * mCellWidth) + (x * mWidthGap) + (mCellWidth / 2),
+                getPaddingTop() + (y * mCellHeight) + (y * mHeightGap) + (mCellHeight / 2)
+        };
+    }
+
+    public void calculateCellCount(int width, int height, int maxCellCountX, int maxCellCountY) {
+        mCellCountX = Math.min(maxCellCountX, estimateCellHSpan(width));
+        mCellCountY = Math.min(maxCellCountY, estimateCellVSpan(height));
+        requestLayout();
+    }
+
+    /**
+     * Estimates the width that the number of hSpan cells will take up.
+     */
+    public int estimateCellWidth(int hSpan) {
+        // TODO: we need to take widthGap into effect
+        return hSpan * mCellWidth;
+    }
+
+    /**
+     * Estimates the height that the number of vSpan cells will take up.
+     */
+    public int estimateCellHeight(int vSpan) {
+        // TODO: we need to take heightGap into effect
+        return vSpan * mCellHeight;
+    }
+
+    @Override
+    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new PagedViewCellLayout.LayoutParams(getContext(), attrs);
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof PagedViewCellLayout.LayoutParams;
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return new PagedViewCellLayout.LayoutParams(p);
+    }
+
+    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
+        /**
+         * Horizontal location of the item in the grid.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellX;
+
+        /**
+         * Vertical location of the item in the grid.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellY;
+
+        /**
+         * Number of cells spanned horizontally by the item.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellHSpan;
+
+        /**
+         * Number of cells spanned vertically by the item.
+         */
+        @ViewDebug.ExportedProperty
+        public int cellVSpan;
+
+        /**
+         * Is this item currently being dragged
+         */
+        public boolean isDragging;
+
+        // a data object that you can bind to this layout params
+        private Object mTag;
+
+        // X coordinate of the view in the layout.
+        @ViewDebug.ExportedProperty
+        int x;
+        // Y coordinate of the view in the layout.
+        @ViewDebug.ExportedProperty
+        int y;
+
+        public LayoutParams() {
+            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+            cellHSpan = 1;
+            cellVSpan = 1;
+        }
+
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+            cellHSpan = 1;
+            cellVSpan = 1;
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+            cellHSpan = 1;
+            cellVSpan = 1;
+        }
+
+        public LayoutParams(LayoutParams source) {
+            super(source);
+            this.cellX = source.cellX;
+            this.cellY = source.cellY;
+            this.cellHSpan = source.cellHSpan;
+            this.cellVSpan = source.cellVSpan;
+        }
+
+        public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
+            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+            this.cellX = cellX;
+            this.cellY = cellY;
+            this.cellHSpan = cellHSpan;
+            this.cellVSpan = cellVSpan;
+        }
+
+        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
+                int hStartPadding, int vStartPadding) {
+
+            final int myCellHSpan = cellHSpan;
+            final int myCellVSpan = cellVSpan;
+            final int myCellX = cellX;
+            final int myCellY = cellY;
+
+            width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
+                    leftMargin - rightMargin;
+            height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
+                    topMargin - bottomMargin;
+
+            if (LauncherApplication.isScreenLarge()) {
+                x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
+                y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+            } else {
+                x = myCellX * (cellWidth + widthGap) + leftMargin;
+                y = myCellY * (cellHeight + heightGap) + topMargin;
+            }
+        }
+
+        public Object getTag() {
+            return mTag;
+        }
+
+        public void setTag(Object tag) {
+            mTag = tag;
+        }
+
+        public String toString() {
+            return "(" + this.cellX + ", " + this.cellY + ", " +
+                this.cellHSpan + ", " + this.cellVSpan + ")";
+        }
+    }
+}
+
+interface Page {
+    public int getPageChildCount();
+    public View getChildOnPageAt(int i);
+    public void removeAllViewsOnPage();
+    public void removeViewOnPageAt(int i);
+    public int indexOfChildOnPage(View v);
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewCellLayoutChildren.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewCellLayoutChildren.java
new file mode 100644
index 0000000..faec1bb
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewCellLayoutChildren.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * An abstraction of the original CellLayout which supports laying out items
+ * which span multiple cells into a grid-like layout.  Also supports dimming
+ * to give a preview of its contents.
+ */
+public class PagedViewCellLayoutChildren extends ViewGroup {
+    static final String TAG = "PagedViewCellLayout";
+
+    private boolean mCenterContent;
+
+    private int mCellWidth;
+    private int mCellHeight;
+    private int mWidthGap;
+    private int mHeightGap;
+
+    public PagedViewCellLayoutChildren(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        // Cancel long press for all children
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.cancelLongPress();
+        }
+    }
+
+    public void setGap(int widthGap, int heightGap) {
+        mWidthGap = widthGap;
+        mHeightGap = heightGap;
+        requestLayout();
+    }
+
+    public void setCellDimensions(int width, int height) {
+        mCellWidth = width;
+        mCellHeight = height;
+        requestLayout();
+    }
+
+    @Override
+    public void requestChildFocus(View child, View focused) {
+        super.requestChildFocus(child, focused);
+        if (child != null) {
+            Rect r = new Rect();
+            child.getDrawingRect(r);
+            requestRectangleOnScreen(r);
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+
+        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
+
+        if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
+            throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
+        }
+
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            PagedViewCellLayout.LayoutParams lp =
+                (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
+            lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
+                    getPaddingLeft(),
+                    getPaddingTop());
+
+            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width,
+                    MeasureSpec.EXACTLY);
+            int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
+                    MeasureSpec.EXACTLY);
+
+            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+        }
+
+        setMeasuredDimension(widthSpecSize, heightSpecSize);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int count = getChildCount();
+
+        int offsetX = 0;
+        if (mCenterContent && count > 0) {
+            // determine the max width of all the rows and center accordingly
+            int maxRowX = 0;
+            int minRowX = Integer.MAX_VALUE;
+            for (int i = 0; i < count; i++) {
+                View child = getChildAt(i);
+                if (child.getVisibility() != GONE) {
+                    PagedViewCellLayout.LayoutParams lp =
+                        (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
+                    minRowX = Math.min(minRowX, lp.x);
+                    maxRowX = Math.max(maxRowX, lp.x + lp.width);
+                }
+            }
+            int maxRowWidth = maxRowX - minRowX;
+            offsetX = (getMeasuredWidth() - maxRowWidth) / 2;
+        }
+
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                PagedViewCellLayout.LayoutParams lp =
+                    (PagedViewCellLayout.LayoutParams) child.getLayoutParams();
+
+                int childLeft = offsetX + lp.x;
+                int childTop = lp.y;
+                child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height);
+            }
+        }
+    }
+
+    public void enableCenteredContent(boolean enabled) {
+        mCenterContent = enabled;
+    }
+
+    @Override
+    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View view = getChildAt(i);
+            view.setDrawingCacheEnabled(enabled);
+            // Update the drawing caches
+            if (!view.isHardwareAccelerated()) {
+                view.buildDrawingCache(true);
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewGridLayout.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewGridLayout.java
new file mode 100644
index 0000000..df4cf9b
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewGridLayout.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.GridLayout;
+
+/**
+ * The grid based layout used strictly for the widget/wallpaper tab of the AppsCustomize pane
+ */
+public class PagedViewGridLayout extends GridLayout implements Page {
+    static final String TAG = "PagedViewGridLayout";
+
+    private int mCellCountX;
+    private int mCellCountY;
+    private Runnable mOnLayoutListener;
+
+    public PagedViewGridLayout(Context context, int cellCountX, int cellCountY) {
+        super(context, null, 0);
+        mCellCountX = cellCountX;
+        mCellCountY = cellCountY;
+    }
+
+    int getCellCountX() {
+        return mCellCountX;
+    }
+
+    int getCellCountY() {
+        return mCellCountY;
+    }
+
+    /**
+     * Clears all the key listeners for the individual widgets.
+     */
+    public void resetChildrenOnKeyListeners() {
+        int childCount = getChildCount();
+        for (int j = 0; j < childCount; ++j) {
+            getChildAt(j).setOnKeyListener(null);
+        }
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // PagedView currently has issues with different-sized pages since it calculates the
+        // offset of each page to scroll to before it updates the actual size of each page
+        // (which can change depending on the content if the contents aren't a fixed size).
+        // We work around this by having a minimum size on each widget page).
+        int widthSpecSize = Math.min(getSuggestedMinimumWidth(),
+                MeasureSpec.getSize(widthMeasureSpec));
+        int widthSpecMode = MeasureSpec.EXACTLY;
+        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
+                heightMeasureSpec);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mOnLayoutListener = null;
+    }
+
+    public void setOnLayoutListener(Runnable r) {
+        mOnLayoutListener = r;
+    }
+
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (mOnLayoutListener != null) {
+            mOnLayoutListener.run();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        boolean result = super.onTouchEvent(event);
+        int count = getPageChildCount();
+        if (count > 0) {
+            // We only intercept the touch if we are tapping in empty space after the final row
+            View child = getChildOnPageAt(count - 1);
+            int bottom = child.getBottom();
+            result = result || (event.getY() < bottom);
+        }
+        return result;
+    }
+
+    void destroyHardwareLayer() {
+        setLayerType(LAYER_TYPE_NONE, null);
+    }
+
+    void createHardwareLayer() {
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+    }
+
+    @Override
+    public void removeAllViewsOnPage() {
+        removeAllViews();
+        mOnLayoutListener = null;
+        destroyHardwareLayer();
+    }
+
+    @Override
+    public void removeViewOnPageAt(int index) {
+        removeViewAt(index);
+    }
+
+    @Override
+    public int getPageChildCount() {
+        return getChildCount();
+    }
+
+    @Override
+    public View getChildOnPageAt(int i) {
+        return getChildAt(i);
+    }
+
+    @Override
+    public int indexOfChildOnPage(View v) {
+        return indexOfChild(v);
+    }
+
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewIcon.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewIcon.java
new file mode 100644
index 0000000..ca46f1c
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewIcon.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * An icon on a PagedView, specifically for items in the launcher's paged view (with compound
+ * drawables on the top).
+ */
+public class PagedViewIcon extends TextView {
+    /** A simple callback interface to allow a PagedViewIcon to notify when it has been pressed */
+    public static interface PressedCallback {
+        void iconPressed(PagedViewIcon icon);
+    }
+
+    @SuppressWarnings("unused")
+    private static final String TAG = "PagedViewIcon";
+    private static final float PRESS_ALPHA = 0.4f;
+
+    private PagedViewIcon.PressedCallback mPressedCallback;
+    private boolean mLockDrawableState = false;
+
+    private Bitmap mIcon;
+
+    public PagedViewIcon(Context context) {
+        this(context, null);
+    }
+
+    public PagedViewIcon(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PagedViewIcon(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void applyFromApplicationInfo(ApplicationInfo info, boolean scaleUp,
+            PagedViewIcon.PressedCallback cb) {
+        mIcon = info.iconBitmap;
+        mPressedCallback = cb;
+        setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
+        setText(info.title);
+        setTag(info);
+    }
+
+    public void lockDrawableState() {
+        mLockDrawableState = true;
+    }
+
+    public void resetDrawableState() {
+        mLockDrawableState = false;
+        post(new Runnable() {
+            @Override
+            public void run() {
+                refreshDrawableState();
+            }
+        });
+    }
+
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+
+        // We keep in the pressed state until resetDrawableState() is called to reset the press
+        // feedback
+        if (isPressed()) {
+            setAlpha(PRESS_ALPHA);
+            if (mPressedCallback != null) {
+                mPressedCallback.iconPressed(this);
+            }
+        } else if (!mLockDrawableState) {
+            setAlpha(1f);
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewIconCache.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewIconCache.java
new file mode 100644
index 0000000..33387ae
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewIconCache.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.pm.ComponentInfo;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+
+/**
+ * Simple cache mechanism for PagedView outlines.
+ */
+public class PagedViewIconCache {
+    public static class Key {
+        public enum Type {
+            ApplicationInfoKey,
+            AppWidgetProviderInfoKey,
+            ResolveInfoKey
+        }
+        private final ComponentName mComponentName;
+        private final Type mType;
+
+        public Key(ApplicationInfo info) {
+            mComponentName = info.componentName;
+            mType = Type.ApplicationInfoKey;
+        }
+        public Key(ResolveInfo info) {
+            final ComponentInfo ci = info.activityInfo != null ? info.activityInfo :
+                info.serviceInfo;
+            mComponentName = new ComponentName(ci.packageName, ci.name);
+            mType = Type.ResolveInfoKey;
+        }
+        public Key(AppWidgetProviderInfo info) {
+            mComponentName = info.provider;
+            mType = Type.AppWidgetProviderInfoKey;
+        }
+
+        private ComponentName getComponentName() {
+            return mComponentName;
+        }
+        public boolean isKeyType(Type t) {
+            return (mType == t);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof Key) {
+                Key k = (Key) o;
+                return mComponentName.equals(k.mComponentName);
+            }
+            return super.equals(o);
+        }
+        @Override
+        public int hashCode() {
+            return getComponentName().hashCode();
+        }
+    }
+
+    private final HashMap<Key, Bitmap> mIconOutlineCache = new HashMap<Key, Bitmap>();
+
+    public void clear() {
+        for (Key key : mIconOutlineCache.keySet()) {
+            mIconOutlineCache.get(key).recycle();
+        }
+        mIconOutlineCache.clear();
+    }
+    private void retainAll(HashSet<Key> keysToKeep, Key.Type t) {
+        HashSet<Key> keysToRemove = new HashSet<Key>(mIconOutlineCache.keySet());
+        keysToRemove.removeAll(keysToKeep);
+        for (Key key : keysToRemove) {
+            if (key.isKeyType(t)) {
+                mIconOutlineCache.get(key).recycle();
+                mIconOutlineCache.remove(key);
+            }
+        }
+    }
+    /** Removes all the keys to applications that aren't in the passed in collection */
+    public void retainAllApps(ArrayList<ApplicationInfo> keys) {
+        HashSet<Key> keysSet = new HashSet<Key>();
+        for (ApplicationInfo info : keys) {
+            keysSet.add(new Key(info));
+        }
+        retainAll(keysSet, Key.Type.ApplicationInfoKey);
+    }
+    /** Removes all the keys to shortcuts that aren't in the passed in collection */
+    public void retainAllShortcuts(List<ResolveInfo> keys) {
+        HashSet<Key> keysSet = new HashSet<Key>();
+        for (ResolveInfo info : keys) {
+            keysSet.add(new Key(info));
+        }
+        retainAll(keysSet, Key.Type.ResolveInfoKey);
+    }
+    /** Removes all the keys to widgets that aren't in the passed in collection */
+    public void retainAllAppWidgets(List<AppWidgetProviderInfo> keys) {
+        HashSet<Key> keysSet = new HashSet<Key>();
+        for (AppWidgetProviderInfo info : keys) {
+            keysSet.add(new Key(info));
+        }
+        retainAll(keysSet, Key.Type.AppWidgetProviderInfoKey);
+    }
+    public void addOutline(Key key, Bitmap b) {
+        mIconOutlineCache.put(key, b);
+    }
+    public void removeOutline(Key key) {
+        if (mIconOutlineCache.containsKey(key)) {
+            mIconOutlineCache.get(key).recycle();
+            mIconOutlineCache.remove(key);
+        }
+    }
+    public Bitmap getOutline(Key key) {
+        return mIconOutlineCache.get(key);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewWidget.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewWidget.java
new file mode 100644
index 0000000..68535ff
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewWidget.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+/**
+ * The linear layout used strictly for the widget/wallpaper tab of the customization tray
+ */
+public class PagedViewWidget extends LinearLayout {
+    static final String TAG = "PagedViewWidgetLayout";
+
+    private static boolean sDeletePreviewsWhenDetachedFromWindow = true;
+
+    private String mDimensionsFormatString;
+    CheckForShortPress mPendingCheckForShortPress = null;
+    ShortPressListener mShortPressListener = null;
+    boolean mShortPressTriggered = false;
+    static PagedViewWidget sShortpressTarget = null;
+    boolean mIsAppWidget;
+    private final Rect mOriginalImagePadding = new Rect();
+
+    public PagedViewWidget(Context context) {
+        this(context, null);
+    }
+
+    public PagedViewWidget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PagedViewWidget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        final Resources r = context.getResources();
+        mDimensionsFormatString = r.getString(R.string.widget_dims_format);
+
+        setWillNotDraw(false);
+        setClipToPadding(false);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        final ImageView image = (ImageView) findViewById(R.id.widget_preview);
+        mOriginalImagePadding.left = image.getPaddingLeft();
+        mOriginalImagePadding.top = image.getPaddingTop();
+        mOriginalImagePadding.right = image.getPaddingRight();
+        mOriginalImagePadding.bottom = image.getPaddingBottom();
+    }
+
+    public static void setDeletePreviewsWhenDetachedFromWindow(boolean value) {
+        sDeletePreviewsWhenDetachedFromWindow = value;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        if (sDeletePreviewsWhenDetachedFromWindow) {
+            final ImageView image = (ImageView) findViewById(R.id.widget_preview);
+            if (image != null) {
+                FastBitmapDrawable preview = (FastBitmapDrawable) image.getDrawable();
+                if (preview != null && preview.getBitmap() != null) {
+                    preview.getBitmap().recycle();
+                }
+                image.setImageDrawable(null);
+            }
+        }
+    }
+
+    public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info,
+            int maxWidth, int[] cellSpan) {
+        mIsAppWidget = true;
+        final ImageView image = (ImageView) findViewById(R.id.widget_preview);
+        if (maxWidth > -1) {
+            image.setMaxWidth(maxWidth);
+        }
+        image.setContentDescription(info.label);
+        final TextView name = (TextView) findViewById(R.id.widget_name);
+        name.setText(info.label);
+        final TextView dims = (TextView) findViewById(R.id.widget_dims);
+        if (dims != null) {
+            int hSpan = Math.min(cellSpan[0], LauncherModel.getCellCountX());
+            int vSpan = Math.min(cellSpan[1], LauncherModel.getCellCountY());
+            dims.setText(String.format(mDimensionsFormatString, hSpan, vSpan));
+        }
+    }
+
+    public void applyFromResolveInfo(PackageManager pm, ResolveInfo info) {
+        mIsAppWidget = false;
+        CharSequence label = info.loadLabel(pm);
+        final ImageView image = (ImageView) findViewById(R.id.widget_preview);
+        image.setContentDescription(label);
+        final TextView name = (TextView) findViewById(R.id.widget_name);
+        name.setText(label);
+        final TextView dims = (TextView) findViewById(R.id.widget_dims);
+        if (dims != null) {
+            dims.setText(String.format(mDimensionsFormatString, 1, 1));
+        }
+    }
+
+    public int[] getPreviewSize() {
+        final ImageView i = (ImageView) findViewById(R.id.widget_preview);
+        int[] maxSize = new int[2];
+        maxSize[0] = i.getWidth() - mOriginalImagePadding.left - mOriginalImagePadding.right;
+        maxSize[1] = i.getHeight() - mOriginalImagePadding.top;
+        return maxSize;
+    }
+
+    void applyPreview(FastBitmapDrawable preview, int index) {
+        final PagedViewWidgetImageView image =
+            (PagedViewWidgetImageView) findViewById(R.id.widget_preview);
+        if (preview != null) {
+            image.mAllowRequestLayout = false;
+            image.setImageDrawable(preview);
+            if (mIsAppWidget) {
+                // center horizontally
+                int[] imageSize = getPreviewSize();
+                int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2;
+                image.setPadding(mOriginalImagePadding.left + centerAmount,
+                        mOriginalImagePadding.top,
+                        mOriginalImagePadding.right,
+                        mOriginalImagePadding.bottom);
+            }
+            image.setAlpha(1f);
+            image.mAllowRequestLayout = true;
+        }
+    }
+
+    void setShortPressListener(ShortPressListener listener) {
+        mShortPressListener = listener;
+    }
+
+    interface ShortPressListener {
+        void onShortPress(View v);
+        void cleanUpShortPress(View v);
+    }
+
+    class CheckForShortPress implements Runnable {
+        public void run() {
+            if (sShortpressTarget != null) return;
+            if (mShortPressListener != null) {
+                mShortPressListener.onShortPress(PagedViewWidget.this);
+                sShortpressTarget = PagedViewWidget.this;
+            }
+            mShortPressTriggered = true;
+        }
+    }
+
+    private void checkForShortPress() {
+        if (sShortpressTarget != null) return;
+        if (mPendingCheckForShortPress == null) {
+            mPendingCheckForShortPress = new CheckForShortPress();
+        }
+        postDelayed(mPendingCheckForShortPress, 120);
+    }
+
+    /**
+     * Remove the longpress detection timer.
+     */
+    private void removeShortPressCallback() {
+        if (mPendingCheckForShortPress != null) {
+          removeCallbacks(mPendingCheckForShortPress);
+        }
+    }
+
+    private void cleanUpShortPress() {
+        removeShortPressCallback();
+        if (mShortPressTriggered) {
+            if (mShortPressListener != null) {
+                mShortPressListener.cleanUpShortPress(PagedViewWidget.this);
+            }
+            mShortPressTriggered = false;
+        }
+    }
+
+    static void resetShortPressTarget() {
+        sShortpressTarget = null;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        super.onTouchEvent(event);
+
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_UP:
+                cleanUpShortPress();
+                break;
+            case MotionEvent.ACTION_DOWN:
+                checkForShortPress();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                cleanUpShortPress();
+                break;
+            case MotionEvent.ACTION_MOVE:
+                break;
+        }
+
+        // We eat up the touch events here, since the PagedView (which uses the same swiping
+        // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when
+        // the user is scrolling between pages.  This means that if the pages themselves don't
+        // handle touch events, it gets forwarded up to PagedView itself, and it's own
+        // onTouchEvent() handling will prevent further intercept touch events from being called
+        // (it's the same view in that case).  This is not ideal, but to prevent more changes,
+        // we just always mark the touch event as handled.
+        return true;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewWidgetImageView.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewWidgetImageView.java
new file mode 100644
index 0000000..a495223
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewWidgetImageView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+class PagedViewWidgetImageView extends ImageView {
+    public boolean mAllowRequestLayout = true;
+
+    public PagedViewWidgetImageView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void requestLayout() {
+        if (mAllowRequestLayout) {
+            super.requestLayout();
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.save();
+        canvas.clipRect(getScrollX() + getPaddingLeft(),
+                getScrollY() + getPaddingTop(),
+                getScrollX() + getRight() - getLeft() - getPaddingRight(),
+                getScrollY() + getBottom() - getTop() - getPaddingBottom());
+
+        super.onDraw(canvas);
+        canvas.restore();
+
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PagedViewWithDraggableItems.java b/FairphoneHome/src/org/fairphone/launcher/PagedViewWithDraggableItems.java
new file mode 100644
index 0000000..18872cf
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PagedViewWithDraggableItems.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+
+/* Class that does most of the work of enabling dragging items out of a PagedView by performing a
+ * vertical drag. Used by both CustomizePagedView and AllAppsPagedView.
+ * Subclasses must do the following:
+ *   * call setDragSlopeThreshold after making an instance of the PagedViewWithDraggableItems
+ *   * call child.setOnLongClickListener(this) and child.setOnTouchListener(this) on all children
+ *       (good place to do it is in syncPageItems)
+ *   * override beginDragging(View) (but be careful to call super.beginDragging(View)
+ *
+ */
+public abstract class PagedViewWithDraggableItems extends PagedView
+    implements View.OnLongClickListener, View.OnTouchListener {
+    private View mLastTouchedItem;
+    private boolean mIsDragging;
+    private boolean mIsDragEnabled;
+    private float mDragSlopeThreshold;
+    private Launcher mLauncher;
+
+    public PagedViewWithDraggableItems(Context context) {
+        this(context, null);
+    }
+
+    public PagedViewWithDraggableItems(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PagedViewWithDraggableItems(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mLauncher = (Launcher) context;
+    }
+
+    protected boolean beginDragging(View v) {
+        boolean wasDragging = mIsDragging;
+        mIsDragging = true;
+        return !wasDragging;
+    }
+
+    protected void cancelDragging() {
+        mIsDragging = false;
+        mLastTouchedItem = null;
+        mIsDragEnabled = false;
+    }
+
+    private void handleTouchEvent(MotionEvent ev) {
+        final int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                cancelDragging();
+                mIsDragEnabled = true;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging && mIsDragEnabled) {
+                    determineDraggingStart(ev);
+                }
+                break;
+        }
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        handleTouchEvent(ev);
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        handleTouchEvent(ev);
+        return super.onTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        mLastTouchedItem = v;
+        mIsDragEnabled = true;
+        return false;
+    }
+
+    @Override
+    public boolean onLongClick(View v) {
+        // Return early if this is not initiated from a touch
+        if (!v.isInTouchMode()) return false;
+        // Return early if we are still animating the pages
+        if (mNextPage != INVALID_PAGE) return false;
+        // When we have exited all apps or are in transition, disregard long clicks
+        if (!mLauncher.isAllAppsVisible() ||
+                mLauncher.getWorkspace().isSwitchingState()) return false;
+        // Return if global dragging is not enabled
+        if (!mLauncher.isDraggingEnabled()) return false;
+
+        return beginDragging(v);
+    }
+
+    /*
+     * Determines if we should change the touch state to start scrolling after the
+     * user moves their touch point too far.
+     */
+    protected void determineScrollingStart(MotionEvent ev) {
+        if (!mIsDragging) super.determineScrollingStart(ev);
+    }
+
+    /*
+     * Determines if we should change the touch state to start dragging after the
+     * user moves their touch point far enough.
+     */
+    protected void determineDraggingStart(MotionEvent ev) {
+        /*
+         * Locally do absolute value. mLastMotionX is set to the y value
+         * of the down event.
+         */
+        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        final float x = ev.getX(pointerIndex);
+        final float y = ev.getY(pointerIndex);
+        final int xDiff = (int) Math.abs(x - mLastMotionX);
+        final int yDiff = (int) Math.abs(y - mLastMotionY);
+
+        final int touchSlop = mTouchSlop;
+        boolean yMoved = yDiff > touchSlop;
+        boolean isUpwardMotion = (yDiff / (float) xDiff) > mDragSlopeThreshold;
+
+        if (isUpwardMotion && yMoved && mLastTouchedItem != null) {
+            // Drag if the user moved far enough along the Y axis
+            beginDragging(mLastTouchedItem);
+
+            // Cancel any pending long press
+            if (mAllowLongPress) {
+                mAllowLongPress = false;
+                // Try canceling the long press. It could also have been scheduled
+                // by a distant descendant, so use the mAllowLongPress flag to block
+                // everything
+                final View currentPage = getPageAt(mCurrentPage);
+                if (currentPage != null) {
+                    currentPage.cancelLongPress();
+                }
+            }
+        }
+    }
+
+    public void setDragSlopeThreshold(float dragSlopeThreshold) {
+        mDragSlopeThreshold = dragSlopeThreshold;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        cancelDragging();
+        super.onDetachedFromWindow();
+    }
+
+    /** Show the scrolling indicators when we move the page */
+    protected void onPageBeginMoving() {
+        showScrollingIndicator(false);
+    }
+    protected void onPageEndMoving() {
+        hideScrollingIndicator(false);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PendingAddItemInfo.java b/FairphoneHome/src/org/fairphone/launcher/PendingAddItemInfo.java
new file mode 100644
index 0000000..ce4d842
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PendingAddItemInfo.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.os.Bundle;
+import android.os.Parcelable;
+
+/**
+ * We pass this object with a drag from the customization tray
+ */
+class PendingAddItemInfo extends ItemInfo {
+    /**
+     * The component that will be created.
+     */
+    ComponentName componentName;
+}
+
+class PendingAddShortcutInfo extends PendingAddItemInfo {
+
+    ActivityInfo shortcutActivityInfo;
+
+    public PendingAddShortcutInfo(ActivityInfo activityInfo) {
+        shortcutActivityInfo = activityInfo;
+    }
+
+    @Override
+    public String toString() {
+        return "Shortcut: " + shortcutActivityInfo.packageName;
+    }
+}
+
+class PendingAddWidgetInfo extends PendingAddItemInfo {
+    int minWidth;
+    int minHeight;
+    int minResizeWidth;
+    int minResizeHeight;
+    int previewImage;
+    int icon;
+    AppWidgetProviderInfo info;
+    AppWidgetHostView boundWidget;
+    Bundle bindOptions = null;
+
+    // Any configuration data that we want to pass to a configuration activity when
+    // starting up a widget
+    String mimeType;
+    Parcelable configurationData;
+
+    public PendingAddWidgetInfo(AppWidgetProviderInfo i, String dataMimeType, Parcelable data) {
+        itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+        this.info = i;
+        componentName = i.provider;
+        minWidth = i.minWidth;
+        minHeight = i.minHeight;
+        minResizeWidth = i.minResizeWidth;
+        minResizeHeight = i.minResizeHeight;
+        previewImage = i.previewImage;
+        icon = i.icon;
+        if (dataMimeType != null && data != null) {
+            mimeType = dataMimeType;
+            configurationData = data;
+        }
+    }
+
+    // Copy constructor
+    public PendingAddWidgetInfo(PendingAddWidgetInfo copy) {
+        minWidth = copy.minWidth;
+        minHeight = copy.minHeight;
+        minResizeWidth = copy.minResizeWidth;
+        minResizeHeight = copy.minResizeHeight;
+        previewImage = copy.previewImage;
+        icon = copy.icon;
+        info = copy.info;
+        boundWidget = copy.boundWidget;
+        mimeType = copy.mimeType;
+        configurationData = copy.configurationData;
+        componentName = copy.componentName;
+        itemType = copy.itemType;
+        spanX = copy.spanX;
+        spanY = copy.spanY;
+        minSpanX = copy.minSpanX;
+        minSpanY = copy.minSpanY;
+        bindOptions = copy.bindOptions == null ? null : (Bundle) copy.bindOptions.clone();
+    }
+
+    @Override
+    public String toString() {
+        return "Widget: " + componentName.toShortString();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/PreloadReceiver.java b/FairphoneHome/src/org/fairphone/launcher/PreloadReceiver.java
new file mode 100644
index 0000000..30c46ae
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/PreloadReceiver.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class PreloadReceiver extends BroadcastReceiver {
+    private static final String TAG = "Launcher.PreloadReceiver";
+    private static final boolean LOGD = false;
+
+    public static final String EXTRA_WORKSPACE_NAME =
+            "com.android.launcher.action.EXTRA_WORKSPACE_NAME";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+        final LauncherProvider provider = app.getLauncherProvider();
+        if (provider != null) {
+            String name = intent.getStringExtra(EXTRA_WORKSPACE_NAME);
+            final int workspaceResId = !TextUtils.isEmpty(name)
+                    ? context.getResources().getIdentifier(name, "xml", "com.android.launcher") : 0;
+            if (LOGD) {
+                Log.d(TAG, "workspace name: " + name + " id: " + workspaceResId);
+            }
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    provider.loadDefaultFavoritesIfNecessary(workspaceResId);
+                }
+            }).start();
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/SearchDropTargetBar.java b/FairphoneHome/src/org/fairphone/launcher/SearchDropTargetBar.java
new file mode 100644
index 0000000..64033b0
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/SearchDropTargetBar.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.FrameLayout;
+
+import org.fairphone.launcher.R;
+
+/*
+ * This bar will manage the transition between the QSB search bar and the delete drop
+ * targets so that each of the individual IconDropTargets don't have to.
+ * 
+ * Fairphone Changes: Removed the entire quick searchBar but left the correct animations for widget
+ * removal.
+ */
+public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
+
+    private static final int sTransitionInDuration = 200;
+    private static final int sTransitionOutDuration = 175;
+
+    private ObjectAnimator mDropTargetBarAnim;
+    private static final AccelerateInterpolator sAccelerateInterpolator =
+            new AccelerateInterpolator();
+
+    private View mDropTargetBar;
+    private ButtonDropTarget mInfoDropTarget;
+    private ButtonDropTarget mDeleteDropTarget;
+    private int mBarHeight;
+    private boolean mDeferOnDragEnd = false;
+
+    private Drawable mPreviousBackground;
+    private boolean mEnableDropDownDropTargets;
+
+    public SearchDropTargetBar(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setup(Launcher launcher, DragController dragController) {
+        dragController.addDragListener(this);
+        dragController.addDragListener(mInfoDropTarget);
+        dragController.addDragListener(mDeleteDropTarget);
+        dragController.addDropTarget(mInfoDropTarget);
+        dragController.addDropTarget(mDeleteDropTarget);
+        dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
+        mInfoDropTarget.setLauncher(launcher);
+        mDeleteDropTarget.setLauncher(launcher);
+    }
+
+    private void prepareStartAnimation(View v) {
+        // Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd
+        // callback below)
+        v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        v.buildLayer();
+    }
+
+    private void setupAnimation(ObjectAnimator anim, final View v) {
+        anim.setInterpolator(sAccelerateInterpolator);
+        anim.setDuration(sTransitionInDuration);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                v.setLayerType(View.LAYER_TYPE_NONE, null);
+            }
+        });
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the individual components
+        mDropTargetBar = findViewById(R.id.drag_target_bar);
+        mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target_text);
+        mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target_text);
+        mBarHeight = getResources().getDimensionPixelSize(R.dimen.qsb_bar_height);
+
+        mInfoDropTarget.setSearchDropTargetBar(this);
+        mDeleteDropTarget.setSearchDropTargetBar(this);
+
+        mEnableDropDownDropTargets =
+            getResources().getBoolean(R.bool.config_useDropTargetDownTransition);
+
+        // Create the various fade animations
+        if (mEnableDropDownDropTargets) {
+            mDropTargetBar.setTranslationY(-mBarHeight);
+            mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "translationY",
+                    -mBarHeight, 0f);
+        } else {
+            mDropTargetBar.setAlpha(0f);
+            mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
+        }
+        setupAnimation(mDropTargetBarAnim, mDropTargetBar);
+    }
+
+    public void finishAnimations() {
+        prepareStartAnimation(mDropTargetBar);
+        mDropTargetBarAnim.reverse();
+    }
+
+
+    /*
+     * Gets various transition durations.
+     */
+    public int getTransitionInDuration() {
+        return sTransitionInDuration;
+    }
+    public int getTransitionOutDuration() {
+        return sTransitionOutDuration;
+    }
+
+    /*
+     * DragController.DragListener implementation
+     */
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        // Animate out the QSB search bar, and animate in the drop target bar
+        prepareStartAnimation(mDropTargetBar);
+        mDropTargetBarAnim.start();
+    }
+
+    public void deferOnDragEnd() {
+        mDeferOnDragEnd = true;
+    }
+
+    @Override
+    public void onDragEnd() {
+        if (!mDeferOnDragEnd) {
+            // Restore the QSB search bar, and animate out the drop target bar
+            prepareStartAnimation(mDropTargetBar);
+            mDropTargetBarAnim.reverse();
+        } else {
+            mDeferOnDragEnd = false;
+        }
+    }
+
+
+    public Rect getSearchBarBounds() {
+            return null;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/ShortcutAndWidgetContainer.java b/FairphoneHome/src/org/fairphone/launcher/ShortcutAndWidgetContainer.java
new file mode 100644
index 0000000..49acf5b
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/ShortcutAndWidgetContainer.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ShortcutAndWidgetContainer extends ViewGroup {
+    static final String TAG = "CellLayoutChildren";
+
+    // These are temporary variables to prevent having to allocate a new object just to
+    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
+    private final int[] mTmpCellXY = new int[2];
+
+    private final WallpaperManager mWallpaperManager;
+
+    private int mCellWidth;
+    private int mCellHeight;
+
+    private int mWidthGap;
+    private int mHeightGap;
+
+    public ShortcutAndWidgetContainer(Context context) {
+        super(context);
+        mWallpaperManager = WallpaperManager.getInstance(context);
+    }
+
+    public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap ) {
+        mCellWidth = cellWidth;
+        mCellHeight = cellHeight;
+        mWidthGap = widthGap;
+        mHeightGap = heightGap;
+    }
+
+    public View getChildAt(int x, int y) {
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+            if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) &&
+                    (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        @SuppressWarnings("all") // suppress dead code warning
+        final boolean debug = false;
+        if (debug) {
+            // Debug drawing for hit space
+            Paint p = new Paint();
+            p.setColor(0x6600FF00);
+            for (int i = getChildCount() - 1; i >= 0; i--) {
+                final View child = getChildAt(i);
+                final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+                canvas.drawRect(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height, p);
+            }
+        }
+        super.dispatchDraw(canvas);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            measureChild(child);
+        }
+        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
+        setMeasuredDimension(widthSpecSize, heightSpecSize);
+    }
+
+    public void setupLp(CellLayout.LayoutParams lp) {
+        lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
+    }
+
+    public void measureChild(View child) {
+        final int cellWidth = mCellWidth;
+        final int cellHeight = mCellHeight;
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+        lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap);
+        int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+        int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
+                MeasureSpec.EXACTLY);
+        child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+                int childLeft = lp.x;
+                int childTop = lp.y;
+                child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height);
+
+                if (lp.dropped) {
+                    lp.dropped = false;
+
+                    final int[] cellXY = mTmpCellXY;
+                    getLocationOnScreen(cellXY);
+                    mWallpaperManager.sendWallpaperCommand(getWindowToken(),
+                            WallpaperManager.COMMAND_DROP,
+                            cellXY[0] + childLeft + lp.width / 2,
+                            cellXY[1] + childTop + lp.height / 2, 0, null);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
+    @Override
+    public void requestChildFocus(View child, View focused) {
+        super.requestChildFocus(child, focused);
+        if (child != null) {
+            Rect r = new Rect();
+            child.getDrawingRect(r);
+            requestRectangleOnScreen(r);
+        }
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        // Cancel long press for all children
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.cancelLongPress();
+        }
+    }
+
+    @Override
+    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View view = getChildAt(i);
+            view.setDrawingCacheEnabled(enabled);
+            // Update the drawing caches
+            if (!view.isHardwareAccelerated() && enabled) {
+                view.buildDrawingCache(true);
+            }
+        }
+    }
+
+    @Override
+    protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
+        super.setChildrenDrawnWithCacheEnabled(enabled);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/ShortcutInfo.java b/FairphoneHome/src/org/fairphone/launcher/ShortcutInfo.java
new file mode 100644
index 0000000..9d9112b
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/ShortcutInfo.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.ArrayList;
+
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.util.Log;
+
+/**
+ * Represents a launchable icon on the workspaces and in folders.
+ */
+class ShortcutInfo extends ItemInfo {
+
+    /**
+     * The intent used to start the application.
+     */
+    Intent intent;
+
+    /**
+     * Indicates whether the icon comes from an application's resource (if false)
+     * or from a custom Bitmap (if true.)
+     */
+    boolean customIcon;
+
+    /**
+     * Indicates whether we're using the default fallback icon instead of something from the
+     * app.
+     */
+    boolean usingFallbackIcon;
+
+    /**
+     * If isShortcut=true and customIcon=false, this contains a reference to the
+     * shortcut icon as an application's resource.
+     */
+    Intent.ShortcutIconResource iconResource;
+
+    /**
+     * The application icon.
+     */
+    private Bitmap mIcon;
+
+    ShortcutInfo() {
+        itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
+    }
+    
+    public ShortcutInfo(ShortcutInfo info) {
+        super(info);
+        title = info.title.toString();
+        intent = new Intent(info.intent);
+        if (info.iconResource != null) {
+            iconResource = new Intent.ShortcutIconResource();
+            iconResource.packageName = info.iconResource.packageName;
+            iconResource.resourceName = info.iconResource.resourceName;
+        }
+        mIcon = info.mIcon; // TODO: should make a copy here.  maybe we don't need this ctor at all
+        customIcon = info.customIcon;
+    }
+
+    /** TODO: Remove this.  It's only called by ApplicationInfo.makeShortcut. */
+    public ShortcutInfo(ApplicationInfo info) {
+        super(info);
+        title = info.title.toString();
+        intent = new Intent(info.intent);
+        customIcon = false;
+    }
+
+    public void setIcon(Bitmap b) {
+        mIcon = b;
+    }
+
+    public Bitmap getIcon(IconCache iconCache) {
+        if (mIcon == null) {
+            updateIcon(iconCache);
+        }
+        return mIcon;
+    }
+
+    /** Returns the package name that the shortcut's intent will resolve to, or an empty string if
+     *  none exists. */
+    String getPackageName() {
+        return super.getPackageName(intent);
+    }
+
+    public void updateIcon(IconCache iconCache) {
+        mIcon = iconCache.getIcon(intent);
+        usingFallbackIcon = iconCache.isDefaultIcon(mIcon);
+    }
+
+    /**
+     * Creates the application intent based on a component name and various launch flags.
+     * Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
+     *
+     * @param className the class name of the component representing the intent
+     * @param launchFlags the launch flags
+     */
+    final void setActivity(ComponentName className, int launchFlags) {
+        intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setComponent(className);
+        intent.setFlags(launchFlags);
+        itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
+    }
+
+    @Override
+    void onAddToDatabase(ContentValues values) {
+        super.onAddToDatabase(values);
+
+        String titleStr = title != null ? title.toString() : null;
+        values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
+
+        String uri = intent != null ? intent.toUri(0) : null;
+        values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
+
+        if (customIcon) {
+            values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
+                    LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
+            writeBitmap(values, mIcon);
+        } else {
+            if (!usingFallbackIcon) {
+                writeBitmap(values, mIcon);
+            }
+            values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
+                    LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
+            if (iconResource != null) {
+                values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE,
+                        iconResource.packageName);
+                values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
+                        iconResource.resourceName);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ShortcutInfo(title=" + title.toString() + "intent=" + intent + "id=" + this.id
+                + " type=" + this.itemType + " container=" + this.container + " screen=" + screen
+                + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY
+                + " dropPos=" + dropPos + ")";
+    }
+
+    public static void dumpShortcutInfoList(String tag, String label,
+            ArrayList<ShortcutInfo> list) {
+        Log.d(tag, label + " size=" + list.size());
+        for (ShortcutInfo info: list) {
+            Log.d(tag, "   title=\"" + info.title + " icon=" + info.mIcon
+                    + " customIcon=" + info.customIcon);
+        }
+    }
+}
+
diff --git a/FairphoneHome/src/org/fairphone/launcher/SmoothPagedView.java b/FairphoneHome/src/org/fairphone/launcher/SmoothPagedView.java
new file mode 100644
index 0000000..96a3191
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/SmoothPagedView.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+public abstract class SmoothPagedView extends PagedView {
+    private static final float SMOOTHING_SPEED = 0.75f;
+    private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
+
+    private float mBaseLineFlingVelocity;
+    private float mFlingVelocityInfluence;
+
+    static final int DEFAULT_MODE = 0;
+    static final int X_LARGE_MODE = 1;
+
+    int mScrollMode;
+
+    private Interpolator mScrollInterpolator;
+
+    public static class OvershootInterpolator implements Interpolator {
+        private static final float DEFAULT_TENSION = 1.3f;
+        private float mTension;
+
+        public OvershootInterpolator() {
+            mTension = DEFAULT_TENSION;
+        }
+
+        public void setDistance(int distance) {
+            mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION;
+        }
+
+        public void disableSettle() {
+            mTension = 0.f;
+        }
+
+        public float getInterpolation(float t) {
+            // _o(t) = t * t * ((tension + 1) * t + tension)
+            // o(t) = _o(t - 1) + 1
+            t -= 1.0f;
+            return t * t * ((mTension + 1) * t + mTension) + 1.0f;
+        }
+    }
+
+    /**
+     * Used to inflate the Workspace from XML.
+     *
+     * @param context The application's context.
+     * @param attrs The attributes set containing the Workspace's customization values.
+     */
+    public SmoothPagedView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * Used to inflate the Workspace from XML.
+     *
+     * @param context The application's context.
+     * @param attrs The attributes set containing the Workspace's customization values.
+     * @param defStyle Unused.
+     */
+    public SmoothPagedView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        mUsePagingTouchSlop = false;
+
+        // This means that we'll take care of updating the scroll parameter ourselves (we do it
+        // in computeScroll), we only do this in the OVERSHOOT_MODE, ie. on phones
+        mDeferScrollUpdate = mScrollMode != X_LARGE_MODE;
+    }
+
+    protected int getScrollMode() {
+        return X_LARGE_MODE;
+    }
+
+    /**
+     * Initializes various states for this workspace.
+     */
+    @Override
+    protected void init() {
+        super.init();
+
+        mScrollMode = getScrollMode();
+        if (mScrollMode == DEFAULT_MODE) {
+            mBaseLineFlingVelocity = 2500.0f;
+            mFlingVelocityInfluence = 0.4f;
+            mScrollInterpolator = new OvershootInterpolator();
+            mScroller = new Scroller(getContext(), mScrollInterpolator);
+        }
+    }
+
+    @Override
+    protected void snapToDestination() {
+        if (mScrollMode == X_LARGE_MODE) {
+            super.snapToDestination();
+        } else {
+            snapToPageWithVelocity(getPageNearestToCenterOfScreen(), 0);
+        }
+    }
+
+    @Override
+    protected void snapToPageWithVelocity(int whichPage, int velocity) {
+        if (mScrollMode == X_LARGE_MODE) {
+            super.snapToPageWithVelocity(whichPage, velocity);
+        } else {
+            snapToPageWithVelocity(whichPage, 0, true);
+        }
+    }
+
+    private void snapToPageWithVelocity(int whichPage, int velocity, boolean settle) {
+            // if (!mScroller.isFinished()) return;
+
+        whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
+
+        final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage));
+        final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
+        final int delta = newX - mUnboundedScrollX;
+        int duration = (screenDelta + 1) * 100;
+
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+        }
+
+        if (settle) {
+            ((OvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
+        } else {
+            ((OvershootInterpolator) mScrollInterpolator).disableSettle();
+        }
+
+        velocity = Math.abs(velocity);
+        if (velocity > 0) {
+            duration += (duration / (velocity / mBaseLineFlingVelocity)) * mFlingVelocityInfluence;
+        } else {
+            duration += 100;
+        }
+
+        snapToPage(whichPage, delta, duration);
+    }
+
+    @Override
+    protected void snapToPage(int whichPage) {
+       if (mScrollMode == X_LARGE_MODE) {
+           super.snapToPage(whichPage);
+       } else {
+           snapToPageWithVelocity(whichPage, 0, false);
+       }
+    }
+
+    @Override
+    public void computeScroll() {
+        if (mScrollMode == X_LARGE_MODE) {
+            super.computeScroll();
+        } else {
+            boolean scrollComputed = computeScrollHelper();
+
+            if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) {
+                final float now = System.nanoTime() / NANOTIME_DIV;
+                final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
+
+                final float dx = mTouchX - mUnboundedScrollX;
+                scrollTo(Math.round(mUnboundedScrollX + dx * e), getScrollY());
+                mSmoothingTime = now;
+
+                // Keep generating points as long as we're more than 1px away from the target
+                if (dx > 1.f || dx < -1.f) {
+                    invalidate();
+                }
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/SpringLoadedDragController.java b/FairphoneHome/src/org/fairphone/launcher/SpringLoadedDragController.java
new file mode 100644
index 0000000..4f7eae6
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/SpringLoadedDragController.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+public class SpringLoadedDragController implements OnAlarmListener {
+    // how long the user must hover over a mini-screen before it unshrinks
+    final long ENTER_SPRING_LOAD_HOVER_TIME = 500;
+    final long ENTER_SPRING_LOAD_CANCEL_HOVER_TIME = 950;
+    final long EXIT_SPRING_LOAD_HOVER_TIME = 200;
+
+    Alarm mAlarm;
+
+    // the screen the user is currently hovering over, if any
+    private CellLayout mScreen;
+    private Launcher mLauncher;
+
+    public SpringLoadedDragController(Launcher launcher) {
+        mLauncher = launcher;
+        mAlarm = new Alarm();
+        mAlarm.setOnAlarmListener(this);
+    }
+
+    public void cancel() {
+        mAlarm.cancelAlarm();
+    }
+
+    // Set a new alarm to expire for the screen that we are hovering over now
+    public void setAlarm(CellLayout cl) {
+        mAlarm.cancelAlarm();
+        mAlarm.setAlarm((cl == null) ? ENTER_SPRING_LOAD_CANCEL_HOVER_TIME :
+            ENTER_SPRING_LOAD_HOVER_TIME);
+        mScreen = cl;
+    }
+
+    // this is called when our timer runs out
+    public void onAlarm(Alarm alarm) {
+        if (mScreen != null) {
+            // Snap to the screen that we are hovering over now
+            Workspace w = mLauncher.getWorkspace();
+            int page = w.indexOfChild(mScreen);
+            if (page != w.getCurrentPage()) {
+                w.snapToPage(page);
+            }
+        } else {
+            mLauncher.getDragController().cancelDrag();
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/StrokedTextView.java b/FairphoneHome/src/org/fairphone/launcher/StrokedTextView.java
new file mode 100644
index 0000000..4a65042
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/StrokedTextView.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+/**
+ * This class adds a stroke to the generic TextView allowing the text to stand out better against
+ * the background (ie. in the AllApps button).
+ */
+public class StrokedTextView extends TextView {
+    private final Canvas mCanvas = new Canvas();
+    private final Paint mPaint = new Paint();
+    private Bitmap mCache;
+    private boolean mUpdateCachedBitmap;
+    private int mStrokeColor;
+    private float mStrokeWidth;
+    private int mTextColor;
+
+    public StrokedTextView(Context context) {
+        super(context);
+        init(context, null, 0);
+    }
+
+    public StrokedTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs, 0);
+    }
+
+    public StrokedTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context, attrs, defStyle);
+    }
+
+    private void init(Context context, AttributeSet attrs, int defStyle) {
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StrokedTextView,
+                defStyle, 0);
+        mStrokeColor = a.getColor(R.styleable.StrokedTextView_strokeColor, 0xFF000000);
+        mStrokeWidth = a.getFloat(R.styleable.StrokedTextView_strokeWidth, 0.0f);
+        mTextColor = a.getColor(R.styleable.StrokedTextView_strokeTextColor, 0xFFFFFFFF);
+        a.recycle();
+        mUpdateCachedBitmap = true;
+
+        // Setup the text paint
+        mPaint.setAntiAlias(true);
+        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+    }
+
+    protected void onTextChanged(CharSequence text, int start, int before, int after) {
+        super.onTextChanged(text, start, before, after);
+        mUpdateCachedBitmap = true;
+    }
+
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        if (w > 0 && h > 0) {
+            mUpdateCachedBitmap = true;
+            mCache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        } else {
+            mCache = null;
+        }
+    }
+
+    protected void onDraw(Canvas canvas) {
+        if (mCache != null) {
+            if (mUpdateCachedBitmap) {
+                final int w = getMeasuredWidth();
+                final int h = getMeasuredHeight();
+                final String text = getText().toString();
+                final Rect textBounds = new Rect();
+                final Paint textPaint = getPaint();
+                final int textWidth = (int) textPaint.measureText(text);
+                textPaint.getTextBounds("x", 0, 1, textBounds);
+
+                // Clear the old cached image
+                mCanvas.setBitmap(mCache);
+                mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+                // Draw the drawable
+                final int drawableLeft = getPaddingLeft();
+                final int drawableTop = getPaddingTop();
+                final Drawable[] drawables = getCompoundDrawables();
+                for (int i = 0; i < drawables.length; ++i) {
+                    if (drawables[i] != null) {
+                        drawables[i].setBounds(drawableLeft, drawableTop,
+                                drawableLeft + drawables[i].getIntrinsicWidth(),
+                                drawableTop + drawables[i].getIntrinsicHeight());
+                        drawables[i].draw(mCanvas);
+                    }
+                }
+
+                final int left = w - getPaddingRight() - textWidth;
+                final int bottom = (h + textBounds.height()) / 2;
+
+                // Draw the outline of the text
+                mPaint.setStrokeWidth(mStrokeWidth);
+                mPaint.setColor(mStrokeColor);
+                mPaint.setTextSize(getTextSize());
+                mCanvas.drawText(text, left, bottom, mPaint);
+
+                // Draw the text itself
+                mPaint.setStrokeWidth(0);
+                mPaint.setColor(mTextColor);
+                mCanvas.drawText(text, left, bottom, mPaint);
+
+                mUpdateCachedBitmap = false;
+            }
+            canvas.drawBitmap(mCache, 0, 0, mPaint);
+        } else {
+            super.onDraw(canvas);
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/SymmetricalLinearTween.java b/FairphoneHome/src/org/fairphone/launcher/SymmetricalLinearTween.java
new file mode 100644
index 0000000..5ea35d2
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/SymmetricalLinearTween.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.os.Handler;
+import android.os.SystemClock;
+
+/**
+ * Provides an animation between 0.0f and 1.0f over a given duration.
+ */
+class SymmetricalLinearTween {
+
+    private static final int FPS = 30;
+    private static final int FRAME_TIME = 1000 / FPS;
+
+    Handler mHandler;
+    int mDuration;
+    TweenCallback mCallback;
+
+    boolean mRunning;
+    long mBase;
+    boolean mDirection;
+    float mValue;
+
+    /**
+     * @param duration milliseconds duration
+     * @param callback callbacks
+     */
+    public SymmetricalLinearTween(boolean initial, int duration, TweenCallback callback) {
+        mValue = initial ? 1.0f : 0.0f;
+        mDirection = initial;
+        mDuration = duration;
+        mCallback = callback;
+        mHandler = new Handler();
+    }
+
+    /**
+     * Starts the tweening.
+     *
+     * @param direction If direction is true, the value goes towards 1.0f.  If direction
+     *                  is false, the value goes towards 0.0f.
+     */
+    public void start(boolean direction) {
+        start(direction, SystemClock.uptimeMillis());
+    }
+
+    /**
+     * Starts the tweening.
+     *
+     * @param direction If direction is true, the value goes towards 1.0f.  If direction
+     *                  is false, the value goes towards 0.0f.
+     * @param baseTime  The time to use as zero for this animation, in the
+     *                  {@link SystemClock.uptimeMillis} time base.  This allows you to
+     *                  synchronize multiple animations.
+     */
+    public void start(boolean direction, long baseTime) {
+        if (direction != mDirection) {
+            if (!mRunning) {
+                mBase = baseTime;
+                mRunning = true;
+                mCallback.onTweenStarted();
+                long next = SystemClock.uptimeMillis() + FRAME_TIME;
+                mHandler.postAtTime(mTick, next);
+            } else {
+                // reverse direction
+                long now = SystemClock.uptimeMillis();
+                long diff = now - mBase;
+                mBase = now + diff - mDuration;
+            }
+            mDirection = direction;
+        }
+    }
+
+    Runnable mTick = new Runnable() {
+        public void run() {
+            long base = mBase;
+            long now = SystemClock.uptimeMillis();
+            long diff = now-base;
+            int duration = mDuration;
+            float val = diff/(float)duration;
+            if (!mDirection) {
+                val = 1.0f - val;
+            }
+            if (val > 1.0f) {
+                val = 1.0f;
+            } else if (val < 0.0f) {
+                val = 0.0f;
+            }
+            float old = mValue;
+            mValue = val;
+            mCallback.onTweenValueChanged(val, old);
+            int frame = (int)(diff / FRAME_TIME);
+            long next = base + ((frame+1)*FRAME_TIME);
+            if (diff < duration) {
+                mHandler.postAtTime(this, next);
+            }
+            if (diff >= duration) {
+                mCallback.onTweenFinished();
+                mRunning = false;
+            }
+        }
+    };
+}
+
diff --git a/FairphoneHome/src/org/fairphone/launcher/TweenCallback.java b/FairphoneHome/src/org/fairphone/launcher/TweenCallback.java
new file mode 100644
index 0000000..22af619
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/TweenCallback.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+interface TweenCallback {
+    void onTweenValueChanged(float value, float oldValue);
+    void onTweenStarted();
+    void onTweenFinished();
+}
+
diff --git a/FairphoneHome/src/org/fairphone/launcher/UninstallShortcutReceiver.java b/FairphoneHome/src/org/fairphone/launcher/UninstallShortcutReceiver.java
new file mode 100644
index 0000000..64c0e7a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/UninstallShortcutReceiver.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.Uri;
+import android.widget.Toast;
+
+import org.fairphone.launcher.R;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class UninstallShortcutReceiver extends BroadcastReceiver {
+    private static final String ACTION_UNINSTALL_SHORTCUT =
+            "com.android.launcher.action.UNINSTALL_SHORTCUT";
+
+    // The set of shortcuts that are pending uninstall
+    private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue =
+            new ArrayList<PendingUninstallShortcutInfo>();
+
+    // Determines whether to defer uninstalling shortcuts immediately until
+    // disableAndFlushUninstallQueue() is called.
+    private static boolean mUseUninstallQueue = false;
+
+    private static class PendingUninstallShortcutInfo {
+        Intent data;
+
+        public PendingUninstallShortcutInfo(Intent rawData) {
+            data = rawData;
+        }
+    }
+
+    public void onReceive(Context context, Intent data) {
+        if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) {
+            return;
+        }
+
+        PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data);
+        if (mUseUninstallQueue) {
+            mUninstallQueue.add(info);
+        } else {
+            processUninstallShortcut(context, info);
+        }
+    }
+
+    static void enableUninstallQueue() {
+        mUseUninstallQueue = true;
+    }
+
+    static void disableAndFlushUninstallQueue(Context context) {
+        mUseUninstallQueue = false;
+        Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator();
+        while (iter.hasNext()) {
+            processUninstallShortcut(context, iter.next());
+            iter.remove();
+        }
+    }
+
+    private static void processUninstallShortcut(Context context,
+            PendingUninstallShortcutInfo pendingInfo) {
+        String spKey = LauncherApplication.getSharedPreferencesKey();
+        SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+
+        final Intent data = pendingInfo.data;
+
+        LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+        synchronized (app) {
+            removeShortcut(context, data, sharedPrefs);
+        }
+    }
+
+    private static void removeShortcut(Context context, Intent data,
+            final SharedPreferences sharedPrefs) {
+        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+        boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
+
+        if (intent != null && name != null) {
+            final ContentResolver cr = context.getContentResolver();
+            Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
+                new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT },
+                LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null);
+
+            final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+            final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+
+            boolean changed = false;
+
+            try {
+                while (c.moveToNext()) {
+                    try {
+                        if (intent.filterEquals(Intent.parseUri(c.getString(intentIndex), 0))) {
+                            final long id = c.getLong(idIndex);
+                            final Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
+                            cr.delete(uri, null, null);
+                            changed = true;
+                            if (!duplicate) {
+                                break;
+                            }
+                        }
+                    } catch (URISyntaxException e) {
+                        // Ignore
+                    }
+                }
+            } finally {
+                c.close();
+            }
+
+            if (changed) {
+                cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null);
+                Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name),
+                        Toast.LENGTH_SHORT).show();
+            }
+
+            // Remove any items due to be animated
+            boolean appRemoved;
+            Set<String> newApps = new HashSet<String>();
+            newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
+            synchronized (newApps) {
+                do {
+                    appRemoved = newApps.remove(intent.toUri(0).toString());
+                } while (appRemoved);
+            }
+            if (appRemoved) {
+                final Set<String> savedNewApps = newApps;
+                new Thread("setNewAppsThread-remove") {
+                    public void run() {
+                        synchronized (savedNewApps) {
+                            SharedPreferences.Editor editor = sharedPrefs.edit();
+                            editor.putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY,
+                                    savedNewApps);
+                            if (savedNewApps.isEmpty()) {
+                                // Reset the page index if there are no more items
+                                editor.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1);
+                            }
+                            editor.commit();
+                        }
+                    }
+                }.start();
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/UserInitializeReceiver.java b/FairphoneHome/src/org/fairphone/launcher/UserInitializeReceiver.java
new file mode 100644
index 0000000..bb712fe
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/UserInitializeReceiver.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.fairphone.launcher.R;
+
+import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+
+/**
+ * Takes care of setting initial wallpaper for a user, by selecting the
+ * first wallpaper that is not in use by another user.
+ */
+public class UserInitializeReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final Resources resources = context.getResources();
+        // Context.getPackageName() may return the "original" package name,
+        // com.android.launcher2; Resources needs the real package name,
+        // com.android.launcher. So we ask Resources for what it thinks the
+        // package name should be.
+        final String packageName = resources.getResourcePackageName(R.array.wallpapers);
+        ArrayList<Integer> list = new ArrayList<Integer>();
+        addWallpapers(resources, packageName, R.array.wallpapers, list);
+        addWallpapers(resources, packageName, R.array.extra_wallpapers, list);
+        WallpaperManager wpm = (WallpaperManager) context.getSystemService(
+                Context.WALLPAPER_SERVICE);
+        for (int i=1; i<list.size(); i++) {
+            int resid = list.get(i);
+            if (!wpm.hasResourceWallpaper(resid)) {
+                try {
+                    wpm.setResource(resid);
+                } catch (IOException e) {
+                }
+                return;
+            }
+        }
+    }
+
+    private void addWallpapers(Resources resources, String packageName, int resid,
+            ArrayList<Integer> outList) {
+        final String[] extras = resources.getStringArray(resid);
+        for (String extra : extras) {
+            int res = resources.getIdentifier(extra, "drawable", packageName);
+            if (res != 0) {
+                outList.add(res);
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Utilities.java b/FairphoneHome/src/org/fairphone/launcher/Utilities.java
new file mode 100644
index 0000000..ed2d416
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Utilities.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import java.util.Random;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.PaintDrawable;
+import android.util.DisplayMetrics;
+
+import org.fairphone.launcher.R;
+
+/**
+ * Various utilities shared amongst the Launcher's classes.
+ */
+final class Utilities {
+    @SuppressWarnings("unused")
+    private static final String TAG = "Launcher.Utilities";
+
+    private static int sIconWidth = -1;
+    private static int sIconHeight = -1;
+    private static int sIconTextureWidth = -1;
+    private static int sIconTextureHeight = -1;
+
+    private static final Paint sBlurPaint = new Paint();
+    private static final Paint sGlowColorPressedPaint = new Paint();
+    private static final Paint sGlowColorFocusedPaint = new Paint();
+    private static final Paint sDisabledPaint = new Paint();
+    private static final Rect sOldBounds = new Rect();
+    private static final Canvas sCanvas = new Canvas();
+
+    static {
+        sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
+                Paint.FILTER_BITMAP_FLAG));
+    }
+    static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
+    static int sColorIndex = 0;
+
+    /**
+     * Returns a bitmap suitable for the all apps view. Used to convert pre-ICS
+     * icon bitmaps that are stored in the database (which were 74x74 pixels at hdpi size)
+     * to the proper size (48dp)
+     */
+    static Bitmap createIconBitmap(Bitmap icon, Context context) {
+        int textureWidth = sIconTextureWidth;
+        int textureHeight = sIconTextureHeight;
+        int sourceWidth = icon.getWidth();
+        int sourceHeight = icon.getHeight();
+        if (sourceWidth > textureWidth && sourceHeight > textureHeight) {
+            // Icon is bigger than it should be; clip it (solves the GB->ICS migration case)
+            return Bitmap.createBitmap(icon,
+                    (sourceWidth - textureWidth) / 2,
+                    (sourceHeight - textureHeight) / 2,
+                    textureWidth, textureHeight);
+        } else if (sourceWidth == textureWidth && sourceHeight == textureHeight) {
+            // Icon is the right size, no need to change it
+            return icon;
+        } else {
+            // Icon is too small, render to a larger bitmap
+            final Resources resources = context.getResources();
+            return createIconBitmap(new BitmapDrawable(resources, icon), context);
+        }
+    }
+
+    /**
+     * Returns a bitmap suitable for the all apps view.
+     */
+    static Bitmap createIconBitmap(Drawable icon, Context context) {
+        synchronized (sCanvas) { // we share the statics :-(
+            if (sIconWidth == -1) {
+                initStatics(context);
+            }
+
+            int width = sIconWidth;
+            int height = sIconHeight;
+
+            if (icon instanceof PaintDrawable) {
+                PaintDrawable painter = (PaintDrawable) icon;
+                painter.setIntrinsicWidth(width);
+                painter.setIntrinsicHeight(height);
+            } else if (icon instanceof BitmapDrawable) {
+                // Ensure the bitmap has a density.
+                BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
+                Bitmap bitmap = bitmapDrawable.getBitmap();
+                if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
+                    bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());
+                }
+            }
+            int sourceWidth = icon.getIntrinsicWidth();
+            int sourceHeight = icon.getIntrinsicHeight();
+            if (sourceWidth > 0 && sourceHeight > 0) {
+                // There are intrinsic sizes.
+                if (width < sourceWidth || height < sourceHeight) {
+                    // It's too big, scale it down.
+                    final float ratio = (float) sourceWidth / sourceHeight;
+                    if (sourceWidth > sourceHeight) {
+                        height = (int) (width / ratio);
+                    } else if (sourceHeight > sourceWidth) {
+                        width = (int) (height * ratio);
+                    }
+                } else if (sourceWidth < width && sourceHeight < height) {
+                    // Don't scale up the icon
+                    width = sourceWidth;
+                    height = sourceHeight;
+                }
+            }
+
+            // no intrinsic size --> use default size
+            int textureWidth = sIconTextureWidth;
+            int textureHeight = sIconTextureHeight;
+
+            final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
+                    Bitmap.Config.ARGB_8888);
+            final Canvas canvas = sCanvas;
+            canvas.setBitmap(bitmap);
+
+            final int left = (textureWidth-width) / 2;
+            final int top = (textureHeight-height) / 2;
+
+            @SuppressWarnings("all") // suppress dead code warning
+            final boolean debug = false;
+            if (debug) {
+                // draw a big box for the icon for debugging
+                canvas.drawColor(sColors[sColorIndex]);
+                if (++sColorIndex >= sColors.length) sColorIndex = 0;
+                Paint debugPaint = new Paint();
+                debugPaint.setColor(0xffcccc00);
+                canvas.drawRect(left, top, left+width, top+height, debugPaint);
+            }
+
+            sOldBounds.set(icon.getBounds());
+            icon.setBounds(left, top, left+width, top+height);
+            icon.draw(canvas);
+            icon.setBounds(sOldBounds);
+            canvas.setBitmap(null);
+
+            return bitmap;
+        }
+    }
+
+    static void drawSelectedAllAppsBitmap(Canvas dest, int destWidth, int destHeight,
+            boolean pressed, Bitmap src) {
+        synchronized (sCanvas) { // we share the statics :-(
+            if (sIconWidth == -1) {
+                // We can't have gotten to here without src being initialized, which
+                // comes from this file already.  So just assert.
+                //initStatics(context);
+                throw new RuntimeException("Assertion failed: Utilities not initialized");
+            }
+
+            dest.drawColor(0, PorterDuff.Mode.CLEAR);
+
+            int[] xy = new int[2];
+            Bitmap mask = src.extractAlpha(sBlurPaint, xy);
+
+            float px = (destWidth - src.getWidth()) / 2;
+            float py = (destHeight - src.getHeight()) / 2;
+            dest.drawBitmap(mask, px + xy[0], py + xy[1],
+                    pressed ? sGlowColorPressedPaint : sGlowColorFocusedPaint);
+
+            mask.recycle();
+        }
+    }
+
+    /**
+     * Returns a Bitmap representing the thumbnail of the specified Bitmap.
+     * The size of the thumbnail is defined by the dimension
+     * android.R.dimen.launcher_application_icon_size.
+     *
+     * @param bitmap The bitmap to get a thumbnail of.
+     * @param context The application's context.
+     *
+     * @return A thumbnail for the specified bitmap or the bitmap itself if the
+     *         thumbnail could not be created.
+     */
+    static Bitmap resampleIconBitmap(Bitmap bitmap, Context context) {
+        synchronized (sCanvas) { // we share the statics :-(
+            if (sIconWidth == -1) {
+                initStatics(context);
+            }
+
+            if (bitmap.getWidth() == sIconWidth && bitmap.getHeight() == sIconHeight) {
+                return bitmap;
+            } else {
+                final Resources resources = context.getResources();
+                return createIconBitmap(new BitmapDrawable(resources, bitmap), context);
+            }
+        }
+    }
+
+    static Bitmap drawDisabledBitmap(Bitmap bitmap, Context context) {
+        synchronized (sCanvas) { // we share the statics :-(
+            if (sIconWidth == -1) {
+                initStatics(context);
+            }
+            final Bitmap disabled = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
+                    Bitmap.Config.ARGB_8888);
+            final Canvas canvas = sCanvas;
+            canvas.setBitmap(disabled);
+            
+            canvas.drawBitmap(bitmap, 0.0f, 0.0f, sDisabledPaint);
+
+            canvas.setBitmap(null);
+
+            return disabled;
+        }
+    }
+
+    private static void initStatics(Context context) {
+        final Resources resources = context.getResources();
+        final DisplayMetrics metrics = resources.getDisplayMetrics();
+        final float density = metrics.density;
+
+        sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
+        sIconTextureWidth = sIconTextureHeight = sIconWidth;
+
+        sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
+        sGlowColorPressedPaint.setColor(0xffffc300);
+        sGlowColorFocusedPaint.setColor(0xffff8e00);
+
+        ColorMatrix cm = new ColorMatrix();
+        cm.setSaturation(0.2f);
+        sDisabledPaint.setColorFilter(new ColorMatrixColorFilter(cm));
+        sDisabledPaint.setAlpha(0x88);
+    }
+
+    /** Only works for positive numbers. */
+    static int roundToPow2(int n) {
+        int orig = n;
+        n >>= 1;
+        int mask = 0x8000000;
+        while (mask != 0 && (n & mask) == 0) {
+            mask >>= 1;
+        }
+        while (mask != 0) {
+            n |= mask;
+            mask >>= 1;
+        }
+        n += 1;
+        if (n != orig) {
+            n <<= 1;
+        }
+        return n;
+    }
+
+    static int generateRandomId() {
+        return new Random(System.currentTimeMillis()).nextInt(1 << 24);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/WallpaperChooser.java b/FairphoneHome/src/org/fairphone/launcher/WallpaperChooser.java
new file mode 100644
index 0000000..d14dbb7
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/WallpaperChooser.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import org.fairphone.launcher.R;
+
+import android.app.Activity;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.os.Bundle;
+
+public class WallpaperChooser extends Activity {
+    @SuppressWarnings("unused")
+    private static final String TAG = "Launcher.WallpaperChooser";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.wallpaper_chooser_base);
+
+        Fragment fragmentView =
+                getFragmentManager().findFragmentById(R.id.wallpaper_chooser_fragment);
+        // TODO: The following code is currently not exercised. Leaving it here in case it
+        // needs to be revived again.
+        if (fragmentView == null) {
+            /* When the screen is XLarge, the fragment is not included in the layout, so show it
+             * as a dialog
+             */
+            DialogFragment fragment = WallpaperChooserDialogFragment.newInstance();
+            fragment.show(getFragmentManager(), "dialog");
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/WallpaperChooserDialogFragment.java b/FairphoneHome/src/org/fairphone/launcher/WallpaperChooserDialogFragment.java
new file mode 100644
index 0000000..5073aa6
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/WallpaperChooserDialogFragment.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.SpinnerAdapter;
+
+import org.fairphone.launcher.R;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class WallpaperChooserDialogFragment extends DialogFragment implements
+        AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+
+    private static final String TAG = "Launcher.WallpaperChooserDialogFragment";
+    private static final String EMBEDDED_KEY = "com.android.launcher2."
+            + "WallpaperChooserDialogFragment.EMBEDDED_KEY";
+
+    private boolean mEmbedded;
+    private Bitmap mBitmap = null;
+
+    private ArrayList<Integer> mThumbs;
+    private ArrayList<Integer> mImages;
+    private WallpaperLoader mLoader;
+    private WallpaperDrawable mWallpaperDrawable = new WallpaperDrawable();
+
+    public static WallpaperChooserDialogFragment newInstance() {
+        WallpaperChooserDialogFragment fragment = new WallpaperChooserDialogFragment();
+        fragment.setCancelable(true);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (savedInstanceState != null && savedInstanceState.containsKey(EMBEDDED_KEY)) {
+            mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY);
+        } else {
+            mEmbedded = isInLayout();
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(EMBEDDED_KEY, mEmbedded);
+    }
+
+    private void cancelLoader() {
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel(true);
+            mLoader = null;
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+
+        cancelLoader();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        cancelLoader();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        /* On orientation changes, the dialog is effectively "dismissed" so this is called
+         * when the activity is no longer associated with this dying dialog fragment. We
+         * should just safely ignore this case by checking if getActivity() returns null
+         */
+        Activity activity = getActivity();
+        if (activity != null) {
+            activity.finish();
+        }
+    }
+
+    /* This will only be called when in XLarge mode, since this Fragment is invoked like
+     * a dialog in that mode
+     */
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        findWallpapers();
+
+        return null;
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        findWallpapers();
+
+        /* If this fragment is embedded in the layout of this activity, then we should
+         * generate a view to display. Otherwise, a dialog will be created in
+         * onCreateDialog()
+         */
+        if (mEmbedded) {
+            View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
+            view.setBackground(mWallpaperDrawable);
+
+            final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
+            gallery.setCallbackDuringFling(false);
+            gallery.setOnItemSelectedListener(this);
+            gallery.setAdapter(new ImageAdapter(getActivity()));
+
+            View setButton = view.findViewById(R.id.set);
+            setButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    selectWallpaper(gallery.getSelectedItemPosition());
+                }
+            });
+            return view;
+        }
+        return null;
+    }
+
+    private void selectWallpaper(int position) {
+        try {
+            WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService(
+                    Context.WALLPAPER_SERVICE);
+            wpm.setResource(mImages.get(position));
+            Activity activity = getActivity();
+            activity.setResult(Activity.RESULT_OK);
+            activity.finish();
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to set wallpaper: " + e);
+        }
+    }
+
+    // Click handler for the Dialog's GridView
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        selectWallpaper(position);
+    }
+
+    // Selection handler for the embedded Gallery view
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel();
+        }
+        mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+    }
+
+    private void findWallpapers() {
+        mThumbs = new ArrayList<Integer>(24);
+        mImages = new ArrayList<Integer>(24);
+
+        final Resources resources = getResources();
+        // Context.getPackageName() may return the "original" package name,
+        // com.android.launcher2; Resources needs the real package name,
+        // com.android.launcher. So we ask Resources for what it thinks the
+        // package name should be.
+        final String packageName = resources.getResourcePackageName(R.array.wallpapers);
+
+        addWallpapers(resources, packageName, R.array.wallpapers);
+        addWallpapers(resources, packageName, R.array.extra_wallpapers);
+    }
+
+    private void addWallpapers(Resources resources, String packageName, int list) {
+        final String[] extras = resources.getStringArray(list);
+        for (String extra : extras) {
+            int res = resources.getIdentifier(extra, "drawable", packageName);
+            if (res != 0) {
+                final int thumbRes = resources.getIdentifier(extra + "_small",
+                        "drawable", packageName);
+
+                if (thumbRes != 0) {
+                    mThumbs.add(thumbRes);
+                    mImages.add(res);
+                }
+            }
+        }
+    }
+
+    private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
+        private LayoutInflater mLayoutInflater;
+
+        ImageAdapter(Activity activity) {
+            mLayoutInflater = activity.getLayoutInflater();
+        }
+
+        public int getCount() {
+            return mThumbs.size();
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            View view;
+
+            if (convertView == null) {
+                view = mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);
+            } else {
+                view = convertView;
+            }
+
+            ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);
+
+            int thumbRes = mThumbs.get(position);
+            image.setImageResource(thumbRes);
+            Drawable thumbDrawable = image.getDrawable();
+            if (thumbDrawable != null) {
+                thumbDrawable.setDither(true);
+            } else {
+                Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
+                        + position);
+            }
+
+            return view;
+        }
+    }
+
+    class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
+        BitmapFactory.Options mOptions;
+
+        WallpaperLoader() {
+            mOptions = new BitmapFactory.Options();
+            mOptions.inDither = false;
+            mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        }
+
+        @Override
+        protected Bitmap doInBackground(Integer... params) {
+            if (isCancelled()) return null;
+            try {
+                return BitmapFactory.decodeResource(getResources(),
+                        mImages.get(params[0]), mOptions);
+            } catch (OutOfMemoryError e) {
+                return null;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(Bitmap b) {
+            if (b == null) return;
+
+            if (!isCancelled() && !mOptions.mCancel) {
+                // Help the GC
+                if (mBitmap != null) {
+                    mBitmap.recycle();
+                }
+
+                View v = getView();
+                if (v != null) {
+                    mBitmap = b;
+                    mWallpaperDrawable.setBitmap(b);
+                    v.postInvalidate();
+                } else {
+                    mBitmap = null;
+                    mWallpaperDrawable.setBitmap(null);
+                }
+                mLoader = null;
+            } else {
+               b.recycle();
+            }
+        }
+
+        void cancel() {
+            mOptions.requestCancelDecode();
+            super.cancel(true);
+        }
+    }
+
+    /**
+     * Custom drawable that centers the bitmap fed to it.
+     */
+    static class WallpaperDrawable extends Drawable {
+
+        Bitmap mBitmap;
+        int mIntrinsicWidth;
+        int mIntrinsicHeight;
+
+        /* package */void setBitmap(Bitmap bitmap) {
+            mBitmap = bitmap;
+            if (mBitmap == null)
+                return;
+            mIntrinsicWidth = mBitmap.getWidth();
+            mIntrinsicHeight = mBitmap.getHeight();
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            if (mBitmap == null) return;
+            int width = canvas.getWidth();
+            int height = canvas.getHeight();
+            int x = (width - mIntrinsicWidth) / 2;
+            int y = (height - mIntrinsicHeight) / 2;
+            canvas.drawBitmap(mBitmap, x, y, null);
+        }
+
+        @Override
+        public int getOpacity() {
+            return android.graphics.PixelFormat.OPAQUE;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            // Ignore
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+            // Ignore
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/Workspace.java b/FairphoneHome/src/org/fairphone/launcher/Workspace.java
new file mode 100644
index 0000000..1e6900d
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/Workspace.java
@@ -0,0 +1,3829 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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 org.fairphone.launcher;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.WallpaperManager;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.fairphone.launcher.R;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.fairphone.launcher.FolderIcon.FolderRingAnimator;
+import org.fairphone.launcher.LauncherSettings.Favorites;
+
+/**
+ * The workspace is a wide area with a wallpaper and a finite number of pages.
+ * Each page contains a number of icons, folders or widgets the user can
+ * interact with. A workspace is meant to be used with a fixed width only.
+ */
+public class Workspace extends SmoothPagedView
+        implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
+        DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener {
+    private static final String TAG = "Launcher.Workspace";
+
+    // Y rotation to apply to the workspace screens
+    private static final float WORKSPACE_OVERSCROLL_ROTATION = 24f;
+
+    private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0;
+    private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
+    private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
+
+    private static final int BACKGROUND_FADE_OUT_DURATION = 350;
+    private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
+    private static final int FLING_THRESHOLD_VELOCITY = 500;
+
+    // These animators are used to fade the children's outlines
+    private ObjectAnimator mChildrenOutlineFadeInAnimation;
+    private ObjectAnimator mChildrenOutlineFadeOutAnimation;
+    private float mChildrenOutlineAlpha = 0;
+
+    // These properties refer to the background protection gradient used for AllApps and Customize
+    private ValueAnimator mBackgroundFadeInAnimation;
+    private ValueAnimator mBackgroundFadeOutAnimation;
+    private Drawable mBackground;
+    boolean mDrawBackground = true;
+    private float mBackgroundAlpha = 0;
+    private float mOverScrollMaxBackgroundAlpha = 0.0f;
+
+    private float mWallpaperScrollRatio = 1.0f;
+    private int mOriginalPageSpacing;
+
+    private final WallpaperManager mWallpaperManager;
+    private IBinder mWindowToken;
+    private static final float WALLPAPER_SCREENS_SPAN = 2f;
+
+    private int mDefaultPage;
+
+    /**
+     * CellInfo for the cell that is currently being dragged
+     */
+    private CellLayout.CellInfo mDragInfo;
+
+    /**
+     * Target drop area calculated during last acceptDrop call.
+     */
+    private int[] mTargetCell = new int[2];
+    private int mDragOverX = -1;
+    private int mDragOverY = -1;
+
+    static Rect mLandscapeCellLayoutMetrics = null;
+    static Rect mPortraitCellLayoutMetrics = null;
+
+    /**
+     * The CellLayout that is currently being dragged over
+     */
+    private CellLayout mDragTargetLayout = null;
+    /**
+     * The CellLayout that we will show as glowing
+     */
+    private CellLayout mDragOverlappingLayout = null;
+
+    /**
+     * The CellLayout which will be dropped to
+     */
+    private CellLayout mDropToLayout = null;
+
+    private Launcher mLauncher;
+    private IconCache mIconCache;
+    private DragController mDragController;
+
+    // These are temporary variables to prevent having to allocate a new object just to
+    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
+    private int[] mTempCell = new int[2];
+    private int[] mTempEstimate = new int[2];
+    private float[] mDragViewVisualCenter = new float[2];
+    private float[] mTempDragCoordinates = new float[2];
+    private float[] mTempCellLayoutCenterCoordinates = new float[2];
+    private float[] mTempDragBottomRightCoordinates = new float[2];
+    private Matrix mTempInverseMatrix = new Matrix();
+
+    private SpringLoadedDragController mSpringLoadedDragController;
+    private float mSpringLoadedShrinkFactor;
+
+    private static final int DEFAULT_CELL_COUNT_X = 4;
+    private static final int DEFAULT_CELL_COUNT_Y = 7;
+
+    // State variable that indicates whether the pages are small (ie when you're
+    // in all apps or customize mode)
+
+    enum State { NORMAL, SPRING_LOADED, SMALL };
+    private State mState = State.NORMAL;
+    private boolean mIsSwitchingState = false;
+
+    boolean mAnimatingViewIntoPlace = false;
+    boolean mIsDragOccuring = false;
+    boolean mChildrenLayersEnabled = true;
+
+    /** Is the user is dragging an item near the edge of a page? */
+    private boolean mInScrollArea = false;
+
+    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
+    private Bitmap mDragOutline = null;
+    private final Rect mTempRect = new Rect();
+    private final int[] mTempXY = new int[2];
+    private int[] mTempVisiblePagesRange = new int[2];
+    private float mOverscrollFade = 0;
+    private boolean mOverscrollTransformsSet;
+    public static final int DRAG_BITMAP_PADDING = 2;
+    private boolean mWorkspaceFadeInAdjacentScreens;
+
+    enum WallpaperVerticalOffset { TOP, MIDDLE, BOTTOM };
+    int mWallpaperWidth;
+    int mWallpaperHeight;
+    WallpaperOffsetInterpolator mWallpaperOffset;
+    boolean mUpdateWallpaperOffsetImmediately = false;
+    private Runnable mDelayedResizeRunnable;
+    private Runnable mDelayedSnapToPageRunnable;
+    private Point mDisplaySize = new Point();
+    private boolean mIsStaticWallpaper;
+    private int mWallpaperTravelWidth;
+    private int mSpringLoadedPageSpacing;
+    private int mCameraDistance;
+
+    // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
+    private static final int FOLDER_CREATION_TIMEOUT = 0;
+    private static final int REORDER_TIMEOUT = 250;
+    private final Alarm mFolderCreationAlarm = new Alarm();
+    private final Alarm mReorderAlarm = new Alarm();
+    private FolderRingAnimator mDragFolderRingAnimator = null;
+    private FolderIcon mDragOverFolderIcon = null;
+    private boolean mCreateUserFolderOnDrop = false;
+    private boolean mAddToExistingFolderOnDrop = false;
+    private DropTarget.DragEnforcer mDragEnforcer;
+    private float mMaxDistanceForFolderCreation;
+
+    // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
+    private float mXDown;
+    private float mYDown;
+    final static float START_DAMPING_TOUCH_SLOP_ANGLE = (float) Math.PI / 6;
+    final static float MAX_SWIPE_ANGLE = (float) Math.PI / 3;
+    final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
+
+    // Relating to the animation of items being dropped externally
+    public static final int ANIMATE_INTO_POSITION_AND_DISAPPEAR = 0;
+    public static final int ANIMATE_INTO_POSITION_AND_REMAIN = 1;
+    public static final int ANIMATE_INTO_POSITION_AND_RESIZE = 2;
+    public static final int COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION = 3;
+    public static final int CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION = 4;
+
+    // Related to dragging, folder creation and reordering
+    private static final int DRAG_MODE_NONE = 0;
+    private static final int DRAG_MODE_CREATE_FOLDER = 1;
+    private static final int DRAG_MODE_ADD_TO_FOLDER = 2;
+    private static final int DRAG_MODE_REORDER = 3;
+    private int mDragMode = DRAG_MODE_NONE;
+    private int mLastReorderX = -1;
+    private int mLastReorderY = -1;
+
+    private SparseArray<Parcelable> mSavedStates;
+    private final ArrayList<Integer> mRestoredPages = new ArrayList<Integer>();
+
+    // These variables are used for storing the initial and final values during workspace animations
+    private int mSavedScrollX;
+    private float mSavedRotationY;
+    private float mSavedTranslationX;
+    private float mCurrentScaleX;
+    private float mCurrentScaleY;
+    private float mCurrentRotationY;
+    private float mCurrentTranslationX;
+    private float mCurrentTranslationY;
+    private float[] mOldTranslationXs;
+    private float[] mOldTranslationYs;
+    private float[] mOldScaleXs;
+    private float[] mOldScaleYs;
+    private float[] mOldBackgroundAlphas;
+    private float[] mOldAlphas;
+    private float[] mNewTranslationXs;
+    private float[] mNewTranslationYs;
+    private float[] mNewScaleXs;
+    private float[] mNewScaleYs;
+    private float[] mNewBackgroundAlphas;
+    private float[] mNewAlphas;
+    private float[] mNewRotationYs;
+    private float mTransitionProgress;
+
+    private final Runnable mBindPages = new Runnable() {
+        @Override
+        public void run() {
+            mLauncher.getModel().bindRemainingSynchronousPages();
+        }
+    };
+
+    /**
+     * Used to inflate the Workspace from XML.
+     *
+     * @param context The application's context.
+     * @param attrs The attributes set containing the Workspace's customization values.
+     */
+    public Workspace(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * Used to inflate the Workspace from XML.
+     *
+     * @param context The application's context.
+     * @param attrs The attributes set containing the Workspace's customization values.
+     * @param defStyle Unused.
+     */
+    public Workspace(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mContentIsRefreshable = false;
+        mOriginalPageSpacing = mPageSpacing;
+
+        mDragEnforcer = new DropTarget.DragEnforcer(context);
+        // With workspace, data is available straight from the get-go
+        setDataIsReady();
+
+        mLauncher = (Launcher) context;
+        final Resources res = getResources();
+        mWorkspaceFadeInAdjacentScreens = res.getBoolean(R.bool.config_workspaceFadeAdjacentScreens);
+        mFadeInAdjacentScreens = false;
+        mWallpaperManager = WallpaperManager.getInstance(context);
+
+        int cellCountX = DEFAULT_CELL_COUNT_X;
+        int cellCountY = DEFAULT_CELL_COUNT_Y;
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.Workspace, defStyle, 0);
+
+            TypedArray actionBarSizeTypedArray =
+                context.obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
+            final float actionBarHeight = actionBarSizeTypedArray.getDimension(0, 0f);
+
+            Point minDims = new Point();
+            Point maxDims = new Point();
+            mLauncher.getWindowManager().getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+
+            boolean isLandscape = LauncherApplication.isScreenLandscape(context);
+            
+            int x = minDims.x;
+            int y = maxDims.y;
+            
+            int cellWidth = getResources().getDimensionPixelSize(R.dimen.workspace_cell_width);
+            int cellHeight = getResources().getDimensionPixelSize(R.dimen.workspace_cell_height);
+            int gapX = getResources().getDimensionPixelSize(R.dimen.workspace_width_gap);
+            int gapY = getResources().getDimensionPixelSize(R.dimen.workspace_height_gap);
+            
+            int cellWidthSize = cellWidth   + gapX;
+            int cellHeightSize = cellHeight + gapY;
+                        
+            if( isLandscape ){
+            	x = maxDims.x;
+            	y = minDims.y;
+            }
+            
+            cellCountX = x / cellWidthSize ;
+            cellCountY = y / cellHeightSize;
+            
+        mSpringLoadedShrinkFactor =
+            res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
+        mSpringLoadedPageSpacing =
+                res.getDimensionPixelSize(R.dimen.workspace_spring_loaded_page_spacing);
+        mCameraDistance = res.getInteger(R.integer.config_cameraDistance);
+
+        
+        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
+        a.recycle();
+
+        setOnHierarchyChangeListener(this);
+
+        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
+        setHapticFeedbackEnabled(false);
+
+        initWorkspace();
+
+        // Disable multitouch across the workspace/all apps/customize tray
+        setMotionEventSplittingEnabled(true);
+
+        // Unless otherwise specified this view is important for accessibility.
+        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+    }
+
+    // estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
+    // dimension if unsuccessful
+    public int[] estimateItemSize(int hSpan, int vSpan,
+            ItemInfo itemInfo, boolean springLoaded) {
+        int[] size = new int[2];
+        if (getChildCount() > 0) {
+            CellLayout cl = (CellLayout) mLauncher.getWorkspace().getChildAt(0);
+            Rect r = estimateItemPosition(cl, itemInfo, 0, 0, hSpan, vSpan);
+            size[0] = r.width();
+            size[1] = r.height();
+            if (springLoaded) {
+                size[0] *= mSpringLoadedShrinkFactor;
+                size[1] *= mSpringLoadedShrinkFactor;
+            }
+            return size;
+        } else {
+            size[0] = Integer.MAX_VALUE;
+            size[1] = Integer.MAX_VALUE;
+            return size;
+        }
+    }
+    public Rect estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
+            int hCell, int vCell, int hSpan, int vSpan) {
+        Rect r = new Rect();
+        cl.cellToRect(hCell, vCell, hSpan, vSpan, r);
+        return r;
+    }
+
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        mIsDragOccuring = true;
+        updateChildrenLayersEnabled(false);
+        mLauncher.lockScreenOrientation();
+        setChildrenBackgroundAlphaMultipliers(1f);
+        // Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
+        InstallShortcutReceiver.enableInstallQueue();
+        UninstallShortcutReceiver.enableUninstallQueue();
+    }
+
+    public void onDragEnd() {
+        mIsDragOccuring = false;
+        updateChildrenLayersEnabled(false);
+        mLauncher.unlockScreenOrientation(false);
+
+        // Re-enable any Un/InstallShortcutReceiver and now process any queued items
+        InstallShortcutReceiver.disableAndFlushInstallQueue(getContext());
+        UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext());
+    }
+
+    /**
+     * Initializes various states for this workspace.
+     */
+    protected void initWorkspace() {
+        Context context = getContext();
+        mCurrentPage = mDefaultPage;
+        Launcher.setScreen(mCurrentPage);
+        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
+        mIconCache = app.getIconCache();
+        setWillNotDraw(false);
+        setChildrenDrawnWithCacheEnabled(true);
+
+        final Resources res = getResources();
+        try {
+            mBackground = res.getDrawable(R.drawable.apps_customize_bg);
+        } catch (Resources.NotFoundException e) {
+            // In this case, we will skip drawing background protection
+        }
+
+        mWallpaperOffset = new WallpaperOffsetInterpolator();
+        Display display = mLauncher.getWindowManager().getDefaultDisplay();
+        display.getSize(mDisplaySize);
+        mWallpaperTravelWidth = (int) (mDisplaySize.x *
+                wallpaperTravelToScreenWidthRatio(mDisplaySize.x, mDisplaySize.y));
+
+        mMaxDistanceForFolderCreation = (0.55f * res.getDimensionPixelSize(R.dimen.app_icon_size));
+        mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+    }
+
+    @Override
+    protected int getScrollMode() {
+        return SmoothPagedView.X_LARGE_MODE;
+    }
+
+    @Override
+    public void onChildViewAdded(View parent, View child) {
+        if (!(child instanceof CellLayout)) {
+            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
+        }
+        CellLayout cl = ((CellLayout) child);
+        cl.setOnInterceptTouchListener(this);
+        cl.setClickable(true);
+        cl.setContentDescription(getContext().getString(
+                R.string.workspace_description_format, getChildCount()));
+    }
+
+    @Override
+    public void onChildViewRemoved(View parent, View child) {
+    }
+
+    protected boolean shouldDrawChild(View child) {
+        final CellLayout cl = (CellLayout) child;
+        return super.shouldDrawChild(child) &&
+            (cl.getShortcutsAndWidgets().getAlpha() > 0 ||
+             cl.getBackgroundAlpha() > 0);
+    }
+
+    /**
+     * @return The open folder on the current screen, or null if there is none
+     */
+    Folder getOpenFolder() {
+        DragLayer dragLayer = mLauncher.getDragLayer();
+        int count = dragLayer.getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = dragLayer.getChildAt(i);
+            if (child instanceof Folder) {
+                Folder folder = (Folder) child;
+                if (folder.getInfo().opened)
+                    return folder;
+            }
+        }
+        return null;
+    }
+
+    boolean isTouchActive() {
+        return mTouchState != TOUCH_STATE_REST;
+    }
+
+    /**
+     * Adds the specified child in the specified screen. The position and dimension of
+     * the child are defined by x, y, spanX and spanY.
+     *
+     * @param child The child to add in one of the workspace's screens.
+     * @param screen The screen in which to add the child.
+     * @param x The X position of the child in the screen's grid.
+     * @param y The Y position of the child in the screen's grid.
+     * @param spanX The number of cells spanned horizontally by the child.
+     * @param spanY The number of cells spanned vertically by the child.
+     */
+    void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY) {
+        addInScreen(child, container, screen, x, y, spanX, spanY, false);
+    }
+
+    /**
+     * Adds the specified child in the specified screen. The position and dimension of
+     * the child are defined by x, y, spanX and spanY.
+     *
+     * @param child The child to add in one of the workspace's screens.
+     * @param screen The screen in which to add the child.
+     * @param x The X position of the child in the screen's grid.
+     * @param y The Y position of the child in the screen's grid.
+     * @param spanX The number of cells spanned horizontally by the child.
+     * @param spanY The number of cells spanned vertically by the child.
+     * @param insert When true, the child is inserted at the beginning of the children list.
+     */
+    void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY,
+            boolean insert) {
+        if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+            if (screen < 0 || screen >= getChildCount()) {
+                Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
+                    + " (was " + screen + "); skipping child");
+                return;
+            }
+        }
+
+        final CellLayout layout;
+        if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            layout = mLauncher.getHotseat().getLayout();
+            child.setOnKeyListener(null);
+
+            // Hide folder title in the hotseat
+            if (child instanceof FolderIcon) {
+                ((FolderIcon) child).setTextVisible(false);
+            }
+
+            if (screen < 0) {
+                screen = mLauncher.getHotseat().getOrderInHotseat(x, y);
+            } else {
+                // Note: We do this to ensure that the hotseat is always laid out in the orientation
+                // of the hotseat in order regardless of which orientation they were added
+                x = mLauncher.getHotseat().getCellXFromOrder(screen);
+                y = mLauncher.getHotseat().getCellYFromOrder(screen);
+            }
+        } else {
+            // Show folder title if not in the hotseat
+            if (child instanceof FolderIcon) {
+                ((FolderIcon) child).setTextVisible(true);
+            }
+
+            layout = (CellLayout) getChildAt(screen);
+            child.setOnKeyListener(new IconKeyEventListener());
+        }
+
+        LayoutParams genericLp = child.getLayoutParams();
+        CellLayout.LayoutParams lp;
+        if (genericLp == null || !(genericLp instanceof CellLayout.LayoutParams)) {
+            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
+        } else {
+            lp = (CellLayout.LayoutParams) genericLp;
+            lp.cellX = x;
+            lp.cellY = y;
+            lp.cellHSpan = spanX;
+            lp.cellVSpan = spanY;
+        }
+
+        if (spanX < 0 && spanY < 0) {
+            lp.isLockedToGrid = false;
+        }
+
+        // Get the canonical child id to uniquely represent this view in this screen
+        int childId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
+        boolean markCellsAsOccupied = !(child instanceof Folder);
+        if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
+            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
+        }
+
+        if (!(child instanceof Folder)) {
+            child.setHapticFeedbackEnabled(false);
+            child.setOnLongClickListener(mLongClickListener);
+        }
+        if (child instanceof DropTarget) {
+            mDragController.addDropTarget((DropTarget) child);
+        }
+    }
+
+    /**
+     * Check if the point (x, y) hits a given page.
+     */
+    private boolean hitsPage(int index, float x, float y) {
+        final View page = getChildAt(index);
+        if (page != null) {
+            float[] localXY = { x, y };
+            mapPointFromSelfToChild(page, localXY);
+            return (localXY[0] >= 0 && localXY[0] < page.getWidth()
+                    && localXY[1] >= 0 && localXY[1] < page.getHeight());
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean hitsPreviousPage(float x, float y) {
+        // mNextPage is set to INVALID_PAGE whenever we are stationary.
+        // Calculating "next page" this way ensures that you scroll to whatever page you tap on
+        final int current = (mNextPage == INVALID_PAGE) ? mCurrentPage : mNextPage;
+
+        // Only allow tap to next page on large devices, where there's significant margin outside
+        // the active workspace
+        return LauncherApplication.isScreenLarge() && hitsPage(current - 1, x, y);
+    }
+
+    @Override
+    protected boolean hitsNextPage(float x, float y) {
+        // mNextPage is set to INVALID_PAGE whenever we are stationary.
+        // Calculating "next page" this way ensures that you scroll to whatever page you tap on
+        final int current = (mNextPage == INVALID_PAGE) ? mCurrentPage : mNextPage;
+
+        // Only allow tap to next page on large devices, where there's significant margin outside
+        // the active workspace
+        return LauncherApplication.isScreenLarge() && hitsPage(current + 1, x, y);
+    }
+
+    /**
+     * Called directly from a CellLayout (not by the framework), after we've been added as a
+     * listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
+     * that it should intercept touch events, which is not something that is normally supported.
+     */
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        return (isSmall() || !isFinishedSwitchingState());
+    }
+
+    public boolean isSwitchingState() {
+        return mIsSwitchingState;
+    }
+
+    /** This differs from isSwitchingState in that we take into account how far the transition
+     *  has completed. */
+    public boolean isFinishedSwitchingState() {
+        return !mIsSwitchingState || (mTransitionProgress > 0.5f);
+    }
+
+    protected void onWindowVisibilityChanged (int visibility) {
+        mLauncher.onWindowVisibilityChanged(visibility);
+    }
+
+    @Override
+    public boolean dispatchUnhandledMove(View focused, int direction) {
+        if (isSmall() || !isFinishedSwitchingState()) {
+            // when the home screens are shrunken, shouldn't allow side-scrolling
+            return false;
+        }
+        return super.dispatchUnhandledMove(focused, direction);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
+        case MotionEvent.ACTION_DOWN:
+            mXDown = ev.getX();
+            mYDown = ev.getY();
+            break;
+        case MotionEvent.ACTION_POINTER_UP:
+        case MotionEvent.ACTION_UP:
+            if (mTouchState == TOUCH_STATE_REST) {
+                final CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
+                if (!currentPage.lastDownOnOccupiedCell()) {
+                    onWallpaperTap(ev);
+                }
+            }
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    protected void reinflateWidgetsIfNecessary() {
+        final int clCount = getChildCount();
+        for (int i = 0; i < clCount; i++) {
+            CellLayout cl = (CellLayout) getChildAt(i);
+            ShortcutAndWidgetContainer swc = cl.getShortcutsAndWidgets();
+            final int itemCount = swc.getChildCount();
+            for (int j = 0; j < itemCount; j++) {
+                View v = swc.getChildAt(j);
+
+                if (v.getTag() instanceof LauncherAppWidgetInfo) {
+                    LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
+                    LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
+                    if (lahv != null && lahv.orientationChangedSincedInflation()) {
+                        mLauncher.removeAppWidget(info);
+                        // Remove the current widget which is inflated with the wrong orientation
+                        cl.removeView(lahv);
+                        mLauncher.bindAppWidget(info);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void determineScrollingStart(MotionEvent ev) {
+        if (isSmall()) return;
+        if (!isFinishedSwitchingState()) return;
+
+        float deltaX = Math.abs(ev.getX() - mXDown);
+        float deltaY = Math.abs(ev.getY() - mYDown);
+
+        if (Float.compare(deltaX, 0f) == 0) return;
+
+        float slope = deltaY / deltaX;
+        float theta = (float) Math.atan(slope);
+
+        if (deltaX > mTouchSlop || deltaY > mTouchSlop) {
+            cancelCurrentPageLongPress();
+        }
+
+        if (theta > MAX_SWIPE_ANGLE) {
+            // Above MAX_SWIPE_ANGLE, we don't want to ever start scrolling the workspace
+            return;
+        } else if (theta > START_DAMPING_TOUCH_SLOP_ANGLE) {
+            // Above START_DAMPING_TOUCH_SLOP_ANGLE and below MAX_SWIPE_ANGLE, we want to
+            // increase the touch slop to make it harder to begin scrolling the workspace. This
+            // results in vertically scrolling widgets to more easily. The higher the angle, the
+            // more we increase touch slop.
+            theta -= START_DAMPING_TOUCH_SLOP_ANGLE;
+            float extraRatio = (float)
+                    Math.sqrt((theta / (MAX_SWIPE_ANGLE - START_DAMPING_TOUCH_SLOP_ANGLE)));
+            super.determineScrollingStart(ev, 1 + TOUCH_SLOP_DAMPING_FACTOR * extraRatio);
+        } else {
+            // Below START_DAMPING_TOUCH_SLOP_ANGLE, we don't do anything special
+            super.determineScrollingStart(ev);
+        }
+    }
+
+    protected void onPageBeginMoving() {
+        super.onPageBeginMoving();
+
+        if (isHardwareAccelerated()) {
+            updateChildrenLayersEnabled(false);
+        } else {
+            if (mNextPage != INVALID_PAGE) {
+                // we're snapping to a particular screen
+                enableChildrenCache(mCurrentPage, mNextPage);
+            } else {
+                // this is when user is actively dragging a particular screen, they might
+                // swipe it either left or right (but we won't advance by more than one screen)
+                enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
+            }
+        }
+
+        // Only show page outlines as we pan if we are on large screen
+        if (LauncherApplication.isScreenLarge()) {
+            showOutlines();
+            mIsStaticWallpaper = mWallpaperManager.getWallpaperInfo() == null;
+        }
+
+        // If we are not fading in adjacent screens, we still need to restore the alpha in case the
+        // user scrolls while we are transitioning (should not affect dispatchDraw optimizations)
+        if (!mWorkspaceFadeInAdjacentScreens) {
+            for (int i = 0; i < getChildCount(); ++i) {
+                ((CellLayout) getPageAt(i)).setShortcutAndWidgetAlpha(1f);
+            }
+        }
+
+        // Show the scroll indicator as you pan the page
+        showScrollingIndicator(false);
+    }
+
+    protected void onPageEndMoving() {
+        super.onPageEndMoving();
+
+        if (isHardwareAccelerated()) {
+            updateChildrenLayersEnabled(false);
+        } else {
+            clearChildrenCache();
+        }
+
+
+        if (mDragController.isDragging()) {
+            if (isSmall()) {
+                // If we are in springloaded mode, then force an event to check if the current touch
+                // is under a new page (to scroll to)
+                mDragController.forceMoveEvent();
+            }
+        } else {
+            // If we are not mid-dragging, hide the page outlines if we are on a large screen
+            if (LauncherApplication.isScreenLarge()) {
+                hideOutlines();
+            }
+
+            // Hide the scroll indicator as you pan the page
+            if (!mDragController.isDragging()) {
+                hideScrollingIndicator(false);
+            }
+        }
+        mOverScrollMaxBackgroundAlpha = 0.0f;
+
+        if (mDelayedResizeRunnable != null) {
+            mDelayedResizeRunnable.run();
+            mDelayedResizeRunnable = null;
+        }
+
+        if (mDelayedSnapToPageRunnable != null) {
+            mDelayedSnapToPageRunnable.run();
+            mDelayedSnapToPageRunnable = null;
+        }
+    }
+
+    @Override
+    protected void notifyPageSwitchListener() {
+        super.notifyPageSwitchListener();
+        Launcher.setScreen(mCurrentPage);
+    };
+
+    // As a ratio of screen height, the total distance we want the parallax effect to span
+    // horizontally
+    private float wallpaperTravelToScreenWidthRatio(int width, int height) {
+        float aspectRatio = width / (float) height;
+
+        // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
+        // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width
+        // We will use these two data points to extrapolate how much the wallpaper parallax effect
+        // to span (ie travel) at any aspect ratio:
+
+        final float ASPECT_RATIO_LANDSCAPE = 16/10f;
+        final float ASPECT_RATIO_PORTRAIT = 10/16f;
+        final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
+        final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
+
+        // To find out the desired width at different aspect ratios, we use the following two
+        // formulas, where the coefficient on x is the aspect ratio (width/height):
+        //   (16/10)x + y = 1.5
+        //   (10/16)x + y = 1.2
+        // We solve for x and y and end up with a final formula:
+        final float x =
+            (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
+            (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
+        final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
+        return x * aspectRatio + y;
+    }
+
+    // The range of scroll values for Workspace
+    private int getScrollRange() {
+        return getChildOffset(getChildCount() - 1) - getChildOffset(0);
+    }
+
+    protected void setWallpaperDimension() {
+        Point minDims = new Point();
+        Point maxDims = new Point();
+        mLauncher.getWindowManager().getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+
+        final int maxDim = Math.max(maxDims.x, maxDims.y);
+        final int minDim = Math.min(minDims.x, minDims.y);
+
+        // We need to ensure that there is enough extra space in the wallpaper for the intended
+        // parallax effects
+        if (LauncherApplication.isScreenLarge()) {
+            mWallpaperWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
+            mWallpaperHeight = maxDim;
+        } else {
+            mWallpaperWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
+            mWallpaperHeight = maxDim;
+        }
+        new Thread("setWallpaperDimension") {
+            public void run() {
+                mWallpaperManager.suggestDesiredDimensions(mWallpaperWidth, mWallpaperHeight);
+            }
+        }.start();
+    }
+
+    private float wallpaperOffsetForCurrentScroll() {
+        // Set wallpaper offset steps (1 / (number of screens - 1))
+        mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f);
+
+        // For the purposes of computing the scrollRange and overScrollOffset, we assume
+        // that mLayoutScale is 1. This means that when we're in spring-loaded mode,
+        // there's no discrepancy between the wallpaper offset for a given page.
+        float layoutScale = mLayoutScale;
+        mLayoutScale = 1f;
+        int scrollRange = getScrollRange();
+
+        // Again, we adjust the wallpaper offset to be consistent between values of mLayoutScale
+        float adjustedScrollX = Math.max(0, Math.min(getScrollX(), mMaxScrollX));
+        adjustedScrollX *= mWallpaperScrollRatio;
+        mLayoutScale = layoutScale;
+
+        float scrollProgress =
+            adjustedScrollX / (float) scrollRange;
+
+        if (LauncherApplication.isScreenLarge() && mIsStaticWallpaper) {
+            // The wallpaper travel width is how far, from left to right, the wallpaper will move
+            // at this orientation. On tablets in portrait mode we don't move all the way to the
+            // edges of the wallpaper, or otherwise the parallax effect would be too strong.
+            int wallpaperTravelWidth = Math.min(mWallpaperTravelWidth, mWallpaperWidth);
+
+            float offsetInDips = wallpaperTravelWidth * scrollProgress +
+                (mWallpaperWidth - wallpaperTravelWidth) / 2; // center it
+            float offset = offsetInDips / (float) mWallpaperWidth;
+            return offset;
+        } else {
+            return scrollProgress;
+        }
+    }
+
+    private void syncWallpaperOffsetWithScroll() {
+        final boolean enableWallpaperEffects = isHardwareAccelerated();
+        if (enableWallpaperEffects) {
+            mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll());
+        }
+    }
+
+    public void updateWallpaperOffsetImmediately() {
+        mUpdateWallpaperOffsetImmediately = true;
+    }
+
+    private void updateWallpaperOffsets() {
+        boolean updateNow = false;
+        boolean keepUpdating = true;
+        if (mUpdateWallpaperOffsetImmediately) {
+            updateNow = true;
+            keepUpdating = false;
+            mWallpaperOffset.jumpToFinal();
+            mUpdateWallpaperOffsetImmediately = false;
+        } else {
+            updateNow = keepUpdating = mWallpaperOffset.computeScrollOffset();
+        }
+        if (updateNow) {
+            if (mWindowToken != null) {
+                mWallpaperManager.setWallpaperOffsets(mWindowToken,
+                        mWallpaperOffset.getCurrX(), mWallpaperOffset.getCurrY());
+            }
+        }
+        if (keepUpdating) {
+            invalidate();
+        }
+    }
+
+    @Override
+    protected void updateCurrentPageScroll() {
+        super.updateCurrentPageScroll();
+        computeWallpaperScrollRatio(mCurrentPage);
+    }
+
+    @Override
+    protected void snapToPage(int whichPage) {
+        super.snapToPage(whichPage);
+        computeWallpaperScrollRatio(whichPage);
+    }
+
+    @Override
+    protected void snapToPage(int whichPage, int duration) {
+        super.snapToPage(whichPage, duration);
+        computeWallpaperScrollRatio(whichPage);
+    }
+
+    protected void snapToPage(int whichPage, Runnable r) {
+        if (mDelayedSnapToPageRunnable != null) {
+            mDelayedSnapToPageRunnable.run();
+        }
+        mDelayedSnapToPageRunnable = r;
+        snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION);
+    }
+
+    private void computeWallpaperScrollRatio(int page) {
+        // Here, we determine what the desired scroll would be with and without a layout scale,
+        // and compute a ratio between the two. This allows us to adjust the wallpaper offset
+        // as though there is no layout scale.
+        float layoutScale = mLayoutScale;
+        int scaled = getChildOffset(page) - getRelativeChildOffset(page);
+        mLayoutScale = 1.0f;
+        float unscaled = getChildOffset(page) - getRelativeChildOffset(page);
+        mLayoutScale = layoutScale;
+        if (scaled > 0) {
+            mWallpaperScrollRatio = (1.0f * unscaled) / scaled;
+        } else {
+            mWallpaperScrollRatio = 1f;
+        }
+    }
+
+    class WallpaperOffsetInterpolator {
+        float mFinalHorizontalWallpaperOffset = 0.0f;
+        float mFinalVerticalWallpaperOffset = 0.5f;
+        float mHorizontalWallpaperOffset = 0.0f;
+        float mVerticalWallpaperOffset = 0.5f;
+        long mLastWallpaperOffsetUpdateTime;
+        boolean mIsMovingFast;
+        boolean mOverrideHorizontalCatchupConstant;
+        float mHorizontalCatchupConstant = 0.35f;
+        float mVerticalCatchupConstant = 0.35f;
+
+        public WallpaperOffsetInterpolator() {
+        }
+
+        public void setOverrideHorizontalCatchupConstant(boolean override) {
+            mOverrideHorizontalCatchupConstant = override;
+        }
+
+        public void setHorizontalCatchupConstant(float f) {
+            mHorizontalCatchupConstant = f;
+        }
+
+        public void setVerticalCatchupConstant(float f) {
+            mVerticalCatchupConstant = f;
+        }
+
+        public boolean computeScrollOffset() {
+            if (Float.compare(mHorizontalWallpaperOffset, mFinalHorizontalWallpaperOffset) == 0 &&
+                    Float.compare(mVerticalWallpaperOffset, mFinalVerticalWallpaperOffset) == 0) {
+                mIsMovingFast = false;
+                return false;
+            }
+            boolean isLandscape = mDisplaySize.x > mDisplaySize.y;
+
+            long currentTime = System.currentTimeMillis();
+            long timeSinceLastUpdate = currentTime - mLastWallpaperOffsetUpdateTime;
+            timeSinceLastUpdate = Math.min((long) (1000/30f), timeSinceLastUpdate);
+            timeSinceLastUpdate = Math.max(1L, timeSinceLastUpdate);
+
+            float xdiff = Math.abs(mFinalHorizontalWallpaperOffset - mHorizontalWallpaperOffset);
+            if (!mIsMovingFast && xdiff > 0.07) {
+                mIsMovingFast = true;
+            }
+
+            float fractionToCatchUpIn1MsHorizontal;
+            if (mOverrideHorizontalCatchupConstant) {
+                fractionToCatchUpIn1MsHorizontal = mHorizontalCatchupConstant;
+            } else if (mIsMovingFast) {
+                fractionToCatchUpIn1MsHorizontal = isLandscape ? 0.5f : 0.75f;
+            } else {
+                // slow
+                fractionToCatchUpIn1MsHorizontal = isLandscape ? 0.27f : 0.5f;
+            }
+            float fractionToCatchUpIn1MsVertical = mVerticalCatchupConstant;
+
+            fractionToCatchUpIn1MsHorizontal /= 33f;
+            fractionToCatchUpIn1MsVertical /= 33f;
+
+            final float UPDATE_THRESHOLD = 0.00001f;
+            float hOffsetDelta = mFinalHorizontalWallpaperOffset - mHorizontalWallpaperOffset;
+            float vOffsetDelta = mFinalVerticalWallpaperOffset - mVerticalWallpaperOffset;
+            boolean jumpToFinalValue = Math.abs(hOffsetDelta) < UPDATE_THRESHOLD &&
+                Math.abs(vOffsetDelta) < UPDATE_THRESHOLD;
+
+            // Don't have any lag between workspace and wallpaper on non-large devices
+            if (!LauncherApplication.isScreenLarge() || jumpToFinalValue) {
+                mHorizontalWallpaperOffset = mFinalHorizontalWallpaperOffset;
+                mVerticalWallpaperOffset = mFinalVerticalWallpaperOffset;
+            } else {
+                float percentToCatchUpVertical =
+                    Math.min(1.0f, timeSinceLastUpdate * fractionToCatchUpIn1MsVertical);
+                float percentToCatchUpHorizontal =
+                    Math.min(1.0f, timeSinceLastUpdate * fractionToCatchUpIn1MsHorizontal);
+                mHorizontalWallpaperOffset += percentToCatchUpHorizontal * hOffsetDelta;
+                mVerticalWallpaperOffset += percentToCatchUpVertical * vOffsetDelta;
+            }
+
+            mLastWallpaperOffsetUpdateTime = System.currentTimeMillis();
+            return true;
+        }
+
+        public float getCurrX() {
+            return mHorizontalWallpaperOffset;
+        }
+
+        public float getFinalX() {
+            return mFinalHorizontalWallpaperOffset;
+        }
+
+        public float getCurrY() {
+            return mVerticalWallpaperOffset;
+        }
+
+        public float getFinalY() {
+            return mFinalVerticalWallpaperOffset;
+        }
+
+        public void setFinalX(float x) {
+            mFinalHorizontalWallpaperOffset = Math.max(0f, Math.min(x, 1.0f));
+        }
+
+        public void setFinalY(float y) {
+            mFinalVerticalWallpaperOffset = Math.max(0f, Math.min(y, 1.0f));
+        }
+
+        public void jumpToFinal() {
+            mHorizontalWallpaperOffset = mFinalHorizontalWallpaperOffset;
+            mVerticalWallpaperOffset = mFinalVerticalWallpaperOffset;
+        }
+    }
+
+    @Override
+    public void computeScroll() {
+        super.computeScroll();
+        syncWallpaperOffsetWithScroll();
+    }
+
+    void showOutlines() {
+        if (!isSmall() && !mIsSwitchingState) {
+            if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
+            if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
+            mChildrenOutlineFadeInAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 1.0f);
+            mChildrenOutlineFadeInAnimation.setDuration(CHILDREN_OUTLINE_FADE_IN_DURATION);
+            mChildrenOutlineFadeInAnimation.start();
+        }
+    }
+
+    void hideOutlines() {
+        if (!isSmall() && !mIsSwitchingState) {
+            if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
+            if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
+            mChildrenOutlineFadeOutAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 0.0f);
+            mChildrenOutlineFadeOutAnimation.setDuration(CHILDREN_OUTLINE_FADE_OUT_DURATION);
+            mChildrenOutlineFadeOutAnimation.setStartDelay(CHILDREN_OUTLINE_FADE_OUT_DELAY);
+            mChildrenOutlineFadeOutAnimation.start();
+        }
+    }
+
+    public void showOutlinesTemporarily() {
+        if (!mIsPageMoving && !isTouchActive()) {
+            snapToPage(mCurrentPage);
+        }
+    }
+
+    public void setChildrenOutlineAlpha(float alpha) {
+        mChildrenOutlineAlpha = alpha;
+        for (int i = 0; i < getChildCount(); i++) {
+            CellLayout cl = (CellLayout) getChildAt(i);
+            cl.setBackgroundAlpha(alpha);
+        }
+    }
+
+    public float getChildrenOutlineAlpha() {
+        return mChildrenOutlineAlpha;
+    }
+
+    void disableBackground() {
+        mDrawBackground = false;
+    }
+    void enableBackground() {
+        mDrawBackground = true;
+    }
+
+    private void animateBackgroundGradient(float finalAlpha, boolean animated) {
+        if (mBackground == null) return;
+        if (mBackgroundFadeInAnimation != null) {
+            mBackgroundFadeInAnimation.cancel();
+            mBackgroundFadeInAnimation = null;
+        }
+        if (mBackgroundFadeOutAnimation != null) {
+            mBackgroundFadeOutAnimation.cancel();
+            mBackgroundFadeOutAnimation = null;
+        }
+        float startAlpha = getBackgroundAlpha();
+        if (finalAlpha != startAlpha) {
+            if (animated) {
+                mBackgroundFadeOutAnimation = LauncherAnimUtils.ofFloat(startAlpha, finalAlpha);
+                mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        setBackgroundAlpha(((Float) animation.getAnimatedValue()).floatValue());
+                    }
+                });
+                mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
+                mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
+                mBackgroundFadeOutAnimation.start();
+            } else {
+                setBackgroundAlpha(finalAlpha);
+            }
+        }
+    }
+
+    public void setBackgroundAlpha(float alpha) {
+        if (alpha != mBackgroundAlpha) {
+            mBackgroundAlpha = alpha;
+            invalidate();
+        }
+    }
+
+    public float getBackgroundAlpha() {
+        return mBackgroundAlpha;
+    }
+
+    float backgroundAlphaInterpolator(float r) {
+        float pivotA = 0.1f;
+        float pivotB = 0.4f;
+        if (r < pivotA) {
+            return 0;
+        } else if (r > pivotB) {
+            return 1.0f;
+        } else {
+            return (r - pivotA)/(pivotB - pivotA);
+        }
+    }
+
+    float overScrollBackgroundAlphaInterpolator(float r) {
+        float threshold = 0.08f;
+
+        if (r > mOverScrollMaxBackgroundAlpha) {
+            mOverScrollMaxBackgroundAlpha = r;
+        } else if (r < mOverScrollMaxBackgroundAlpha) {
+            r = mOverScrollMaxBackgroundAlpha;
+        }
+
+        return Math.min(r / threshold, 1.0f);
+    }
+
+    private void updatePageAlphaValues(int screenCenter) {
+        boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
+        if (mWorkspaceFadeInAdjacentScreens &&
+                mState == State.NORMAL &&
+                !mIsSwitchingState &&
+                !isInOverscroll) {
+            for (int i = 0; i < getChildCount(); i++) {
+                CellLayout child = (CellLayout) getChildAt(i);
+                if (child != null) {
+                    float scrollProgress = getScrollProgress(screenCenter, child, i);
+                    float alpha = 1 - Math.abs(scrollProgress);
+                    child.getShortcutsAndWidgets().setAlpha(alpha);
+                    if (!mIsDragOccuring) {
+                        child.setBackgroundAlphaMultiplier(
+                                backgroundAlphaInterpolator(Math.abs(scrollProgress)));
+                    } else {
+                        child.setBackgroundAlphaMultiplier(1f);
+                    }
+                }
+            }
+        }
+    }
+
+    private void setChildrenBackgroundAlphaMultipliers(float a) {
+        for (int i = 0; i < getChildCount(); i++) {
+            CellLayout child = (CellLayout) getChildAt(i);
+            child.setBackgroundAlphaMultiplier(a);
+        }
+    }
+
+    @Override
+    protected void screenScrolled(int screenCenter) {
+        super.screenScrolled(screenCenter);
+
+        updatePageAlphaValues(screenCenter);
+        enableHwLayersOnVisiblePages();
+
+        if (mOverScrollX < 0 || mOverScrollX > mMaxScrollX) {
+            int index = mOverScrollX < 0 ? 0 : getChildCount() - 1;
+            CellLayout cl = (CellLayout) getChildAt(index);
+            float scrollProgress = getScrollProgress(screenCenter, cl, index);
+            cl.setOverScrollAmount(Math.abs(scrollProgress), index == 0);
+            float rotation = - WORKSPACE_OVERSCROLL_ROTATION * scrollProgress;
+            cl.setRotationY(rotation);
+            setFadeForOverScroll(Math.abs(scrollProgress));
+            if (!mOverscrollTransformsSet) {
+                mOverscrollTransformsSet = true;
+                cl.setCameraDistance(mDensity * mCameraDistance);
+                cl.setPivotX(cl.getMeasuredWidth() * (index == 0 ? 0.75f : 0.25f));
+                cl.setPivotY(cl.getMeasuredHeight() * 0.5f);
+                cl.setOverscrollTransformsDirty(true);
+            }
+        } else {
+            if (mOverscrollFade != 0) {
+                setFadeForOverScroll(0);
+            }
+            if (mOverscrollTransformsSet) {
+                mOverscrollTransformsSet = false;
+                ((CellLayout) getChildAt(0)).resetOverscrollTransforms();
+                ((CellLayout) getChildAt(getChildCount() - 1)).resetOverscrollTransforms();
+            }
+        }
+    }
+
+    @Override
+    protected void overScroll(float amount) {
+        acceleratedOverScroll(amount);
+    }
+
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mWindowToken = getWindowToken();
+        computeScroll();
+        mDragController.setWindowToken(mWindowToken);
+    }
+
+    protected void onDetachedFromWindow() {
+        mWindowToken = null;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
+            mUpdateWallpaperOffsetImmediately = true;
+        }
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        updateWallpaperOffsets();
+
+        // Draw the background gradient if necessary
+        if (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground) {
+            int alpha = (int) (mBackgroundAlpha * 255);
+            mBackground.setAlpha(alpha);
+            mBackground.setBounds(getScrollX(), 0, getScrollX() + getMeasuredWidth(),
+                    getMeasuredHeight());
+            mBackground.draw(canvas);
+        }
+
+        super.onDraw(canvas);
+
+        // Call back to LauncherModel to finish binding after the first draw
+        post(mBindPages);
+    }
+
+    boolean isDrawingBackgroundGradient() {
+        return (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground);
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        if (!mLauncher.isAllAppsVisible()) {
+            final Folder openFolder = getOpenFolder();
+            if (openFolder != null) {
+                return openFolder.requestFocus(direction, previouslyFocusedRect);
+            } else {
+                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int getDescendantFocusability() {
+        if (isSmall()) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
+
+    @Override
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        if (!mLauncher.isAllAppsVisible()) {
+            final Folder openFolder = getOpenFolder();
+            if (openFolder != null) {
+                openFolder.addFocusables(views, direction);
+            } else {
+                super.addFocusables(views, direction, focusableMode);
+            }
+        }
+    }
+
+    public boolean isSmall() {
+        return mState == State.SMALL || mState == State.SPRING_LOADED;
+    }
+
+    void enableChildrenCache(int fromPage, int toPage) {
+        if (fromPage > toPage) {
+            final int temp = fromPage;
+            fromPage = toPage;
+            toPage = temp;
+        }
+
+        final int screenCount = getChildCount();
+
+        fromPage = Math.max(fromPage, 0);
+        toPage = Math.min(toPage, screenCount - 1);
+
+        for (int i = fromPage; i <= toPage; i++) {
+            final CellLayout layout = (CellLayout) getChildAt(i);
+            layout.setChildrenDrawnWithCacheEnabled(true);
+            layout.setChildrenDrawingCacheEnabled(true);
+        }
+    }
+
+    void clearChildrenCache() {
+        final int screenCount = getChildCount();
+        for (int i = 0; i < screenCount; i++) {
+            final CellLayout layout = (CellLayout) getChildAt(i);
+            layout.setChildrenDrawnWithCacheEnabled(false);
+            // In software mode, we don't want the items to continue to be drawn into bitmaps
+            if (!isHardwareAccelerated()) {
+                layout.setChildrenDrawingCacheEnabled(false);
+            }
+        }
+    }
+
+
+    private void updateChildrenLayersEnabled(boolean force) {
+        boolean small = mState == State.SMALL || mIsSwitchingState;
+        boolean enableChildrenLayers = force || small || mAnimatingViewIntoPlace || isPageMoving();
+
+        if (enableChildrenLayers != mChildrenLayersEnabled) {
+            mChildrenLayersEnabled = enableChildrenLayers;
+            if (mChildrenLayersEnabled) {
+                enableHwLayersOnVisiblePages();
+            } else {
+                for (int i = 0; i < getPageCount(); i++) {
+                    final CellLayout cl = (CellLayout) getChildAt(i);
+                    cl.disableHardwareLayers();
+                }
+            }
+        }
+    }
+
+    private void enableHwLayersOnVisiblePages() {
+        if (mChildrenLayersEnabled) {
+            final int screenCount = getChildCount();
+            getVisiblePages(mTempVisiblePagesRange);
+            int leftScreen = mTempVisiblePagesRange[0];
+            int rightScreen = mTempVisiblePagesRange[1];
+            if (leftScreen == rightScreen) {
+                // make sure we're caching at least two pages always
+                if (rightScreen < screenCount - 1) {
+                    rightScreen++;
+                } else if (leftScreen > 0) {
+                    leftScreen--;
+                }
+            }
+            for (int i = 0; i < screenCount; i++) {
+                final CellLayout layout = (CellLayout) getChildAt(i);
+                if (!(leftScreen <= i && i <= rightScreen && shouldDrawChild(layout))) {
+                    layout.disableHardwareLayers();
+                }
+            }
+            for (int i = 0; i < screenCount; i++) {
+                final CellLayout layout = (CellLayout) getChildAt(i);
+                if (leftScreen <= i && i <= rightScreen && shouldDrawChild(layout)) {
+                    layout.enableHardwareLayers();
+                }
+            }
+        }
+    }
+
+    public void buildPageHardwareLayers() {
+        // force layers to be enabled just for the call to buildLayer
+        updateChildrenLayersEnabled(true);
+        if (getWindowToken() != null) {
+            final int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                CellLayout cl = (CellLayout) getChildAt(i);
+                cl.buildHardwareLayer();
+            }
+        }
+        updateChildrenLayersEnabled(false);
+    }
+
+    protected void onWallpaperTap(MotionEvent ev) {
+        final int[] position = mTempCell;
+        getLocationOnScreen(position);
+
+        int pointerIndex = ev.getActionIndex();
+        position[0] += (int) ev.getX(pointerIndex);
+        position[1] += (int) ev.getY(pointerIndex);
+
+        mWallpaperManager.sendWallpaperCommand(getWindowToken(),
+                ev.getAction() == MotionEvent.ACTION_UP
+                        ? WallpaperManager.COMMAND_TAP : WallpaperManager.COMMAND_SECONDARY_TAP,
+                position[0], position[1], 0, null);
+    }
+
+    /*
+     * This interpolator emulates the rate at which the perceived scale of an object changes
+     * as its distance from a camera increases. When this interpolator is applied to a scale
+     * animation on a view, it evokes the sense that the object is shrinking due to moving away
+     * from the camera.
+     */
+    static class ZInterpolator implements TimeInterpolator {
+        private float focalLength;
+
+        public ZInterpolator(float foc) {
+            focalLength = foc;
+        }
+
+        public float getInterpolation(float input) {
+            return (1.0f - focalLength / (focalLength + input)) /
+                (1.0f - focalLength / (focalLength + 1.0f));
+        }
+    }
+
+    /*
+     * The exact reverse of ZInterpolator.
+     */
+    static class InverseZInterpolator implements TimeInterpolator {
+        private ZInterpolator zInterpolator;
+        public InverseZInterpolator(float foc) {
+            zInterpolator = new ZInterpolator(foc);
+        }
+        public float getInterpolation(float input) {
+            return 1 - zInterpolator.getInterpolation(1 - input);
+        }
+    }
+
+    /*
+     * ZInterpolator compounded with an ease-out.
+     */
+    static class ZoomOutInterpolator implements TimeInterpolator {
+        private final DecelerateInterpolator decelerate = new DecelerateInterpolator(0.75f);
+        private final ZInterpolator zInterpolator = new ZInterpolator(0.13f);
+
+        public float getInterpolation(float input) {
+            return decelerate.getInterpolation(zInterpolator.getInterpolation(input));
+        }
+    }
+
+    /*
+     * InverseZInterpolator compounded with an ease-out.
+     */
+    static class ZoomInInterpolator implements TimeInterpolator {
+        private final InverseZInterpolator inverseZInterpolator = new InverseZInterpolator(0.35f);
+        private final DecelerateInterpolator decelerate = new DecelerateInterpolator(3.0f);
+
+        public float getInterpolation(float input) {
+            return decelerate.getInterpolation(inverseZInterpolator.getInterpolation(input));
+        }
+    }
+
+    private final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
+
+    /*
+    *
+    * We call these methods (onDragStartedWithItemSpans/onDragStartedWithSize) whenever we
+    * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
+    *
+    * These methods mark the appropriate pages as accepting drops (which alters their visual
+    * appearance).
+    *
+    */
+    public void onDragStartedWithItem(View v) {
+        final Canvas canvas = new Canvas();
+
+        // The outline is used to visualize where the item will land if dropped
+        mDragOutline = createDragOutline(v, canvas, DRAG_BITMAP_PADDING);
+    }
+
+    public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, boolean clipAlpha) {
+        final Canvas canvas = new Canvas();
+
+        int[] size = estimateItemSize(info.spanX, info.spanY, info, false);
+
+        // The outline is used to visualize where the item will land if dropped
+        mDragOutline = createDragOutline(b, canvas, DRAG_BITMAP_PADDING, size[0],
+                size[1], clipAlpha);
+    }
+
+    public void exitWidgetResizeMode() {
+        DragLayer dragLayer = mLauncher.getDragLayer();
+        dragLayer.clearAllResizeFrames();
+    }
+
+    private void initAnimationArrays() {
+        final int childCount = getChildCount();
+        if (mOldTranslationXs != null) return;
+        mOldTranslationXs = new float[childCount];
+        mOldTranslationYs = new float[childCount];
+        mOldScaleXs = new float[childCount];
+        mOldScaleYs = new float[childCount];
+        mOldBackgroundAlphas = new float[childCount];
+        mOldAlphas = new float[childCount];
+        mNewTranslationXs = new float[childCount];
+        mNewTranslationYs = new float[childCount];
+        mNewScaleXs = new float[childCount];
+        mNewScaleYs = new float[childCount];
+        mNewBackgroundAlphas = new float[childCount];
+        mNewAlphas = new float[childCount];
+        mNewRotationYs = new float[childCount];
+    }
+
+    Animator getChangeStateAnimation(final State state, boolean animated) {
+        return getChangeStateAnimation(state, animated, 0);
+    }
+
+    Animator getChangeStateAnimation(final State state, boolean animated, int delay) {
+        if (mState == state) {
+            return null;
+        }
+
+        // Initialize animation arrays for the first time if necessary
+        initAnimationArrays();
+
+        AnimatorSet anim = animated ? LauncherAnimUtils.createAnimatorSet() : null;
+
+        // Stop any scrolling, move to the current page right away
+        setCurrentPage(getNextPage());
+
+        final State oldState = mState;
+        final boolean oldStateIsNormal = (oldState == State.NORMAL);
+        final boolean oldStateIsSpringLoaded = (oldState == State.SPRING_LOADED);
+        final boolean oldStateIsSmall = (oldState == State.SMALL);
+        mState = state;
+        final boolean stateIsNormal = (state == State.NORMAL);
+        final boolean stateIsSpringLoaded = (state == State.SPRING_LOADED);
+        final boolean stateIsSmall = (state == State.SMALL);
+        float finalScaleFactor = 1.0f;
+        float finalBackgroundAlpha = stateIsSpringLoaded ? 1.0f : 0f;
+        float translationX = 0;
+        float translationY = 0;
+        boolean zoomIn = true;
+
+        if (state != State.NORMAL) {
+            finalScaleFactor = mSpringLoadedShrinkFactor - (stateIsSmall ? 0.1f : 0);
+            setPageSpacing(mSpringLoadedPageSpacing);
+            if (oldStateIsNormal && stateIsSmall) {
+                zoomIn = false;
+                setLayoutScale(finalScaleFactor);
+                updateChildrenLayersEnabled(false);
+            } else {
+                finalBackgroundAlpha = 1.0f;
+                setLayoutScale(finalScaleFactor);
+            }
+        } else {
+            setPageSpacing(mOriginalPageSpacing);
+            setLayoutScale(1.0f);
+        }
+
+        final int duration = zoomIn ?
+                getResources().getInteger(R.integer.config_workspaceUnshrinkTime) :
+                getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
+        for (int i = 0; i < getChildCount(); i++) {
+            final CellLayout cl = (CellLayout) getChildAt(i);
+            float finalAlpha = (!mWorkspaceFadeInAdjacentScreens || stateIsSpringLoaded ||
+                    (i == mCurrentPage)) ? 1f : 0f;
+            float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
+            float initialAlpha = currentAlpha;
+
+            // Determine the pages alpha during the state transition
+            if ((oldStateIsSmall && stateIsNormal) ||
+                (oldStateIsNormal && stateIsSmall)) {
+                // To/from workspace - only show the current page unless the transition is not
+                //                     animated and the animation end callback below doesn't run;
+                //                     or, if we're in spring-loaded mode
+                if (i == mCurrentPage || !animated || oldStateIsSpringLoaded) {
+                    finalAlpha = 1f;
+                } else {
+                    initialAlpha = 0f;
+                    finalAlpha = 0f;
+                }
+            }
+
+            mOldAlphas[i] = initialAlpha;
+            mNewAlphas[i] = finalAlpha;
+            if (animated) {
+                mOldTranslationXs[i] = cl.getTranslationX();
+                mOldTranslationYs[i] = cl.getTranslationY();
+                mOldScaleXs[i] = cl.getScaleX();
+                mOldScaleYs[i] = cl.getScaleY();
+                mOldBackgroundAlphas[i] = cl.getBackgroundAlpha();
+
+                mNewTranslationXs[i] = translationX;
+                mNewTranslationYs[i] = translationY;
+                mNewScaleXs[i] = finalScaleFactor;
+                mNewScaleYs[i] = finalScaleFactor;
+                mNewBackgroundAlphas[i] = finalBackgroundAlpha;
+            } else {
+                cl.setTranslationX(translationX);
+                cl.setTranslationY(translationY);
+                cl.setScaleX(finalScaleFactor);
+                cl.setScaleY(finalScaleFactor);
+                cl.setBackgroundAlpha(finalBackgroundAlpha);
+                cl.setShortcutAndWidgetAlpha(finalAlpha);
+            }
+        }
+
+        if (animated) {
+            for (int index = 0; index < getChildCount(); index++) {
+                final int i = index;
+                final CellLayout cl = (CellLayout) getChildAt(i);
+                float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
+                if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
+                    cl.setTranslationX(mNewTranslationXs[i]);
+                    cl.setTranslationY(mNewTranslationYs[i]);
+                    cl.setScaleX(mNewScaleXs[i]);
+                    cl.setScaleY(mNewScaleYs[i]);
+                    cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
+                    cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
+                    cl.setRotationY(mNewRotationYs[i]);
+                } else {
+                    LauncherViewPropertyAnimator a = new LauncherViewPropertyAnimator(cl);
+                    a.translationX(mNewTranslationXs[i])
+                        .translationY(mNewTranslationYs[i])
+                        .scaleX(mNewScaleXs[i])
+                        .scaleY(mNewScaleYs[i])
+                        .setDuration(duration)
+                        .setInterpolator(mZoomInInterpolator);
+                    anim.play(a);
+
+                    if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
+                        LauncherViewPropertyAnimator alphaAnim =
+                            new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
+                        alphaAnim.alpha(mNewAlphas[i])
+                            .setDuration(duration)
+                            .setInterpolator(mZoomInInterpolator);
+                        anim.play(alphaAnim);
+                    }
+                    if (mOldBackgroundAlphas[i] != 0 ||
+                        mNewBackgroundAlphas[i] != 0) {
+                        ValueAnimator bgAnim = LauncherAnimUtils.ofFloat(0f, 1f).setDuration(duration);
+                        bgAnim.setInterpolator(mZoomInInterpolator);
+                        bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                                public void onAnimationUpdate(float a, float b) {
+                                    cl.setBackgroundAlpha(
+                                            a * mOldBackgroundAlphas[i] +
+                                            b * mNewBackgroundAlphas[i]);
+                                }
+                            });
+                        anim.play(bgAnim);
+                    }
+                }
+            }
+            buildPageHardwareLayers();
+            anim.setStartDelay(delay);
+        }
+
+        if (stateIsSpringLoaded) {
+            // Right now we're covered by Apps Customize
+            // Show the background gradient immediately, so the gradient will
+            // be showing once AppsCustomize disappears
+            animateBackgroundGradient(getResources().getInteger(
+                    R.integer.config_appsCustomizeSpringLoadedBgAlpha) / 100f, false);
+        } else {
+            // Fade the background gradient away
+            animateBackgroundGradient(0f, true);
+        }
+        return anim;
+    }
+
+    @Override
+    public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
+        mIsSwitchingState = true;
+        cancelScrollingIndicatorAnimations();
+    }
+
+    @Override
+    public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
+    }
+
+    @Override
+    public void onLauncherTransitionStep(Launcher l, float t) {
+        mTransitionProgress = t;
+    }
+
+    @Override
+    public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
+        mIsSwitchingState = false;
+        mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
+        updateChildrenLayersEnabled(false);
+        // The code in getChangeStateAnimation to determine initialAlpha and finalAlpha will ensure
+        // ensure that only the current page is visible during (and subsequently, after) the
+        // transition animation.  If fade adjacent pages is disabled, then re-enable the page
+        // visibility after the transition animation.
+        if (!mWorkspaceFadeInAdjacentScreens) {
+            for (int i = 0; i < getChildCount(); i++) {
+                final CellLayout cl = (CellLayout) getChildAt(i);
+                cl.setShortcutAndWidgetAlpha(1f);
+            }
+        }
+    }
+
+    @Override
+    public View getContent() {
+        return this;
+    }
+
+    /**
+     * Draw the View v into the given Canvas.
+     *
+     * @param v the view to draw
+     * @param destCanvas the canvas to draw on
+     * @param padding the horizontal and vertical padding to use when drawing
+     */
+    private void drawDragView(View v, Canvas destCanvas, int padding, boolean pruneToDrawable) {
+        final Rect clipRect = mTempRect;
+        v.getDrawingRect(clipRect);
+
+        boolean textVisible = false;
+
+        destCanvas.save();
+        if (v instanceof TextView && pruneToDrawable) {
+            Drawable d = ((TextView) v).getCompoundDrawables()[1];
+            clipRect.set(0, 0, d.getIntrinsicWidth() + padding, d.getIntrinsicHeight() + padding);
+            destCanvas.translate(padding / 2, padding / 2);
+            d.draw(destCanvas);
+        } else {
+            if (v instanceof FolderIcon) {
+                // For FolderIcons the text can bleed into the icon area, and so we need to
+                // hide the text completely (which can't be achieved by clipping).
+                if (((FolderIcon) v).getTextVisible()) {
+                    ((FolderIcon) v).setTextVisible(false);
+                    textVisible = true;
+                }
+            } else if (v instanceof BubbleTextView) {
+                final BubbleTextView tv = (BubbleTextView) v;
+                clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V +
+                        tv.getLayout().getLineTop(0);
+            } else if (v instanceof TextView) {
+                final TextView tv = (TextView) v;
+                clipRect.bottom = tv.getExtendedPaddingTop() - tv.getCompoundDrawablePadding() +
+                        tv.getLayout().getLineTop(0);
+            }
+            destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
+            destCanvas.clipRect(clipRect, Op.REPLACE);
+            v.draw(destCanvas);
+
+            // Restore text visibility of FolderIcon if necessary
+            if (textVisible) {
+                ((FolderIcon) v).setTextVisible(true);
+            }
+        }
+        destCanvas.restore();
+    }
+
+    /**
+     * Returns a new bitmap to show when the given View is being dragged around.
+     * Responsibility for the bitmap is transferred to the caller.
+     */
+    public Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
+        Bitmap b;
+
+        if (v instanceof TextView) {
+            Drawable d = ((TextView) v).getCompoundDrawables()[1];
+            b = Bitmap.createBitmap(d.getIntrinsicWidth() + padding,
+                    d.getIntrinsicHeight() + padding, Bitmap.Config.ARGB_8888);
+        } else {
+            b = Bitmap.createBitmap(
+                    v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
+        }
+
+        canvas.setBitmap(b);
+        drawDragView(v, canvas, padding, true);
+        canvas.setBitmap(null);
+
+        return b;
+    }
+
+    /**
+     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
+     * Responsibility for the bitmap is transferred to the caller.
+     */
+    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
+        final int outlineColor = getResources().getColor(android.R.color.holo_blue_light);
+        final Bitmap b = Bitmap.createBitmap(
+                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
+
+        canvas.setBitmap(b);
+        drawDragView(v, canvas, padding, true);
+        mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
+        canvas.setBitmap(null);
+        return b;
+    }
+
+    /**
+     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
+     * Responsibility for the bitmap is transferred to the caller.
+     */
+    private Bitmap createDragOutline(Bitmap orig, Canvas canvas, int padding, int w, int h,
+            boolean clipAlpha) {
+        final int outlineColor = getResources().getColor(android.R.color.holo_blue_light);
+        final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        canvas.setBitmap(b);
+
+        Rect src = new Rect(0, 0, orig.getWidth(), orig.getHeight());
+        float scaleFactor = Math.min((w - padding) / (float) orig.getWidth(),
+                (h - padding) / (float) orig.getHeight());
+        int scaledWidth = (int) (scaleFactor * orig.getWidth());
+        int scaledHeight = (int) (scaleFactor * orig.getHeight());
+        Rect dst = new Rect(0, 0, scaledWidth, scaledHeight);
+
+        // center the image
+        dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2);
+
+        canvas.drawBitmap(orig, src, dst, null);
+        mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor,
+                clipAlpha);
+        canvas.setBitmap(null);
+
+        return b;
+    }
+
+    void startDrag(CellLayout.CellInfo cellInfo) {
+        View child = cellInfo.cell;
+
+        // Make sure the drag was started by a long press as opposed to a long click.
+        if (!child.isInTouchMode()) {
+            return;
+        }
+
+        mDragInfo = cellInfo;
+        child.setVisibility(INVISIBLE);
+        CellLayout layout = (CellLayout) child.getParent().getParent();
+        layout.prepareChildForDrag(child);
+
+        child.clearFocus();
+        child.setPressed(false);
+
+        final Canvas canvas = new Canvas();
+
+        // The outline is used to visualize where the item will land if dropped
+        mDragOutline = createDragOutline(child, canvas, DRAG_BITMAP_PADDING);
+        beginDragShared(child, this);
+    }
+
+    public void beginDragShared(View child, DragSource source) {
+        Resources r = getResources();
+
+        // The drag bitmap follows the touch point around on the screen
+        final Bitmap b = createDragBitmap(child, new Canvas(), DRAG_BITMAP_PADDING);
+
+        final int bmpWidth = b.getWidth();
+        final int bmpHeight = b.getHeight();
+
+        float scale = mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
+        int dragLayerX =
+                Math.round(mTempXY[0] - (bmpWidth - scale * child.getWidth()) / 2);
+        int dragLayerY =
+                Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2
+                        - DRAG_BITMAP_PADDING / 2);
+
+        Point dragVisualizeOffset = null;
+        Rect dragRect = null;
+        if (child instanceof BubbleTextView || child instanceof PagedViewIcon) {
+            int iconSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
+            int iconPaddingTop = r.getDimensionPixelSize(R.dimen.app_icon_padding_top);
+            int top = child.getPaddingTop();
+            int left = (bmpWidth - iconSize) / 2;
+            int right = left + iconSize;
+            int bottom = top + iconSize;
+            dragLayerY += top;
+            // Note: The drag region is used to calculate drag layer offsets, but the
+            // dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
+            dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2,
+                    iconPaddingTop - DRAG_BITMAP_PADDING / 2);
+            dragRect = new Rect(left, top, right, bottom);
+        } else if (child instanceof FolderIcon) {
+            int previewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
+            dragRect = new Rect(0, 0, child.getWidth(), previewSize);
+        }
+
+        // Clear the pressed state if necessary
+        if (child instanceof BubbleTextView) {
+            BubbleTextView icon = (BubbleTextView) child;
+            icon.clearPressedOrFocusedBackground();
+        }
+
+        mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
+                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
+        b.recycle();
+
+        // Show the scrolling indicator when you pick up an item
+        showScrollingIndicator(false);
+    }
+
+    void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, int screen,
+            int cellX, int cellY, boolean insertAtFirst, int intersectX, int intersectY) {
+        View view = mLauncher.createShortcut(R.layout.application, target, (ShortcutInfo) info);
+
+        final int[] cellXY = new int[2];
+        target.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
+        addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
+        LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen, cellXY[0],
+                cellXY[1]);
+    }
+
+    public boolean transitionStateShouldAllowDrop() {
+        return ((!isSwitchingState() || mTransitionProgress > 0.5f) && mState != State.SMALL);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean acceptDrop(DragObject d) {
+        // If it's an external drop (e.g. from All Apps), check if it should be accepted
+        CellLayout dropTargetLayout = mDropToLayout;
+        if (d.dragSource != this) {
+            // Don't accept the drop if we're not over a screen at time of drop
+            if (dropTargetLayout == null) {
+                return false;
+            }
+            if (!transitionStateShouldAllowDrop()) return false;
+
+            mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
+                    d.dragView, mDragViewVisualCenter);
+
+            // We want the point to be mapped to the dragTarget.
+            if (mLauncher.isHotseatLayout(dropTargetLayout)) {
+                mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
+            } else {
+                mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null);
+            }
+
+            int spanX = 1;
+            int spanY = 1;
+            if (mDragInfo != null) {
+                final CellLayout.CellInfo dragCellInfo = mDragInfo;
+                spanX = dragCellInfo.spanX;
+                spanY = dragCellInfo.spanY;
+            } else {
+                final ItemInfo dragInfo = (ItemInfo) d.dragInfo;
+                spanX = dragInfo.spanX;
+                spanY = dragInfo.spanY;
+            }
+
+            int minSpanX = spanX;
+            int minSpanY = spanY;
+            if (d.dragInfo instanceof PendingAddWidgetInfo) {
+                minSpanX = ((PendingAddWidgetInfo) d.dragInfo).minSpanX;
+                minSpanY = ((PendingAddWidgetInfo) d.dragInfo).minSpanY;
+            }
+
+            mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1], minSpanX, minSpanY, dropTargetLayout,
+                    mTargetCell);
+            float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
+                    mDragViewVisualCenter[1], mTargetCell);
+            if (willCreateUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,
+                    mTargetCell, distance, true)) {
+                return true;
+            }
+            if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,
+                    mTargetCell, distance)) {
+                return true;
+            }
+
+            int[] resultSpan = new int[2];
+            mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
+                    null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP);
+            boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
+
+            // Don't accept the drop if there's no room for the item
+            if (!foundCell) {
+                // Don't show the message if we are dropping on the AllApps button and the hotseat
+                // is full
+                boolean isHotseat = mLauncher.isHotseatLayout(dropTargetLayout);
+                if (mTargetCell != null && isHotseat) {
+                    Hotseat hotseat = mLauncher.getHotseat();
+                    if (hotseat.isAllAppsButtonRank(
+                            hotseat.getOrderInHotseat(mTargetCell[0], mTargetCell[1]))) {
+                        return false;
+                    }
+                }
+
+                mLauncher.showOutOfSpaceMessage(isHotseat);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell, float
+            distance, boolean considerTimeout) {
+        if (distance > mMaxDistanceForFolderCreation) return false;
+        View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
+
+        if (dropOverView != null) {
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) dropOverView.getLayoutParams();
+            if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.tmpCellY)) {
+                return false;
+            }
+        }
+
+        boolean hasntMoved = false;
+        if (mDragInfo != null) {
+            hasntMoved = dropOverView == mDragInfo.cell;
+        }
+
+        if (dropOverView == null || hasntMoved || (considerTimeout && !mCreateUserFolderOnDrop)) {
+            return false;
+        }
+
+        boolean aboveShortcut = (dropOverView.getTag() instanceof ShortcutInfo);
+        boolean willBecomeShortcut =
+                (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+                info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
+
+        return (aboveShortcut && willBecomeShortcut);
+    }
+
+    boolean willAddToExistingUserFolder(Object dragInfo, CellLayout target, int[] targetCell,
+            float distance) {
+        if (distance > mMaxDistanceForFolderCreation) return false;
+        View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
+
+        if (dropOverView != null) {
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) dropOverView.getLayoutParams();
+            if (lp.useTmpCoords && (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.tmpCellY)) {
+                return false;
+            }
+        }
+
+        if (dropOverView instanceof FolderIcon) {
+            FolderIcon fi = (FolderIcon) dropOverView;
+            if (fi.acceptDrop(dragInfo)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
+            int[] targetCell, float distance, boolean external, DragView dragView,
+            Runnable postAnimationRunnable) {
+        if (distance > mMaxDistanceForFolderCreation) return false;
+        View v = target.getChildAt(targetCell[0], targetCell[1]);
+
+        boolean hasntMoved = false;
+        if (mDragInfo != null) {
+            CellLayout cellParent = getParentCellLayoutForView(mDragInfo.cell);
+            hasntMoved = (mDragInfo.cellX == targetCell[0] &&
+                    mDragInfo.cellY == targetCell[1]) && (cellParent == target);
+        }
+
+        if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;
+        mCreateUserFolderOnDrop = false;
+        final int screen = (targetCell == null) ? mDragInfo.screen : indexOfChild(target);
+
+        boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
+        boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
+
+        if (aboveShortcut && willBecomeShortcut) {
+            ShortcutInfo sourceInfo = (ShortcutInfo) newView.getTag();
+            ShortcutInfo destInfo = (ShortcutInfo) v.getTag();
+            // if the drag started here, we need to remove it from the workspace
+            if (!external) {
+                getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
+            }
+
+            Rect folderLocation = new Rect();
+            float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
+            target.removeView(v);
+
+            FolderIcon fi =
+                mLauncher.addFolder(target, container, screen, targetCell[0], targetCell[1]);
+            destInfo.cellX = -1;
+            destInfo.cellY = -1;
+            sourceInfo.cellX = -1;
+            sourceInfo.cellY = -1;
+
+            // If the dragView is null, we can't animate
+            boolean animate = dragView != null;
+            if (animate) {
+                fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale,
+                        postAnimationRunnable);
+            } else {
+                fi.addItem(destInfo);
+                fi.addItem(sourceInfo);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] targetCell,
+            float distance, DragObject d, boolean external) {
+        if (distance > mMaxDistanceForFolderCreation) return false;
+
+        View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
+        if (!mAddToExistingFolderOnDrop) return false;
+        mAddToExistingFolderOnDrop = false;
+
+        if (dropOverView instanceof FolderIcon) {
+            FolderIcon fi = (FolderIcon) dropOverView;
+            if (fi.acceptDrop(d.dragInfo)) {
+                fi.onDrop(d);
+
+                // if the drag started here, we need to remove it from the workspace
+                if (!external) {
+                    getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void onDrop(final DragObject d) {
+        mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
+                mDragViewVisualCenter);
+
+        CellLayout dropTargetLayout = mDropToLayout;
+
+        // We want the point to be mapped to the dragTarget.
+        if (dropTargetLayout != null) {
+            if (mLauncher.isHotseatLayout(dropTargetLayout)) {
+                mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
+            } else {
+                mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null);
+            }
+        }
+
+        int snapScreen = -1;
+        boolean resizeOnDrop = false;
+        if (d.dragSource != this) {
+            final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1] };
+            onDropExternal(touchXY, d.dragInfo, dropTargetLayout, false, d);
+        } else if (mDragInfo != null) {
+            final View cell = mDragInfo.cell;
+
+            Runnable resizeRunnable = null;
+            if (dropTargetLayout != null) {
+                // Move internally
+                boolean hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
+                boolean hasMovedIntoHotseat = mLauncher.isHotseatLayout(dropTargetLayout);
+                long container = hasMovedIntoHotseat ?
+                        LauncherSettings.Favorites.CONTAINER_HOTSEAT :
+                        LauncherSettings.Favorites.CONTAINER_DESKTOP;
+                int screen = (mTargetCell[0] < 0) ?
+                        mDragInfo.screen : indexOfChild(dropTargetLayout);
+                int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+                int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+                // First we find the cell nearest to point at which the item is
+                // dropped, without any consideration to whether there is an item there.
+
+                mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int)
+                        mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
+                float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
+                        mDragViewVisualCenter[1], mTargetCell);
+
+                // If the item being dropped is a shortcut and the nearest drop
+                // cell also contains a shortcut, then create a folder with the two shortcuts.
+                if (!mInScrollArea && createUserFolderIfNecessary(cell, container,
+                        dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {
+                    return;
+                }
+
+                if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
+                        distance, d, false)) {
+                    return;
+                }
+
+                // Aside from the special case where we're dropping a shortcut onto a shortcut,
+                // we need to find the nearest cell location that is vacant
+                ItemInfo item = (ItemInfo) d.dragInfo;
+                int minSpanX = item.spanX;
+                int minSpanY = item.spanY;
+                if (item.minSpanX > 0 && item.minSpanY > 0) {
+                    minSpanX = item.minSpanX;
+                    minSpanY = item.minSpanY;
+                }
+
+                int[] resultSpan = new int[2];
+                mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],
+                        (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell,
+                        mTargetCell, resultSpan, CellLayout.MODE_ON_DROP);
+
+                boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
+
+                // if the widget resizes on drop
+                if (foundCell && (cell instanceof AppWidgetHostView) &&
+                        (resultSpan[0] != item.spanX || resultSpan[1] != item.spanY)) {
+                    resizeOnDrop = true;
+                    item.spanX = resultSpan[0];
+                    item.spanY = resultSpan[1];
+                    AppWidgetHostView awhv = (AppWidgetHostView) cell;
+                    AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],
+                            resultSpan[1]);
+                }
+
+                if (mCurrentPage != screen && !hasMovedIntoHotseat) {
+                    snapScreen = screen;
+                    snapToPage(screen);
+                }
+
+                if (foundCell) {
+                    final ItemInfo info = (ItemInfo) cell.getTag();
+                    if (hasMovedLayouts) {
+                        // Reparent the view
+                        getParentCellLayoutForView(cell).removeView(cell);
+                        addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
+                                info.spanX, info.spanY);
+                    }
+
+                    // update the item's position after drop
+                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
+                    lp.cellX = lp.tmpCellX = mTargetCell[0];
+                    lp.cellY = lp.tmpCellY = mTargetCell[1];
+                    lp.cellHSpan = item.spanX;
+                    lp.cellVSpan = item.spanY;
+                    lp.isLockedToGrid = true;
+                    cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
+                            mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
+
+                    if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
+                            cell instanceof LauncherAppWidgetHostView) {
+                        final CellLayout cellLayout = dropTargetLayout;
+                        // We post this call so that the widget has a chance to be placed
+                        // in its final location
+
+                        final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
+                        AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
+                        if (pinfo != null &&
+                                pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+                            final Runnable addResizeFrame = new Runnable() {
+                                public void run() {
+                                    DragLayer dragLayer = mLauncher.getDragLayer();
+                                    dragLayer.addResizeFrame(info, hostView, cellLayout);
+                                }
+                            };
+                            resizeRunnable = (new Runnable() {
+                                public void run() {
+                                    if (!isPageMoving()) {
+                                        addResizeFrame.run();
+                                    } else {
+                                        mDelayedResizeRunnable = addResizeFrame;
+                                    }
+                                }
+                            });
+                        }
+                    }
+
+                    LauncherModel.moveItemInDatabase(mLauncher, info, container, screen, lp.cellX,
+                            lp.cellY);
+                } else {
+                    // If we can't find a drop location, we return the item to its original position
+                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
+                    mTargetCell[0] = lp.cellX;
+                    mTargetCell[1] = lp.cellY;
+                    CellLayout layout = (CellLayout) cell.getParent().getParent();
+                    layout.markCellsAsOccupiedForView(cell);
+                }
+            }
+
+            final CellLayout parent = (CellLayout) cell.getParent().getParent();
+            final Runnable finalResizeRunnable = resizeRunnable;
+            // Prepare it to be animated into its new position
+            // This must be called after the view has been re-parented
+            final Runnable onCompleteRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    mAnimatingViewIntoPlace = false;
+                    updateChildrenLayersEnabled(false);
+                    if (finalResizeRunnable != null) {
+                        finalResizeRunnable.run();
+                    }
+                }
+            };
+            mAnimatingViewIntoPlace = true;
+            if (d.dragView.hasDrawn()) {
+                final ItemInfo info = (ItemInfo) cell.getTag();
+                if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+                    int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
+                            ANIMATE_INTO_POSITION_AND_DISAPPEAR;
+                    animateWidgetDrop(info, parent, d.dragView,
+                            onCompleteRunnable, animationType, cell, false);
+                } else {
+                    int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
+                    mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
+                            onCompleteRunnable, this);
+                }
+            } else {
+                d.deferDragViewCleanupPostAnimation = false;
+                cell.setVisibility(VISIBLE);
+            }
+            parent.onDropChild(cell);
+        }
+    }
+
+    public void setFinalScrollForPageChange(int screen) {
+        if (screen >= 0) {
+            mSavedScrollX = getScrollX();
+            CellLayout cl = (CellLayout) getChildAt(screen);
+            mSavedTranslationX = cl.getTranslationX();
+            mSavedRotationY = cl.getRotationY();
+            final int newX = getChildOffset(screen) - getRelativeChildOffset(screen);
+            setScrollX(newX);
+            cl.setTranslationX(0f);
+            cl.setRotationY(0f);
+        }
+    }
+
+    public void resetFinalScrollForPageChange(int screen) {
+        if (screen >= 0) {
+            CellLayout cl = (CellLayout) getChildAt(screen);
+            setScrollX(mSavedScrollX);
+            cl.setTranslationX(mSavedTranslationX);
+            cl.setRotationY(mSavedRotationY);
+        }
+    }
+
+    public void getViewLocationRelativeToSelf(View v, int[] location) {
+        getLocationInWindow(location);
+        int x = location[0];
+        int y = location[1];
+
+        v.getLocationInWindow(location);
+        int vX = location[0];
+        int vY = location[1];
+
+        location[0] = vX - x;
+        location[1] = vY - y;
+    }
+
+    public void onDragEnter(DragObject d) {
+        mDragEnforcer.onDragEnter();
+        mCreateUserFolderOnDrop = false;
+        mAddToExistingFolderOnDrop = false;
+
+        mDropToLayout = null;
+        CellLayout layout = getCurrentDropLayout();
+        setCurrentDropLayout(layout);
+        setCurrentDragOverlappingLayout(layout);
+
+        // Because we don't have space in the Phone UI (the CellLayouts run to the edge) we
+        // don't need to show the outlines
+        if (LauncherApplication.isScreenLarge()) {
+            showOutlines();
+        }
+    }
+
+    static Rect getCellLayoutMetrics(Launcher launcher, int orientation) {
+        Resources res = launcher.getResources();
+        Display display = launcher.getWindowManager().getDefaultDisplay();
+        Point smallestSize = new Point();
+        Point largestSize = new Point();
+        display.getCurrentSizeRange(smallestSize, largestSize);
+        if (orientation == CellLayout.LANDSCAPE) {
+            if (mLandscapeCellLayoutMetrics == null) {
+                int paddingLeft = res.getDimensionPixelSize(R.dimen.workspace_left_padding_land);
+                int paddingRight = res.getDimensionPixelSize(R.dimen.workspace_right_padding_land);
+                int paddingTop = res.getDimensionPixelSize(R.dimen.workspace_top_padding_land);
+                int paddingBottom = res.getDimensionPixelSize(R.dimen.workspace_bottom_padding_land);
+                int width = largestSize.x - paddingLeft - paddingRight;
+                int height = smallestSize.y - paddingTop - paddingBottom;
+                mLandscapeCellLayoutMetrics = new Rect();
+                CellLayout.getMetrics(mLandscapeCellLayoutMetrics, res,
+                        width, height, LauncherModel.getCellCountX(), LauncherModel.getCellCountY(),
+                        orientation);
+            }
+            return mLandscapeCellLayoutMetrics;
+        } else if (orientation == CellLayout.PORTRAIT) {
+            if (mPortraitCellLayoutMetrics == null) {
+                int paddingLeft = res.getDimensionPixelSize(R.dimen.workspace_left_padding_land);
+                int paddingRight = res.getDimensionPixelSize(R.dimen.workspace_right_padding_land);
+                int paddingTop = res.getDimensionPixelSize(R.dimen.workspace_top_padding_land);
+                int paddingBottom = res.getDimensionPixelSize(R.dimen.workspace_bottom_padding_land);
+                int width = smallestSize.x - paddingLeft - paddingRight;
+                int height = largestSize.y - paddingTop - paddingBottom;
+                mPortraitCellLayoutMetrics = new Rect();
+                CellLayout.getMetrics(mPortraitCellLayoutMetrics, res,
+                        width, height, LauncherModel.getCellCountX(), LauncherModel.getCellCountY(),
+                        orientation);
+            }
+            return mPortraitCellLayoutMetrics;
+        }
+        return null;
+    }
+
+    public void onDragExit(DragObject d) {
+        mDragEnforcer.onDragExit();
+
+        // Here we store the final page that will be dropped to, if the workspace in fact
+        // receives the drop
+        if (mInScrollArea) {
+            if (isPageMoving()) {
+                // If the user drops while the page is scrolling, we should use that page as the
+                // destination instead of the page that is being hovered over.
+                mDropToLayout = (CellLayout) getPageAt(getNextPage());
+            } else {
+                mDropToLayout = mDragOverlappingLayout;
+            }
+        } else {
+            mDropToLayout = mDragTargetLayout;
+        }
+
+        if (mDragMode == DRAG_MODE_CREATE_FOLDER) {
+            mCreateUserFolderOnDrop = true;
+        } else if (mDragMode == DRAG_MODE_ADD_TO_FOLDER) {
+            mAddToExistingFolderOnDrop = true;
+        }
+
+        // Reset the scroll area and previous drag target
+        onResetScrollArea();
+        setCurrentDropLayout(null);
+        setCurrentDragOverlappingLayout(null);
+
+        mSpringLoadedDragController.cancel();
+
+        if (!mIsPageMoving) {
+            hideOutlines();
+        }
+    }
+
+    void setCurrentDropLayout(CellLayout layout) {
+        if (mDragTargetLayout != null) {
+            mDragTargetLayout.revertTempState();
+            mDragTargetLayout.onDragExit();
+        }
+        mDragTargetLayout = layout;
+        if (mDragTargetLayout != null) {
+            mDragTargetLayout.onDragEnter();
+        }
+        cleanupReorder(true);
+        cleanupFolderCreation();
+        setCurrentDropOverCell(-1, -1);
+    }
+
+    void setCurrentDragOverlappingLayout(CellLayout layout) {
+        if (mDragOverlappingLayout != null) {
+            mDragOverlappingLayout.setIsDragOverlapping(false);
+        }
+        mDragOverlappingLayout = layout;
+        if (mDragOverlappingLayout != null) {
+            mDragOverlappingLayout.setIsDragOverlapping(true);
+        }
+        invalidate();
+    }
+
+    void setCurrentDropOverCell(int x, int y) {
+        if (x != mDragOverX || y != mDragOverY) {
+            mDragOverX = x;
+            mDragOverY = y;
+            setDragMode(DRAG_MODE_NONE);
+        }
+    }
+
+    void setDragMode(int dragMode) {
+        if (dragMode != mDragMode) {
+            if (dragMode == DRAG_MODE_NONE) {
+                cleanupAddToFolder();
+                // We don't want to cancel the re-order alarm every time the target cell changes
+                // as this feels to slow / unresponsive.
+                cleanupReorder(false);
+                cleanupFolderCreation();
+            } else if (dragMode == DRAG_MODE_ADD_TO_FOLDER) {
+                cleanupReorder(true);
+                cleanupFolderCreation();
+            } else if (dragMode == DRAG_MODE_CREATE_FOLDER) {
+                cleanupAddToFolder();
+                cleanupReorder(true);
+            } else if (dragMode == DRAG_MODE_REORDER) {
+                cleanupAddToFolder();
+                cleanupFolderCreation();
+            }
+            mDragMode = dragMode;
+        }
+    }
+
+    private void cleanupFolderCreation() {
+        if (mDragFolderRingAnimator != null) {
+            mDragFolderRingAnimator.animateToNaturalState();
+        }
+        mFolderCreationAlarm.cancelAlarm();
+    }
+
+    private void cleanupAddToFolder() {
+        if (mDragOverFolderIcon != null) {
+            mDragOverFolderIcon.onDragExit(null);
+            mDragOverFolderIcon = null;
+        }
+    }
+
+    private void cleanupReorder(boolean cancelAlarm) {
+        // Any pending reorders are canceled
+        if (cancelAlarm) {
+            mReorderAlarm.cancelAlarm();
+        }
+        mLastReorderX = -1;
+        mLastReorderY = -1;
+    }
+
+    public DropTarget getDropTargetDelegate(DragObject d) {
+        return null;
+    }
+
+    /*
+    *
+    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
+    * coordinate space. The argument xy is modified with the return result.
+    *
+    */
+   void mapPointFromSelfToChild(View v, float[] xy) {
+       mapPointFromSelfToChild(v, xy, null);
+   }
+
+   /*
+    *
+    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
+    * coordinate space. The argument xy is modified with the return result.
+    *
+    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
+    * computing it itself; we use this to avoid redundant matrix inversions in
+    * findMatchingPageForDragOver
+    *
+    */
+   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
+       if (cachedInverseMatrix == null) {
+           v.getMatrix().invert(mTempInverseMatrix);
+           cachedInverseMatrix = mTempInverseMatrix;
+       }
+       int scrollX = getScrollX();
+       if (mNextPage != INVALID_PAGE) {
+           scrollX = mScroller.getFinalX();
+       }
+       xy[0] = xy[0] + scrollX - v.getLeft();
+       xy[1] = xy[1] + getScrollY() - v.getTop();
+       cachedInverseMatrix.mapPoints(xy);
+   }
+
+
+   void mapPointFromSelfToHotseatLayout(Hotseat hotseat, float[] xy) {
+       hotseat.getLayout().getMatrix().invert(mTempInverseMatrix);
+       xy[0] = xy[0] - hotseat.getLeft() - hotseat.getLayout().getLeft();
+       xy[1] = xy[1] - hotseat.getTop() - hotseat.getLayout().getTop();
+       mTempInverseMatrix.mapPoints(xy);
+   }
+
+   /*
+    *
+    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
+    * the parent View's coordinate space. The argument xy is modified with the return result.
+    *
+    */
+   void mapPointFromChildToSelf(View v, float[] xy) {
+       v.getMatrix().mapPoints(xy);
+       int scrollX = getScrollX();
+       if (mNextPage != INVALID_PAGE) {
+           scrollX = mScroller.getFinalX();
+       }
+       xy[0] -= (scrollX - v.getLeft());
+       xy[1] -= (getScrollY() - v.getTop());
+   }
+
+   static private float squaredDistance(float[] point1, float[] point2) {
+        float distanceX = point1[0] - point2[0];
+        float distanceY = point2[1] - point2[1];
+        return distanceX * distanceX + distanceY * distanceY;
+   }
+
+    /*
+     *
+     * Returns true if the passed CellLayout cl overlaps with dragView
+     *
+     */
+    boolean overlaps(CellLayout cl, DragView dragView,
+            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
+        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
+        final float[] draggedItemTopLeft = mTempDragCoordinates;
+        draggedItemTopLeft[0] = dragViewX;
+        draggedItemTopLeft[1] = dragViewY;
+        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
+        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getDragRegionWidth();
+        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getDragRegionHeight();
+
+        // Transform the dragged item's top left coordinates
+        // to the CellLayout's local coordinates
+        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
+        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
+        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
+
+        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
+            // Transform the dragged item's bottom right coordinates
+            // to the CellLayout's local coordinates
+            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
+            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
+            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
+
+            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
+                float overlap = (overlapRegionRight - overlapRegionLeft) *
+                         (overlapRegionBottom - overlapRegionTop);
+                if (overlap > 0) {
+                    return true;
+                }
+             }
+        }
+        return false;
+    }
+
+    /*
+     *
+     * This method returns the CellLayout that is currently being dragged to. In order to drag
+     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
+     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
+     *
+     * Return null if no CellLayout is currently being dragged over
+     *
+     */
+    private CellLayout findMatchingPageForDragOver(
+            DragView dragView, float originX, float originY, boolean exact) {
+        // We loop through all the screens (ie CellLayouts) and see which ones overlap
+        // with the item being dragged and then choose the one that's closest to the touch point
+        final int screenCount = getChildCount();
+        CellLayout bestMatchingScreen = null;
+        float smallestDistSoFar = Float.MAX_VALUE;
+
+        for (int i = 0; i < screenCount; i++) {
+            CellLayout cl = (CellLayout) getChildAt(i);
+
+            final float[] touchXy = {originX, originY};
+            // Transform the touch coordinates to the CellLayout's local coordinates
+            // If the touch point is within the bounds of the cell layout, we can return immediately
+            cl.getMatrix().invert(mTempInverseMatrix);
+            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
+
+            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
+                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
+                return cl;
+            }
+
+            if (!exact) {
+                // Get the center of the cell layout in screen coordinates
+                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
+                cellLayoutCenter[0] = cl.getWidth()/2;
+                cellLayoutCenter[1] = cl.getHeight()/2;
+                mapPointFromChildToSelf(cl, cellLayoutCenter);
+
+                touchXy[0] = originX;
+                touchXy[1] = originY;
+
+                // Calculate the distance between the center of the CellLayout
+                // and the touch point
+                float dist = squaredDistance(touchXy, cellLayoutCenter);
+
+                if (dist < smallestDistSoFar) {
+                    smallestDistSoFar = dist;
+                    bestMatchingScreen = cl;
+                }
+            }
+        }
+        return bestMatchingScreen;
+    }
+
+    // This is used to compute the visual center of the dragView. This point is then
+    // used to visualize drop locations and determine where to drop an item. The idea is that
+    // the visual center represents the user's interpretation of where the item is, and hence
+    // is the appropriate point to use when determining drop location.
+    private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
+            DragView dragView, float[] recycle) {
+        float res[];
+        if (recycle == null) {
+            res = new float[2];
+        } else {
+            res = recycle;
+        }
+
+        // First off, the drag view has been shifted in a way that is not represented in the
+        // x and y values or the x/yOffsets. Here we account for that shift.
+        x += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetX);
+        y += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+
+        // These represent the visual top and left of drag view if a dragRect was provided.
+        // If a dragRect was not provided, then they correspond to the actual view left and
+        // top, as the dragRect is in that case taken to be the entire dragView.
+        // R.dimen.dragViewOffsetY.
+        int left = x - xOffset;
+        int top = y - yOffset;
+
+        // In order to find the visual center, we shift by half the dragRect
+        res[0] = left + dragView.getDragRegion().width() / 2;
+        res[1] = top + dragView.getDragRegion().height() / 2;
+
+        return res;
+    }
+
+    private boolean isDragWidget(DragObject d) {
+        return (d.dragInfo instanceof LauncherAppWidgetInfo ||
+                d.dragInfo instanceof PendingAddWidgetInfo);
+    }
+    private boolean isExternalDragWidget(DragObject d) {
+        return d.dragSource != this && isDragWidget(d);
+    }
+
+    public void onDragOver(DragObject d) {
+        // Skip drag over events while we are dragging over side pages
+        if (mInScrollArea || mIsSwitchingState || mState == State.SMALL) return;
+
+        Rect r = new Rect();
+        CellLayout layout = null;
+        ItemInfo item = (ItemInfo) d.dragInfo;
+
+        // Ensure that we have proper spans for the item that we are dropping
+        if (item.spanX < 0 || item.spanY < 0) throw new RuntimeException("Improper spans found");
+        mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
+            d.dragView, mDragViewVisualCenter);
+
+        final View child = (mDragInfo == null) ? null : mDragInfo.cell;
+        // Identify whether we have dragged over a side page
+        if (isSmall()) {
+            if (mLauncher.getHotseat() != null && !isExternalDragWidget(d)) {
+                mLauncher.getHotseat().getHitRect(r);
+                if (r.contains(d.x, d.y)) {
+                    layout = mLauncher.getHotseat().getLayout();
+                }
+            }
+            if (layout == null) {
+                layout = findMatchingPageForDragOver(d.dragView, d.x, d.y, false);
+            }
+            if (layout != mDragTargetLayout) {
+
+                setCurrentDropLayout(layout);
+                setCurrentDragOverlappingLayout(layout);
+
+                boolean isInSpringLoadedMode = (mState == State.SPRING_LOADED);
+                if (isInSpringLoadedMode) {
+                    if (mLauncher.isHotseatLayout(layout)) {
+                        mSpringLoadedDragController.cancel();
+                    } else {
+                        mSpringLoadedDragController.setAlarm(mDragTargetLayout);
+                    }
+                }
+            }
+        } else {
+            // Test to see if we are over the hotseat otherwise just use the current page
+            if (mLauncher.getHotseat() != null && !isDragWidget(d)) {
+                mLauncher.getHotseat().getHitRect(r);
+                if (r.contains(d.x, d.y)) {
+                    layout = mLauncher.getHotseat().getLayout();
+                }
+            }
+            if (layout == null) {
+                layout = getCurrentDropLayout();
+            }
+            if (layout != mDragTargetLayout) {
+                setCurrentDropLayout(layout);
+                setCurrentDragOverlappingLayout(layout);
+            }
+        }
+
+        // Handle the drag over
+        if (mDragTargetLayout != null) {
+            // We want the point to be mapped to the dragTarget.
+            if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
+                mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
+            } else {
+                mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+            }
+
+            ItemInfo info = (ItemInfo) d.dragInfo;
+
+            mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1], item.spanX, item.spanY,
+                    mDragTargetLayout, mTargetCell);
+
+            setCurrentDropOverCell(mTargetCell[0], mTargetCell[1]);
+
+            float targetCellDistance = mDragTargetLayout.getDistanceFromCell(
+                    mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell);
+
+            final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
+                    mTargetCell[1]);
+
+            manageFolderFeedback(info, mDragTargetLayout, mTargetCell,
+                    targetCellDistance, dragOverView);
+
+            int minSpanX = item.spanX;
+            int minSpanY = item.spanY;
+            if (item.minSpanX > 0 && item.minSpanY > 0) {
+                minSpanX = item.minSpanX;
+                minSpanY = item.minSpanY;
+            }
+
+            boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
+                    mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
+                    item.spanY, child, mTargetCell);
+
+            if (!nearestDropOccupied) {
+                mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
+                        (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
+                        mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false,
+                        d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
+            } else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
+                    && !mReorderAlarm.alarmPending() && (mLastReorderX != mTargetCell[0] ||
+                    mLastReorderY != mTargetCell[1])) {
+
+                // Otherwise, if we aren't adding to or creating a folder and there's no pending
+                // reorder, then we schedule a reorder
+                ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
+                        minSpanX, minSpanY, item.spanX, item.spanY, d.dragView, child);
+                mReorderAlarm.setOnAlarmListener(listener);
+                mReorderAlarm.setAlarm(REORDER_TIMEOUT);
+            }
+
+            if (mDragMode == DRAG_MODE_CREATE_FOLDER || mDragMode == DRAG_MODE_ADD_TO_FOLDER ||
+                    !nearestDropOccupied) {
+                if (mDragTargetLayout != null) {
+                    mDragTargetLayout.revertTempState();
+                }
+            }
+        }
+    }
+
+    private void manageFolderFeedback(ItemInfo info, CellLayout targetLayout,
+            int[] targetCell, float distance, View dragOverView) {
+        boolean userFolderPending = willCreateUserFolder(info, targetLayout, targetCell, distance,
+                false);
+
+        if (mDragMode == DRAG_MODE_NONE && userFolderPending &&
+                !mFolderCreationAlarm.alarmPending()) {
+            mFolderCreationAlarm.setOnAlarmListener(new
+                    FolderCreationAlarmListener(targetLayout, targetCell[0], targetCell[1]));
+            mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
+            return;
+        }
+
+        boolean willAddToFolder =
+                willAddToExistingUserFolder(info, targetLayout, targetCell, distance);
+
+        if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
+            mDragOverFolderIcon = ((FolderIcon) dragOverView);
+            mDragOverFolderIcon.onDragEnter(info);
+            if (targetLayout != null) {
+                targetLayout.clearDragOutlines();
+            }
+            setDragMode(DRAG_MODE_ADD_TO_FOLDER);
+            return;
+        }
+
+        if (mDragMode == DRAG_MODE_ADD_TO_FOLDER && !willAddToFolder) {
+            setDragMode(DRAG_MODE_NONE);
+        }
+        if (mDragMode == DRAG_MODE_CREATE_FOLDER && !userFolderPending) {
+            setDragMode(DRAG_MODE_NONE);
+        }
+
+        return;
+    }
+
+    class FolderCreationAlarmListener implements OnAlarmListener {
+        CellLayout layout;
+        int cellX;
+        int cellY;
+
+        public FolderCreationAlarmListener(CellLayout layout, int cellX, int cellY) {
+            this.layout = layout;
+            this.cellX = cellX;
+            this.cellY = cellY;
+        }
+
+        public void onAlarm(Alarm alarm) {
+            if (mDragFolderRingAnimator == null) {
+                mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null);
+            }
+            mDragFolderRingAnimator.setCell(cellX, cellY);
+            mDragFolderRingAnimator.setCellLayout(layout);
+            mDragFolderRingAnimator.animateToAcceptState();
+            layout.showFolderAccept(mDragFolderRingAnimator);
+            layout.clearDragOutlines();
+            setDragMode(DRAG_MODE_CREATE_FOLDER);
+        }
+    }
+
+    class ReorderAlarmListener implements OnAlarmListener {
+        float[] dragViewCenter;
+        int minSpanX, minSpanY, spanX, spanY;
+        DragView dragView;
+        View child;
+
+        public ReorderAlarmListener(float[] dragViewCenter, int minSpanX, int minSpanY, int spanX,
+                int spanY, DragView dragView, View child) {
+            this.dragViewCenter = dragViewCenter;
+            this.minSpanX = minSpanX;
+            this.minSpanY = minSpanY;
+            this.spanX = spanX;
+            this.spanY = spanY;
+            this.child = child;
+            this.dragView = dragView;
+        }
+
+        public void onAlarm(Alarm alarm) {
+            int[] resultSpan = new int[2];
+            mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1], spanX, spanY, mDragTargetLayout, mTargetCell);
+            mLastReorderX = mTargetCell[0];
+            mLastReorderY = mTargetCell[1];
+
+            mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0],
+                (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
+                child, mTargetCell, resultSpan, CellLayout.MODE_DRAG_OVER);
+
+            if (mTargetCell[0] < 0 || mTargetCell[1] < 0) {
+                mDragTargetLayout.revertTempState();
+            } else {
+                setDragMode(DRAG_MODE_REORDER);
+            }
+
+            boolean resize = resultSpan[0] != spanX || resultSpan[1] != spanY;
+            mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
+                (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
+                mTargetCell[0], mTargetCell[1], resultSpan[0], resultSpan[1], resize,
+                dragView.getDragVisualizeOffset(), dragView.getDragRegion());
+        }
+    }
+
+    @Override
+    public void getHitRect(Rect outRect) {
+        // We want the workspace to have the whole area of the display (it will find the correct
+        // cell layout to drop to in the existing drag/drop logic.
+        outRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
+    }
+
+    /**
+     * Add the item specified by dragInfo to the given layout.
+     * @return true if successful
+     */
+    public boolean addExternalItemToScreen(ItemInfo dragInfo, CellLayout layout) {
+        if (layout.findCellForSpan(mTempEstimate, dragInfo.spanX, dragInfo.spanY)) {
+            onDropExternal(dragInfo.dropPos, (ItemInfo) dragInfo, (CellLayout) layout, false);
+            return true;
+        }
+        mLauncher.showOutOfSpaceMessage(mLauncher.isHotseatLayout(layout));
+        return false;
+    }
+
+    private void onDropExternal(int[] touchXY, Object dragInfo,
+            CellLayout cellLayout, boolean insertAtFirst) {
+        onDropExternal(touchXY, dragInfo, cellLayout, insertAtFirst, null);
+    }
+
+    /**
+     * Drop an item that didn't originate on one of the workspace screens.
+     * It may have come from Launcher (e.g. from all apps or customize), or it may have
+     * come from another app altogether.
+     *
+     * NOTE: This can also be called when we are outside of a drag event, when we want
+     * to add an item to one of the workspace screens.
+     */
+    private void onDropExternal(final int[] touchXY, final Object dragInfo,
+            final CellLayout cellLayout, boolean insertAtFirst, DragObject d) {
+        final Runnable exitSpringLoadedRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mLauncher.exitSpringLoadedDragModeDelayed(true, false, null);
+            }
+        };
+
+        ItemInfo info = (ItemInfo) dragInfo;
+        int spanX = info.spanX;
+        int spanY = info.spanY;
+        if (mDragInfo != null) {
+            spanX = mDragInfo.spanX;
+            spanY = mDragInfo.spanY;
+        }
+
+        final long container = mLauncher.isHotseatLayout(cellLayout) ?
+                LauncherSettings.Favorites.CONTAINER_HOTSEAT :
+                    LauncherSettings.Favorites.CONTAINER_DESKTOP;
+        final int screen = indexOfChild(cellLayout);
+        if (!mLauncher.isHotseatLayout(cellLayout) && screen != mCurrentPage
+                && mState != State.SPRING_LOADED) {
+            snapToPage(screen);
+        }
+
+        if (info instanceof PendingAddItemInfo) {
+            final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) dragInfo;
+
+            boolean findNearestVacantCell = true;
+            if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+                mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
+                        cellLayout, mTargetCell);
+                float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0],
+                        mDragViewVisualCenter[1], mTargetCell);
+                if (willCreateUserFolder((ItemInfo) d.dragInfo, cellLayout, mTargetCell,
+                        distance, true) || willAddToExistingUserFolder((ItemInfo) d.dragInfo,
+                                cellLayout, mTargetCell, distance)) {
+                    findNearestVacantCell = false;
+                }
+            }
+
+            final ItemInfo item = (ItemInfo) d.dragInfo;
+            boolean updateWidgetSize = false;
+            if (findNearestVacantCell) {
+                int minSpanX = item.spanX;
+                int minSpanY = item.spanY;
+                if (item.minSpanX > 0 && item.minSpanY > 0) {
+                    minSpanX = item.minSpanX;
+                    minSpanY = item.minSpanY;
+                }
+                int[] resultSpan = new int[2];
+                mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0],
+                        (int) mDragViewVisualCenter[1], minSpanX, minSpanY, info.spanX, info.spanY,
+                        null, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP_EXTERNAL);
+
+                if (resultSpan[0] != item.spanX || resultSpan[1] != item.spanY) {
+                    updateWidgetSize = true;
+                }
+                item.spanX = resultSpan[0];
+                item.spanY = resultSpan[1];
+            }
+
+            Runnable onAnimationCompleteRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    // When dragging and dropping from customization tray, we deal with creating
+                    // widgets/shortcuts/folders in a slightly different way
+                    switch (pendingInfo.itemType) {
+                    case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                        int span[] = new int[2];
+                        span[0] = item.spanX;
+                        span[1] = item.spanY;
+                        mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
+                                container, screen, mTargetCell, span, null);
+                        break;
+                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                        mLauncher.processShortcutFromDrop(pendingInfo.componentName,
+                                container, screen, mTargetCell, null);
+                        break;
+                    default:
+                        throw new IllegalStateException("Unknown item type: " +
+                                pendingInfo.itemType);
+                    }
+                }
+            };
+            View finalView = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+                    ? ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
+
+            if (finalView instanceof AppWidgetHostView && updateWidgetSize) {
+                AppWidgetHostView awhv = (AppWidgetHostView) finalView;
+                AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, item.spanX,
+                        item.spanY);
+            }
+
+            int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
+            if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
+                    ((PendingAddWidgetInfo) pendingInfo).info.configure != null) {
+                animationStyle = ANIMATE_INTO_POSITION_AND_REMAIN;
+            }
+            animateWidgetDrop(info, cellLayout, d.dragView, onAnimationCompleteRunnable,
+                    animationStyle, finalView, true);
+        } else {
+            // This is for other drag/drop cases, like dragging from All Apps
+            View view = null;
+
+            switch (info.itemType) {
+            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                if (info.container == NO_ID && info instanceof ApplicationInfo) {
+                    // Came from all apps -- make a copy
+                    info = new ShortcutInfo((ApplicationInfo) info);
+                }
+                view = mLauncher.createShortcut(R.layout.application, cellLayout,
+                        (ShortcutInfo) info);
+                break;
+            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
+                        (FolderInfo) info, mIconCache);
+                break;
+            default:
+                throw new IllegalStateException("Unknown item type: " + info.itemType);
+            }
+
+            // First we find the cell nearest to point at which the item is
+            // dropped, without any consideration to whether there is an item there.
+            if (touchXY != null) {
+                mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
+                        cellLayout, mTargetCell);
+                float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0],
+                        mDragViewVisualCenter[1], mTargetCell);
+                d.postAnimationRunnable = exitSpringLoadedRunnable;
+                if (createUserFolderIfNecessary(view, container, cellLayout, mTargetCell, distance,
+                        true, d.dragView, d.postAnimationRunnable)) {
+                    return;
+                }
+                if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, distance, d,
+                        true)) {
+                    return;
+                }
+            }
+
+            if (touchXY != null) {
+                // when dragging and dropping, just find the closest free spot
+                mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0],
+                        (int) mDragViewVisualCenter[1], 1, 1, 1, 1,
+                        null, mTargetCell, null, CellLayout.MODE_ON_DROP_EXTERNAL);
+            } else {
+                cellLayout.findCellForSpan(mTargetCell, 1, 1);
+            }
+            addInScreen(view, container, screen, mTargetCell[0], mTargetCell[1], info.spanX,
+                    info.spanY, insertAtFirst);
+            cellLayout.onDropChild(view);
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+            cellLayout.getShortcutsAndWidgets().measureChild(view);
+
+
+            LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen,
+                    lp.cellX, lp.cellY);
+
+            if (d.dragView != null) {
+                // We wrap the animation call in the temporary set and reset of the current
+                // cellLayout to its final transform -- this means we animate the drag view to
+                // the correct final location.
+                setFinalTransitionTransform(cellLayout);
+                mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view,
+                        exitSpringLoadedRunnable);
+                resetTransitionTransform(cellLayout);
+            }
+        }
+    }
+
+    public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
+        int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo.spanX,
+                widgetInfo.spanY, widgetInfo, false);
+        int visibility = layout.getVisibility();
+        layout.setVisibility(VISIBLE);
+
+        int width = MeasureSpec.makeMeasureSpec(unScaledSize[0], MeasureSpec.EXACTLY);
+        int height = MeasureSpec.makeMeasureSpec(unScaledSize[1], MeasureSpec.EXACTLY);
+        Bitmap b = Bitmap.createBitmap(unScaledSize[0], unScaledSize[1],
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+
+        layout.measure(width, height);
+        layout.layout(0, 0, unScaledSize[0], unScaledSize[1]);
+        layout.draw(c);
+        c.setBitmap(null);
+        layout.setVisibility(visibility);
+        return b;
+    }
+
+    private void getFinalPositionForDropAnimation(int[] loc, float[] scaleXY,
+            DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell,
+            boolean external, boolean scale) {
+        // Now we animate the dragView, (ie. the widget or shortcut preview) into its final
+        // location and size on the home screen.
+        int spanX = info.spanX;
+        int spanY = info.spanY;
+
+        Rect r = estimateItemPosition(layout, info, targetCell[0], targetCell[1], spanX, spanY);
+        loc[0] = r.left;
+        loc[1] = r.top;
+
+        setFinalTransitionTransform(layout);
+        float cellLayoutScale =
+                mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc);
+        resetTransitionTransform(layout);
+
+        float dragViewScaleX;
+        float dragViewScaleY;
+        if (scale) {
+            dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
+            dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
+        } else {
+            dragViewScaleX = 1f;
+            dragViewScaleY = 1f;
+        }
+
+        // The animation will scale the dragView about its center, so we need to center about
+        // the final location.
+        loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2;
+        loc[1] -= (dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
+
+        scaleXY[0] = dragViewScaleX * cellLayoutScale;
+        scaleXY[1] = dragViewScaleY * cellLayoutScale;
+    }
+
+    public void animateWidgetDrop(ItemInfo info, CellLayout cellLayout, DragView dragView,
+            final Runnable onCompleteRunnable, int animationType, final View finalView,
+            boolean external) {
+        Rect from = new Rect();
+        mLauncher.getDragLayer().getViewRectRelativeToSelf(dragView, from);
+
+        int[] finalPos = new int[2];
+        float scaleXY[] = new float[2];
+        boolean scalePreview = !(info instanceof PendingAddShortcutInfo);
+        getFinalPositionForDropAnimation(finalPos, scaleXY, dragView, cellLayout, info, mTargetCell,
+                external, scalePreview);
+
+        Resources res = mLauncher.getResources();
+        int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
+
+        // In the case where we've prebound the widget, we remove it from the DragLayer
+        if (finalView instanceof AppWidgetHostView && external) {
+            Log.d(TAG, "6557954 Animate widget drop, final view is appWidgetHostView");
+            mLauncher.getDragLayer().removeView(finalView);
+        }
+        if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {
+            Bitmap crossFadeBitmap = createWidgetBitmap(info, finalView);
+            dragView.setCrossFadeBitmap(crossFadeBitmap);
+            dragView.crossFade((int) (duration * 0.8f));
+        } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET && external) {
+            scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0],  scaleXY[1]);
+        }
+
+        DragLayer dragLayer = mLauncher.getDragLayer();
+        if (animationType == CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION) {
+            mLauncher.getDragLayer().animateViewIntoPosition(dragView, finalPos, 0f, 0.1f, 0.1f,
+                    DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
+        } else {
+            int endStyle;
+            if (animationType == ANIMATE_INTO_POSITION_AND_REMAIN) {
+                endStyle = DragLayer.ANIMATION_END_REMAIN_VISIBLE;
+            } else {
+                endStyle = DragLayer.ANIMATION_END_DISAPPEAR;;
+            }
+
+            Runnable onComplete = new Runnable() {
+                @Override
+                public void run() {
+                    if (finalView != null) {
+                        finalView.setVisibility(VISIBLE);
+                    }
+                    if (onCompleteRunnable != null) {
+                        onCompleteRunnable.run();
+                    }
+                }
+            };
+            dragLayer.animateViewIntoPosition(dragView, from.left, from.top, finalPos[0],
+                    finalPos[1], 1, 1, 1, scaleXY[0], scaleXY[1], onComplete, endStyle,
+                    duration, this);
+        }
+    }
+
+    public void setFinalTransitionTransform(CellLayout layout) {
+        if (isSwitchingState()) {
+            int index = indexOfChild(layout);
+            mCurrentScaleX = layout.getScaleX();
+            mCurrentScaleY = layout.getScaleY();
+            mCurrentTranslationX = layout.getTranslationX();
+            mCurrentTranslationY = layout.getTranslationY();
+            mCurrentRotationY = layout.getRotationY();
+            layout.setScaleX(mNewScaleXs[index]);
+            layout.setScaleY(mNewScaleYs[index]);
+            layout.setTranslationX(mNewTranslationXs[index]);
+            layout.setTranslationY(mNewTranslationYs[index]);
+            layout.setRotationY(mNewRotationYs[index]);
+        }
+    }
+    public void resetTransitionTransform(CellLayout layout) {
+        if (isSwitchingState()) {
+            mCurrentScaleX = layout.getScaleX();
+            mCurrentScaleY = layout.getScaleY();
+            mCurrentTranslationX = layout.getTranslationX();
+            mCurrentTranslationY = layout.getTranslationY();
+            mCurrentRotationY = layout.getRotationY();
+            layout.setScaleX(mCurrentScaleX);
+            layout.setScaleY(mCurrentScaleY);
+            layout.setTranslationX(mCurrentTranslationX);
+            layout.setTranslationY(mCurrentTranslationY);
+            layout.setRotationY(mCurrentRotationY);
+        }
+    }
+
+    /**
+     * Return the current {@link CellLayout}, correctly picking the destination
+     * screen while a scroll is in progress.
+     */
+    public CellLayout getCurrentDropLayout() {
+        return (CellLayout) getChildAt(getNextPage());
+    }
+
+    /**
+     * Return the current CellInfo describing our current drag; this method exists
+     * so that Launcher can sync this object with the correct info when the activity is created/
+     * destroyed
+     *
+     */
+    public CellLayout.CellInfo getDragInfo() {
+        return mDragInfo;
+    }
+
+    /**
+     * Calculate the nearest cell where the given object would be dropped.
+     *
+     * pixelX and pixelY should be in the coordinate system of layout
+     */
+    private int[] findNearestArea(int pixelX, int pixelY,
+            int spanX, int spanY, CellLayout layout, int[] recycle) {
+        return layout.findNearestArea(
+                pixelX, pixelY, spanX, spanY, recycle);
+    }
+
+    void setup(DragController dragController) {
+        mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
+        mDragController = dragController;
+
+        // hardware layers on children are enabled on startup, but should be disabled until
+        // needed
+        updateChildrenLayersEnabled(false);
+        setWallpaperDimension();
+    }
+
+    /**
+     * Called at the end of a drag which originated on the workspace.
+     */
+    public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
+            boolean success) {
+        if (success) {
+            if (target != this) {
+                if (mDragInfo != null) {
+                    getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
+                    if (mDragInfo.cell instanceof DropTarget) {
+                        mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
+                    }
+                }
+            }
+        } else if (mDragInfo != null) {
+            CellLayout cellLayout;
+            if (mLauncher.isHotseatLayout(target)) {
+                cellLayout = mLauncher.getHotseat().getLayout();
+            } else {
+                cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
+            }
+            cellLayout.onDropChild(mDragInfo.cell);
+        }
+        if (d.cancelled &&  mDragInfo.cell != null) {
+                mDragInfo.cell.setVisibility(VISIBLE);
+        }
+        mDragOutline = null;
+        mDragInfo = null;
+
+        // Hide the scrolling indicator after you pick up an item
+        hideScrollingIndicator(false);
+    }
+
+    void updateItemLocationsInDatabase(CellLayout cl) {
+        int count = cl.getShortcutsAndWidgets().getChildCount();
+
+        int screen = indexOfChild(cl);
+        int container = Favorites.CONTAINER_DESKTOP;
+
+        if (mLauncher.isHotseatLayout(cl)) {
+            screen = -1;
+            container = Favorites.CONTAINER_HOTSEAT;
+        }
+
+        for (int i = 0; i < count; i++) {
+            View v = cl.getShortcutsAndWidgets().getChildAt(i);
+            ItemInfo info = (ItemInfo) v.getTag();
+            // Null check required as the AllApps button doesn't have an item info
+            if (info != null && info.requiresDbUpdate) {
+                info.requiresDbUpdate = false;
+                LauncherModel.modifyItemInDatabase(mLauncher, info, container, screen, info.cellX,
+                        info.cellY, info.spanX, info.spanY);
+            }
+        }
+    }
+
+    @Override
+    public boolean supportsFlingToDelete() {
+        return true;
+    }
+
+    @Override
+    public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
+        // Do nothing
+    }
+
+    @Override
+    public void onFlingToDeleteCompleted() {
+        // Do nothing
+    }
+
+    public boolean isDropEnabled() {
+        return true;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        super.onRestoreInstanceState(state);
+        Launcher.setScreen(mCurrentPage);
+    }
+
+    @Override
+    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+        // We don't dispatch restoreInstanceState to our children using this code path.
+        // Some pages will be restored immediately as their items are bound immediately, and 
+        // others we will need to wait until after their items are bound.
+        mSavedStates = container;
+    }
+
+    public void restoreInstanceStateForChild(int child) {
+        if (mSavedStates != null) {
+            mRestoredPages.add(child);
+            CellLayout cl = (CellLayout) getChildAt(child);
+            cl.restoreInstanceState(mSavedStates);
+        }
+    }
+
+    public void restoreInstanceStateForRemainingPages() {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            if (!mRestoredPages.contains(i)) {
+                restoreInstanceStateForChild(i);
+            }
+        }
+        mRestoredPages.clear();
+    }
+
+    @Override
+    public void scrollLeft() {
+        if (!isSmall() && !mIsSwitchingState) {
+            super.scrollLeft();
+        }
+        Folder openFolder = getOpenFolder();
+        if (openFolder != null) {
+            openFolder.completeDragExit();
+        }
+    }
+
+    @Override
+    public void scrollRight() {
+        if (!isSmall() && !mIsSwitchingState) {
+            super.scrollRight();
+        }
+        Folder openFolder = getOpenFolder();
+        if (openFolder != null) {
+            openFolder.completeDragExit();
+        }
+    }
+
+    @Override
+    public boolean onEnterScrollArea(int x, int y, int direction) {
+        // Ignore the scroll area if we are dragging over the hot seat
+        boolean isPortrait = !LauncherApplication.isScreenLandscape(getContext());
+        if (mLauncher.getHotseat() != null && isPortrait) {
+            Rect r = new Rect();
+            mLauncher.getHotseat().getHitRect(r);
+            if (r.contains(x, y)) {
+                return false;
+            }
+        }
+
+        boolean result = false;
+        if (!isSmall() && !mIsSwitchingState) {
+            mInScrollArea = true;
+
+            final int page = getNextPage() +
+                       (direction == DragController.SCROLL_LEFT ? -1 : 1);
+
+            // We always want to exit the current layout to ensure parity of enter / exit
+            setCurrentDropLayout(null);
+
+            if (0 <= page && page < getChildCount()) {
+                CellLayout layout = (CellLayout) getChildAt(page);
+                setCurrentDragOverlappingLayout(layout);
+
+                // Workspace is responsible for drawing the edge glow on adjacent pages,
+                // so we need to redraw the workspace when this may have changed.
+                invalidate();
+                result = true;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public boolean onExitScrollArea() {
+        boolean result = false;
+        if (mInScrollArea) {
+            invalidate();
+            CellLayout layout = getCurrentDropLayout();
+            setCurrentDropLayout(layout);
+            setCurrentDragOverlappingLayout(layout);
+
+            result = true;
+            mInScrollArea = false;
+        }
+        return result;
+    }
+
+    private void onResetScrollArea() {
+        setCurrentDragOverlappingLayout(null);
+        mInScrollArea = false;
+    }
+
+    /**
+     * Returns a specific CellLayout
+     */
+    CellLayout getParentCellLayoutForView(View v) {
+        ArrayList<CellLayout> layouts = getWorkspaceAndHotseatCellLayouts();
+        for (CellLayout layout : layouts) {
+            if (layout.getShortcutsAndWidgets().indexOfChild(v) > -1) {
+                return layout;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a list of all the CellLayouts in the workspace.
+     */
+    ArrayList<CellLayout> getWorkspaceAndHotseatCellLayouts() {
+        ArrayList<CellLayout> layouts = new ArrayList<CellLayout>();
+        int screenCount = getChildCount();
+        for (int screen = 0; screen < screenCount; screen++) {
+            layouts.add(((CellLayout) getChildAt(screen)));
+        }
+        if (mLauncher.getHotseat() != null) {
+            layouts.add(mLauncher.getHotseat().getLayout());
+        }
+        return layouts;
+    }
+
+    /**
+     * We should only use this to search for specific children.  Do not use this method to modify
+     * ShortcutsAndWidgetsContainer directly. Includes ShortcutAndWidgetContainers from
+     * the hotseat and workspace pages
+     */
+    ArrayList<ShortcutAndWidgetContainer> getAllShortcutAndWidgetContainers() {
+        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
+                new ArrayList<ShortcutAndWidgetContainer>();
+        int screenCount = getChildCount();
+        for (int screen = 0; screen < screenCount; screen++) {
+            childrenLayouts.add(((CellLayout) getChildAt(screen)).getShortcutsAndWidgets());
+        }
+        if (mLauncher.getHotseat() != null) {
+            childrenLayouts.add(mLauncher.getHotseat().getLayout().getShortcutsAndWidgets());
+        }
+        return childrenLayouts;
+    }
+
+    public Folder getFolderForTag(Object tag) {
+        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
+                getAllShortcutAndWidgetContainers();
+        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
+            int count = layout.getChildCount();
+            for (int i = 0; i < count; i++) {
+                View child = layout.getChildAt(i);
+                if (child instanceof Folder) {
+                    Folder f = (Folder) child;
+                    if (f.getInfo() == tag && f.getInfo().opened) {
+                        return f;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public View getViewForTag(Object tag) {
+        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
+                getAllShortcutAndWidgetContainers();
+        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
+            int count = layout.getChildCount();
+            for (int i = 0; i < count; i++) {
+                View child = layout.getChildAt(i);
+                if (child.getTag() == tag) {
+                    return child;
+                }
+            }
+        }
+        return null;
+    }
+
+    void clearDropTargets() {
+        ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
+                getAllShortcutAndWidgetContainers();
+        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
+            int childCount = layout.getChildCount();
+            for (int j = 0; j < childCount; j++) {
+                View v = layout.getChildAt(j);
+                if (v instanceof DropTarget) {
+                    mDragController.removeDropTarget((DropTarget) v);
+                }
+            }
+        }
+    }
+
+    void removeItems(final ArrayList<String> packages) {
+        final HashSet<String> packageNames = new HashSet<String>();
+        packageNames.addAll(packages);
+
+        ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
+        for (final CellLayout layoutParent: cellLayouts) {
+            final ViewGroup layout = layoutParent.getShortcutsAndWidgets();
+
+            // Avoid ANRs by treating each screen separately
+            post(new Runnable() {
+                public void run() {
+                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
+                    childrenToRemove.clear();
+
+                    int childCount = layout.getChildCount();
+                    for (int j = 0; j < childCount; j++) {
+                        final View view = layout.getChildAt(j);
+                        Object tag = view.getTag();
+
+                        if (tag instanceof ShortcutInfo) {
+                            final ShortcutInfo info = (ShortcutInfo) tag;
+                            final Intent intent = info.intent;
+                            final ComponentName name = intent.getComponent();
+
+                            if (name != null) {
+                                if (packageNames.contains(name.getPackageName())) {
+                                    LauncherModel.deleteItemFromDatabase(mLauncher, info);
+                                    childrenToRemove.add(view);
+                                }
+                            }
+                        } else if (tag instanceof FolderInfo) {
+                            final FolderInfo info = (FolderInfo) tag;
+                            final ArrayList<ShortcutInfo> contents = info.contents;
+                            final int contentsCount = contents.size();
+                            final ArrayList<ShortcutInfo> appsToRemoveFromFolder =
+                                    new ArrayList<ShortcutInfo>();
+
+                            for (int k = 0; k < contentsCount; k++) {
+                                final ShortcutInfo appInfo = contents.get(k);
+                                final Intent intent = appInfo.intent;
+                                final ComponentName name = intent.getComponent();
+
+                                if (name != null) {
+                                    if (packageNames.contains(name.getPackageName())) {
+                                        appsToRemoveFromFolder.add(appInfo);
+                                    }
+                                }
+                            }
+                            for (ShortcutInfo item: appsToRemoveFromFolder) {
+                                info.remove(item);
+                                LauncherModel.deleteItemFromDatabase(mLauncher, item);
+                            }
+                        } else if (tag instanceof LauncherAppWidgetInfo) {
+                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
+                            final ComponentName provider = info.providerName;
+                            if (provider != null) {
+                                if (packageNames.contains(provider.getPackageName())) {
+                                    LauncherModel.deleteItemFromDatabase(mLauncher, info);
+                                    childrenToRemove.add(view);
+                                }
+                            }
+                        }
+                    }
+
+                    childCount = childrenToRemove.size();
+                    for (int j = 0; j < childCount; j++) {
+                        View child = childrenToRemove.get(j);
+                        // Note: We can not remove the view directly from CellLayoutChildren as this
+                        // does not re-mark the spaces as unoccupied.
+                        layoutParent.removeViewInLayout(child);
+                        if (child instanceof DropTarget) {
+                            mDragController.removeDropTarget((DropTarget)child);
+                        }
+                    }
+
+                    if (childCount > 0) {
+                        layout.requestLayout();
+                        layout.invalidate();
+                    }
+                }
+            });
+        }
+
+        // Clean up new-apps animation list
+        final Context context = getContext();
+        post(new Runnable() {
+            @Override
+            public void run() {
+                String spKey = LauncherApplication.getSharedPreferencesKey();
+                SharedPreferences sp = context.getSharedPreferences(spKey,
+                        Context.MODE_PRIVATE);
+                Set<String> newApps = sp.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY,
+                        null);
+
+                // Remove all queued items that match the same package
+                if (newApps != null) {
+                    synchronized (newApps) {
+                        Iterator<String> iter = newApps.iterator();
+                        while (iter.hasNext()) {
+                            try {
+                                Intent intent = Intent.parseUri(iter.next(), 0);
+                                String pn = ItemInfo.getPackageName(intent);
+                                if (packageNames.contains(pn)) {
+                                    iter.remove();
+                                }
+
+                                // It is possible that we've queued an item to be loaded, yet it has
+                                // not been added to the workspace, so remove those items as well.
+                                ArrayList<ItemInfo> shortcuts;
+                                shortcuts = LauncherModel.getWorkspaceShortcutItemInfosWithIntent(
+                                        intent);
+                                for (ItemInfo info : shortcuts) {
+                                    LauncherModel.deleteItemFromDatabase(context, info);
+                                }
+                            } catch (URISyntaxException e) {}
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
+        ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers();
+        for (ShortcutAndWidgetContainer layout: childrenLayouts) {
+            int childCount = layout.getChildCount();
+            for (int j = 0; j < childCount; j++) {
+                final View view = layout.getChildAt(j);
+                Object tag = view.getTag();
+                if (tag instanceof ShortcutInfo) {
+                    ShortcutInfo info = (ShortcutInfo) tag;
+                    // We need to check for ACTION_MAIN otherwise getComponent() might
+                    // return null for some shortcuts (for instance, for shortcuts to
+                    // web pages.)
+                    final Intent intent = info.intent;
+                    final ComponentName name = intent.getComponent();
+                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
+                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
+                        final int appCount = apps.size();
+                        for (int k = 0; k < appCount; k++) {
+                            ApplicationInfo app = apps.get(k);
+                            if (app.componentName.equals(name)) {
+                                BubbleTextView shortcut = (BubbleTextView) view;
+                                info.updateIcon(mIconCache);
+                                info.title = app.title.toString();
+                                shortcut.applyFromShortcutInfo(info, mIconCache);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    void moveToDefaultScreen(boolean animate) {
+        if (!isSmall()) {
+            if (animate) {
+                snapToPage(mDefaultPage);
+            } else {
+                setCurrentPage(mDefaultPage);
+            }
+        }
+        getChildAt(mDefaultPage).requestFocus();
+    }
+
+    @Override
+    public void syncPages() {
+    }
+
+    @Override
+    public void syncPageItems(int page, boolean immediate) {
+    }
+
+    @Override
+    protected String getCurrentPageDescription() {
+        int page = (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
+        return String.format(getContext().getString(R.string.workspace_scroll_format),
+                page + 1, getChildCount());
+    }
+
+    public void getLocationInDragLayer(int[] loc) {
+        mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
+    }
+
+    void setFadeForOverScroll(float fade) {
+        if (!isScrollingIndicatorEnabled()) return;
+
+        mOverscrollFade = fade;
+        final View scrollIndicator = getScrollingIndicator();
+
+        cancelScrollingIndicatorAnimations();
+        scrollIndicator.setAlpha(1 - fade);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper.java
new file mode 100644
index 0000000..640b885
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/EdgeSwipeAppMenuHelper.java
@@ -0,0 +1,772 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe;
+
+import org.fairphone.launcher.ApplicationInfo;
+import org.fairphone.launcher.DragController;
+import org.fairphone.launcher.Launcher;
+import org.fairphone.launcher.R;
+import org.fairphone.launcher.edgeswipe.edit.FavoritesStorageHelper;
+import org.fairphone.launcher.edgeswipe.ui.EdgeSwipeInterceptorViewListener;
+import org.fairphone.launcher.util.KWMathUtils;
+
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.HapticFeedbackConstants;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+public class EdgeSwipeAppMenuHelper implements EdgeSwipeInterceptorViewListener
+{
+
+    private static final String TAG = EdgeSwipeAppMenuHelper.class.getSimpleName();
+
+    private static int MAX_FAVORITE_APPS = 4;
+    private static int ITEM_COUNT = 5;
+
+    public static enum Side
+    {
+        LEFT, RIGHT
+    };
+
+    enum IconEndPositions
+    {
+        Icon1(0, 0), Icon2(0, 0), Icon3(0, 0), Icon4(0, 0), Icon5(0, 0);
+
+        private int x;
+        private int y;
+
+        private IconEndPositions(int x, int y)
+        {
+            this.x = x;
+            this.y = y;
+        }
+
+        public int getX()
+        {
+            return x;
+        }
+
+        public int getY()
+        {
+            return y;
+        }
+    }
+
+    private int mMenuWidth;
+    private int mMenuHeight;
+
+    private int mIconWidth;
+    private int mIconHeight;
+
+    private float mCenterX;
+    private float mCenterY;
+
+    private Side mCurrentSide;
+
+    private float innerDeadzone;
+    private float outerDeadzone;
+
+    private ViewGroup menuContainerView;
+    private View menuRoot;
+    private View menuContent;
+    private View menuBackground;
+    private View editGroup;
+    private View swipeMenuTopShadow;
+    private View swipeMenuBottomShadow;
+
+    private Context mContext;
+
+    private ItemIcon[] icons;
+
+    private int prevVisibleIcon;
+    private Launcher mLauncher;
+    private DisplayMetrics mDisplayMetrics;
+
+    private boolean mIsInitialized;
+    private boolean isInSelection;
+
+	private long mEditMenuButtonStartTime;
+
+    public class ItemIcon
+    {
+        TextView selectedViewName;
+        View rootView;
+        View iconRingView;
+        Intent intent;
+
+        private ItemIcon(View rootView, Drawable iconSelected, String iconSelectedName, Intent intent)
+        {
+            this.intent = intent;
+            this.rootView = rootView;
+
+            selectedViewName = (TextView) rootView.findViewById(R.id.iconSelectedName);
+            iconRingView = rootView.findViewById(R.id.iconPressRing);
+
+            Resources r = mContext.getResources();
+            float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, r.getDisplayMetrics());
+            iconSelected.setBounds(0, 0, Math.round(px), Math.round(px));
+            selectedViewName.setCompoundDrawables(null, iconSelected, null, null);
+
+            // App drawer doesn't have a text description
+            if (selectedViewName != null)
+            {
+                selectedViewName.setText(iconSelectedName);
+            }
+        }
+    }
+
+    public EdgeSwipeAppMenuHelper(Context context, DragController detectorView, ViewGroup menuContainerView, Launcher launcher)
+    {
+
+        mContext = context;
+        mIsInitialized = false;
+        prevVisibleIcon = -1;
+        isInSelection = false;
+
+        icons = new ItemIcon[ITEM_COUNT];
+
+        this.setMenuContainerView(menuContainerView);
+        this.mLauncher = launcher;
+
+        detectorView.addOnSelectionListener(this);
+
+        mDisplayMetrics = new DisplayMetrics();
+
+        launcher.getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
+
+        setCurrentSide(null);
+
+        setupLayout();
+
+        setDeadzones();
+    }
+
+    /**
+     * Set the inner and outer deadzones to control icon selection
+     */
+    private void setDeadzones()
+    {
+        innerDeadzone = convertDpToPixels(mLauncher.getResources().getDimensionPixelSize(R.dimen.edge_swipe_inner_deadzone));
+        outerDeadzone = convertDpToPixels(mLauncher.getResources().getDimensionPixelSize(R.dimen.edge_swipe_outer_deadzone));
+    }
+
+    private int convertDpToPixels(float dpToConvert)
+    {
+
+        // Get the screen's density scale
+        final float scale = mLauncher.getResources().getDisplayMetrics().density;
+
+        // Convert the dps to pixels, based on density scale
+        return (int) (dpToConvert * scale + 0.5f);
+    }
+
+    public ItemIcon[] getIcons()
+    {
+        return icons;
+    }
+    
+
+    @Override
+    public void onSelectionStarted(float pointerX, float pointerY)
+    {
+
+        // update the icons
+        if (!mIsInitialized)
+        {
+            updateIcons();
+            mIsInitialized = true;
+        }
+
+        isInSelection = true;
+        
+        // set the Y coords
+        float newPointerY = pointerY;
+        
+        setupCurrentDisplay(pointerX, newPointerY);
+
+        // Animate the menu
+        // setup the side animation
+        Animation animation = setTheSwipeSideAnimation(pointerX);
+
+        // show the menu and background views
+        getMenuContainerView().setVisibility(View.VISIBLE);
+        menuRoot.setVisibility(View.VISIBLE);
+        menuBackground.setVisibility(View.VISIBLE);
+        menuContent.setVisibility(View.VISIBLE);
+        menuContent.startAnimation(animation);
+        
+        swipeMenuTopShadow.setVisibility(View.VISIBLE);
+        swipeMenuBottomShadow.setVisibility(View.VISIBLE);
+
+        // Animate the background
+        Animation backAnimation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_background_fade_in);
+        menuBackground.startAnimation(backAnimation);
+
+        // define the side of the swipe
+        int halfMenuWidth = menuRoot.getWidth() / 2;
+        int halfContentWidth = menuContent.getWidth() / 2;
+        
+        // set the X coords
+        switch (getCurrentSide())
+        {
+            case LEFT:
+                menuRoot.setX(-halfMenuWidth + (halfContentWidth - halfMenuWidth) / 2);
+                break;
+            case RIGHT:
+                menuRoot.setX((int) (mDisplayMetrics.widthPixels - halfContentWidth));
+                break;
+            default:
+                break;
+        }
+        
+        
+        setupEditButtonPositionAndTimer(newPointerY);
+        
+        float menuYCoord = newPointerY - halfMenuWidth;
+        
+        menuRoot.setY(menuYCoord);
+
+        // update the icons position
+        updateIconPosition();
+    }
+
+	private boolean startEditButtonAnimation() {
+		boolean isTimeToShow = mEditMenuButtonStartTime < System.currentTimeMillis();
+		if(isTimeToShow && (editGroup.getVisibility() != View.VISIBLE) && menuRoot.getVisibility() == View.VISIBLE){
+			Animation editMenuAnimation = getEditButtonAnimation();        
+	        if(editMenuAnimation != null){
+		        //set the button visible and animate
+		        editGroup.setVisibility(View.VISIBLE);
+		        editGroup.startAnimation(editMenuAnimation);
+	        }
+		}else{
+			Log.d(TAG, "Edit button can't be shown");
+		}
+		return isTimeToShow;
+	}
+
+	private void setupEditButtonPositionAndTimer(float pointerY) {
+		
+		//set edit menu button timer
+        mEditMenuButtonStartTime = System.currentTimeMillis() + mLauncher.getApplicationContext().getResources().getInteger(R.integer.config_edgeMenuEditButtonTime);
+        
+		// set the X coords
+		switch (getCurrentSide())
+        {
+            case LEFT:
+                editGroup.setX((int) (mDisplayMetrics.widthPixels - editGroup.getWidth()));
+                break;
+            case RIGHT:
+                editGroup.setX(0);
+                break;
+            default:
+                break;
+        }
+        
+        //set Y coords
+        editGroup.setY(pointerY-(editGroup.getHeight()/2));
+	}
+	
+	private Animation getEditButtonAnimation() {	
+		Animation editMenuAnimation = AnimationUtils.loadAnimation(editGroup.getContext(), R.anim.menu_edge_edit_button_fade_in);
+
+		return editMenuAnimation;
+	}
+
+    private Animation setTheSwipeSideAnimation(float pointerX)
+    {
+        Animation animation;
+        if (pointerX < mDisplayMetrics.widthPixels / 2)
+        {
+            setCurrentSide(Side.LEFT);
+            menuContent.setX(-menuContent.getWidth() + menuRoot.getWidth());
+            animation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_appear_from_left_animation);
+        }
+        else
+        {
+            setCurrentSide(Side.RIGHT);
+            menuContent.setX(0);
+            animation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_appear_from_right_animation);
+        }
+        return animation;
+    }
+
+    private void setupCurrentDisplay(float pointerX, float pointerY)
+    {
+    	// setup the size
+        mMenuWidth = menuContent.getWidth();
+        mMenuHeight = menuContent.getHeight();
+        
+        // setup the center of the menu
+        mCenterX = pointerX;
+        mCenterY = pointerY;
+
+        // setup the icon size
+        RelativeLayout v = (RelativeLayout) menuContent.findViewById(R.id.icon1);
+        mIconHeight = v.getHeight();
+        mIconWidth = v.getWidth();
+    }
+
+    @Override
+    public void onSelectionUpdate(float pointerX, float pointerY)
+    {   
+    	startEditButtonAnimation();
+    			
+    	//select the edit zone menu with a circle
+    	selectEditFavoritesMenuZone(pointerX, pointerY);
+    	
+        // check to see if the user is above the icon zone
+        if (isInActiveZone(pointerX, pointerY))
+        {
+            // get the icon
+            int iconIndex = getIconIndex(pointerX, pointerY);
+
+            // check to see if the user is changing the icon
+            if (prevVisibleIcon != iconIndex)
+            {          
+                //Animate the selected icon ring
+                startIconRingAppearAnimation(icons[iconIndex].iconRingView);
+                
+                //Animate the previous icon aka remove the ring
+                if(prevVisibleIcon != -1){
+                	startIconRingDisappearAnimation(icons[prevVisibleIcon].iconRingView);
+                }
+                
+                
+                prevVisibleIcon = iconIndex;
+            }
+        }
+        else
+        {
+        	if(prevVisibleIcon != -1){
+        		startIconRingDisappearAnimation(icons[prevVisibleIcon].iconRingView);
+        	}
+        	
+            prevVisibleIcon = -1;
+        }
+
+    }
+
+	private void selectEditFavoritesMenuZone(float pointerX, float pointerY) {
+		if(editGroup.getVisibility() == View.VISIBLE){
+			if(isInEditZone(pointerX, pointerY)){
+	    		View editZoneCircle = editGroup.findViewById(R.id.editRing);
+	    		if(editZoneCircle != null && editZoneCircle.getVisibility() != View.VISIBLE){
+	    			startIconRingAppearAnimation(editZoneCircle);
+	    		}
+	    	}
+	    	else{
+	    		View editZoneCircle = editGroup.findViewById(R.id.editRing);
+	    		if(editZoneCircle != null && editZoneCircle.getVisibility() == View.VISIBLE){
+	    			startIconRingDisappearAnimation(editZoneCircle);
+	    		}
+	    	}
+		}
+	}
+
+    private void startIconRingAppearAnimation(View viewToAnimate)
+    {
+    	menuRoot.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
+    	
+    	Animation iconRingAnimation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_icon_ring_fade_in);
+    	viewToAnimate.setVisibility(View.VISIBLE);
+    	viewToAnimate.startAnimation(iconRingAnimation);
+    }
+    
+	private void startIconRingDisappearAnimation(View viewToAnimate) {
+	    Animation iconRingFadeOutAnimation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_icon_ring_fade_out);    
+	    viewToAnimate.startAnimation(iconRingFadeOutAnimation);
+	    viewToAnimate.setVisibility(View.INVISIBLE);
+	}
+
+    private int getIconIndex(float pointerX, float pointerY)
+    {
+        double deg = KWMathUtils.radToDeg(Math.atan2(-(pointerY - mCenterY), pointerX - mCenterX));
+
+        if (deg < 0)
+        {
+            deg += 360;
+        }
+
+        if (deg > 360)
+        {
+            deg -= 360;
+        }
+
+        float ratio = 0;
+
+        if (getCurrentSide() == Side.RIGHT)
+        {
+            ratio = KWMathUtils.getFloatRatio(90, 270, (float) deg);
+        }
+        else
+        {
+            if (deg <= 90)
+            {
+                ratio = 0.5f - KWMathUtils.getFloatRatio(0, 180, (float) deg);
+            }
+            else
+            {
+                ratio = 1.5f - KWMathUtils.getFloatRatio(180, 360, (float) deg);
+            }
+        }
+
+        float dr = 1.0f / ITEM_COUNT;
+
+        int iconIndex = (int) (ratio / dr);
+
+        if (iconIndex >= ITEM_COUNT)
+        {
+            iconIndex = ITEM_COUNT - 1;
+        }
+
+        return iconIndex;
+    }
+
+    private boolean isInActiveZone(float pointerX, float pointerY)
+    {
+
+        double distance = KWMathUtils.getDistance(pointerX, pointerY, mCenterX, mCenterY);
+        return (distance > innerDeadzone && distance < outerDeadzone);
+    }
+    
+    private boolean isInEditZone(float pointerX, float pointerY)
+    {   
+    	boolean validX = false;
+        boolean validY = false;
+        
+        if(getCurrentSide() == null){
+        	return false;
+        }
+        
+    	switch (getCurrentSide())
+        {
+            case LEFT:
+                validX = pointerX >= editGroup.getX();
+                break;
+            case RIGHT:
+            	validX = pointerX <= (editGroup.getX() + editGroup.getWidth());
+                break;
+            default:
+                break;
+        }
+    	validY = pointerY >= editGroup.getY();
+    	validY &= pointerY <= editGroup.getY() + editGroup.getHeight();
+        
+        return validX && validY;
+    }
+
+    boolean contentVisible = false;
+    boolean backVisible = false;
+
+    @Override
+    public void onSelectionFinished(float pointerX, float pointerY)
+    {
+    	//launch the edit menu
+    	if(editGroup.getVisibility() == View.VISIBLE && isInEditZone(pointerX, pointerY)){	    	
+	    	View editZoneCircle = editGroup.findViewById(R.id.editRing);
+    		if(editZoneCircle != null && editZoneCircle.getVisibility() == View.VISIBLE){
+    			startIconRingDisappearAnimation(editZoneCircle);
+    		}
+    		
+    		//to avoid multiple open actions:
+    		//open edit favorites and then the apps drawer
+    		if (prevVisibleIcon >= 0)
+            {
+            	startIconRingDisappearAnimation(icons[prevVisibleIcon].iconRingView);
+            }
+            
+            prevVisibleIcon = -1;
+            
+	    	mLauncher.startEditFavorites();
+    	}
+    	
+        if (!isInSelection)
+        {
+            return;
+        }
+        isInSelection = false;
+
+        // verify if the menu is showing
+        if (menuContent.getVisibility() == View.VISIBLE)
+        {
+            setMenuSideExitAnimation();
+        }
+        else
+        {
+            contentVisible = false;
+            backVisible = false;
+            menuRoot.setVisibility(View.INVISIBLE);
+            contentVisible = false;
+            getMenuContainerView().setVisibility(View.GONE);
+        }
+
+        setBackgroundExitAnimation();
+
+        if (prevVisibleIcon >= 0)
+        {
+        	startIconRingDisappearAnimation(icons[prevVisibleIcon].iconRingView);
+            launchMenuItem();
+        }
+        
+        prevVisibleIcon = -1;
+
+        setCurrentSide(null);
+
+        editGroup.setVisibility(View.GONE);
+        View editZoneCircle = editGroup.findViewById(R.id.editRing);
+        editZoneCircle.setVisibility(View.GONE);
+        
+        swipeMenuTopShadow.setVisibility(View.GONE);
+        swipeMenuBottomShadow.setVisibility(View.GONE);
+    }
+
+    private void launchMenuItem()
+    {
+        try
+        {
+            if (prevVisibleIcon == 2)
+            {
+                mLauncher.showAllApps(true);
+            }
+            else
+            {
+				if (icons[prevVisibleIcon] != null && icons[prevVisibleIcon].intent != null) {
+					mLauncher.startActivity(this.getMenuContainerView(), icons[prevVisibleIcon].intent, null);
+				} else {
+					//to avoid the addition of fairphone home launcher to appSwitcher
+					mLauncher.startEditFavorites();
+				}
+            }
+
+        } catch (ActivityNotFoundException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    private void setBackgroundExitAnimation()
+    {
+        Animation backAnimation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_background_fade_out);
+
+        backAnimation.setAnimationListener(new AnimationListener()
+        {
+            @Override
+            public void onAnimationStart(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation)
+            {
+                backVisible = false;
+                menuBackground.setVisibility(View.INVISIBLE);
+                menuRoot.setVisibility(View.INVISIBLE);
+            }
+        });
+
+        menuBackground.startAnimation(backAnimation);
+    }
+
+    private void setMenuSideExitAnimation()
+    {
+        // draw back the menu
+        // load the correct side for the animation
+        Animation animation = null;
+        if (getCurrentSide() == Side.LEFT)
+        {
+            animation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_disappear_to_left_animation);
+        }
+        else
+        {
+            animation = AnimationUtils.loadAnimation(menuRoot.getContext(), R.anim.menu_disappear_to_right_animation);
+        }
+
+        getMenuContainerView().setVisibility(View.VISIBLE);
+        contentVisible = true;
+        backVisible = true;
+        animation.setAnimationListener(new AnimationListener()
+        {
+            @Override
+            public void onAnimationStart(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation)
+            {
+                menuRoot.setVisibility(View.INVISIBLE);
+                contentVisible = false;
+                if (!backVisible)
+                {
+                    getMenuContainerView().setVisibility(View.GONE);
+                }
+            }
+        });
+
+        menuContent.startAnimation(animation);
+    }
+
+    private void setupLayout()
+    {
+
+        LayoutInflater.from(getMenuContainerView().getContext()).inflate(R.layout.fp_fav_apps_layout, getMenuContainerView());
+
+        menuRoot = getMenuContainerView().findViewById(R.id.menuRoot);
+        getMenuContainerView().setVisibility(View.INVISIBLE);
+        getMenuContainerView().post(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                getMenuContainerView().setVisibility(View.GONE);
+            }
+        });
+
+        menuContent = menuRoot.findViewById(R.id.menuContent);
+        menuBackground = getMenuContainerView().findViewById(R.id.menuBackground);
+
+        editGroup = getMenuContainerView().findViewById(R.id.editGroup);
+        swipeMenuTopShadow = getMenuContainerView().findViewById(R.id.swipeMenuTopShadow);
+        swipeMenuBottomShadow = getMenuContainerView().findViewById(R.id.swipeMenuBottomShadow);
+    }
+
+    public void updateIcons()
+    {
+        ApplicationInfo[] selectedApps = FavoritesStorageHelper.loadSelectedApps(getMenuContainerView().getContext(), MAX_FAVORITE_APPS);
+        // set apps
+        icons[0] = generateItemForMenu(selectedApps[0], R.id.icon1);
+        icons[1] = generateItemForMenu(selectedApps[1], R.id.icon2);
+        icons[2] = generateAllAppsMenuItem(R.id.icon3);
+        icons[3] = generateItemForMenu(selectedApps[2], R.id.icon4);
+        icons[4] = generateItemForMenu(selectedApps[3], R.id.icon5);
+
+        updateIconPosition();
+    }
+
+    private ItemIcon generateAllAppsMenuItem(int iconId)
+    {
+        return new ItemIcon(menuContent.findViewById(iconId), mLauncher.getResources().getDrawable(R.drawable.ic_allapps), "", null);
+    }
+
+    private ItemIcon generateItemForMenu(ApplicationInfo applicationInfo, int iconId)
+    {
+        Intent launchIntent = null;
+        ComponentName componentName = null;
+        Drawable icon = null;
+        String label = "";
+
+        if (applicationInfo == null)
+        {
+            icon = mLauncher.getResources().getDrawable(R.drawable.edit_holder);
+            label = mLauncher.getString(R.string.edit);
+        }
+        else
+        {
+            componentName = applicationInfo.componentName;
+            icon = new BitmapDrawable(mContext.getResources(), applicationInfo.iconBitmap);
+            label = applicationInfo.getApplicationTitle();
+            PackageManager pacManager = getMenuContainerView().getContext().getPackageManager();
+            launchIntent = pacManager.getLaunchIntentForPackage(componentName.getPackageName());
+            launchIntent.setComponent(componentName);
+        }
+
+        // Set the right ComponentName in order to launch Phone
+        // or Contacts correctly
+
+        return new ItemIcon(menuContent.findViewById(iconId), icon, label, launchIntent);
+    }
+
+    private void updateIconPosition()
+    {
+        float radius = mLauncher.getResources().getDimensionPixelSize(R.dimen.edge_swipe_menu_radius);
+
+        float minAngle = 95;
+        float maxAngle = 265;
+
+        float angleDif = (maxAngle - minAngle) / ITEM_COUNT;
+        float curAngle = minAngle + angleDif / 2;
+        float centerX = (mMenuWidth / 2);
+        float centerY = mMenuHeight / 2;
+        for (int i = 0; i < ITEM_COUNT; i++)
+        {
+            double posX =
+                    (getCurrentSide() == Side.RIGHT ? centerX + 25 : centerX - 25) + (getCurrentSide() == Side.RIGHT ? 1 : -1)
+                            * Math.cos(KWMathUtils.degToRad(curAngle)) * radius;
+            double posY = centerY - Math.sin(KWMathUtils.degToRad(curAngle)) * radius;
+            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) icons[i].rootView.getLayoutParams();
+
+            lp.leftMargin = (int) posX - mIconWidth / 2;
+            lp.topMargin = (int) posY - mIconHeight / 2;
+            icons[i].rootView.setLayoutParams(lp);
+
+            curAngle += angleDif;
+        }
+    }
+
+    public boolean isMenuVisible()
+    {
+        return this.contentVisible;
+    }
+
+    public ViewGroup getMenuContainerView()
+    {
+        return menuContainerView;
+    }
+
+    protected void setMenuContainerView(ViewGroup menuContainerView)
+    {
+        this.menuContainerView = menuContainerView;
+    }
+
+    public Side getCurrentSide()
+    {
+        return mCurrentSide;
+    }
+
+    protected void setCurrentSide(Side mCurrentSide)
+    {
+        this.mCurrentSide = mCurrentSide;
+    }
+
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter.java
new file mode 100644
index 0000000..428c024
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/AllAppsListAdapter.java
@@ -0,0 +1,93 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.edit;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.ApplicationInfo;
+import org.fairphone.launcher.R;
+
+import android.app.Activity;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+
+public class AllAppsListAdapter extends BaseAdapter
+{    
+    private Activity context;
+    private ArrayList<ApplicationInfo> allApps;
+    
+    static class ViewHolder
+    {
+        public TextView appName;
+        public ImageView appImage;
+    }
+
+    public AllAppsListAdapter(Activity context)
+    {
+        this.context = context;
+    }
+
+    public void setAllApps(ArrayList<ApplicationInfo> allApps)
+    {
+        this.allApps = allApps;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent)
+    {
+        View rowView = convertView;
+        if (rowView == null)
+        {
+            LayoutInflater inflater = context.getLayoutInflater();
+            rowView = inflater.inflate(R.layout.fp_favorites_all_apps_list_item, null);
+            ViewHolder viewHolder = new ViewHolder();
+            viewHolder.appName = (TextView) rowView.findViewById(R.id.appText);
+            viewHolder.appImage = (ImageView) rowView.findViewById(R.id.appPicture);
+            rowView.setTag(viewHolder);
+        }
+
+        ViewHolder holder = (ViewHolder) rowView.getTag();
+        ApplicationInfo applicationInfo = allApps.get(position);
+        holder.appName.setText(applicationInfo.getApplicationTitle());
+        holder.appImage.setImageDrawable(new BitmapDrawable(context.getResources(), applicationInfo.iconBitmap));
+        
+        return rowView;
+    }
+
+    @Override
+    public int getCount()
+    {
+        return allApps.size();
+    }
+
+    @Override
+    public Object getItem(int position)
+    {
+        return allApps.get(position);
+    }
+
+    @Override
+    public long getItemId(int position)
+    {
+        return position;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/AppDiscoverer.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/AppDiscoverer.java
new file mode 100644
index 0000000..1f1360f
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/AppDiscoverer.java
@@ -0,0 +1,59 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.edit;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.ApplicationInfo;
+
+import android.content.ComponentName;
+import android.util.Log;
+
+public class AppDiscoverer {
+	private static AppDiscoverer _instance = new AppDiscoverer();
+	
+	private ArrayList<ApplicationInfo> _allApps;
+
+	public static AppDiscoverer getInstance() {
+		return _instance;
+	}
+
+	private AppDiscoverer() {
+		_allApps = new ArrayList<ApplicationInfo>(0); 
+	}
+
+	public void loadAllApps(ArrayList<ApplicationInfo> allApps ) {
+		_allApps = new ArrayList<ApplicationInfo>(allApps);
+	}
+
+	public ArrayList<ApplicationInfo> getPackages(){
+		return _allApps;
+	}
+
+	public ApplicationInfo getApplicationFromComponentName(ComponentName componentName) {
+		
+		//TODO: changes this to O(1) algorithm instead of O(N)
+		for(ApplicationInfo appInfo : _allApps){
+			if(componentName.getClassName().equals(appInfo.componentName.getClassName()) &&
+				componentName.getPackageName().equals(appInfo.componentName.getPackageName())){
+				return appInfo;
+			}
+		}
+		
+		return null;
+	}
+	
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/DragDropItemLayoutListener.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/DragDropItemLayoutListener.java
new file mode 100644
index 0000000..04d4448
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/DragDropItemLayoutListener.java
@@ -0,0 +1,29 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.edit;
+
+import org.fairphone.launcher.ApplicationInfo;
+
+import android.widget.RelativeLayout;
+
+public interface DragDropItemLayoutListener {
+	void setupFavoriteIcon(RelativeLayout rla, ApplicationInfo info, int idx, boolean performAnimation);
+	void showAllAppsRemoveZone();
+	void hideAllAppsRemoveZone();
+	void toggleAllAppRemoveZoneRedGlow(float pointerX, float pointerY);
+	void showAllAppsRemoveZoneRedGlow();
+	void hideAllAppsRemoveZoneRedGlow();
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/EdgeSwipeApplicationInfo.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/EdgeSwipeApplicationInfo.java
new file mode 100644
index 0000000..af676a3
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/EdgeSwipeApplicationInfo.java
@@ -0,0 +1,87 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.edit;
+
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+public class EdgeSwipeApplicationInfo
+{
+    /* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((appName == null) ? 0 : appName.hashCode());
+		result = prime * result + ((icon == null) ? 0 : icon.hashCode());
+		result = prime * result
+				+ ((packageName == null) ? 0 : packageName.hashCode());
+		result = prime * result + versionCode;
+		result = prime * result
+				+ ((versionName == null) ? 0 : versionName.hashCode());
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		EdgeSwipeApplicationInfo other = (EdgeSwipeApplicationInfo) obj;
+		if (appName == null) {
+			if (other.appName != null)
+				return false;
+		} else if (!appName.equals(other.appName))
+			return false;
+		if (icon == null) {
+			if (other.icon != null)
+				return false;
+		} else if (!icon.equals(other.icon))
+			return false;
+		if (packageName == null) {
+			if (other.packageName != null)
+				return false;
+		} else if (!packageName.equals(other.packageName))
+			return false;
+		if (versionCode != other.versionCode)
+			return false;
+		if (versionName == null) {
+			if (other.versionName != null)
+				return false;
+		} else if (!versionName.equals(other.versionName))
+			return false;
+		return true;
+	}
+
+	public String appName = "";
+    public String packageName = "";
+    public String versionName = "";
+    public int versionCode = 0;
+    public Drawable icon;
+
+    public void logPrint()
+    {
+        Log.v(EdgeSwipeApplicationInfo.class.getSimpleName(), appName + "\t" + packageName + "\t" + versionName + "\t" + versionCode);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity.java
new file mode 100644
index 0000000..f4b9d72
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/EditFavoritesActivity.java
@@ -0,0 +1,661 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.edit;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.ApplicationInfo;
+import org.fairphone.launcher.R;
+import org.fairphone.launcher.edgeswipe.ui.EditFavoritesGridView;
+import org.fairphone.launcher.edgeswipe.ui.EditFavoritesGridView.OnEditFavouritesIconDraggedListener;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.DragEvent;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/**
+ * Edit favorites activity implements functionality to edit your favorite apps
+ * that will appear with the edge swipe.
+ */
+public class EditFavoritesActivity extends Activity implements
+		View.OnDragListener, DragDropItemLayoutListener {
+	private static final String TAG = EditFavoritesActivity.class
+			.getSimpleName();
+
+	// This is used to differentiate a drag from the all apps to favorites
+	// from a drag between two favorites to perform a swap
+	public static final int SELECTED_APPS_DRAG = 0;
+	public static final int ALL_APPS_DRAG = 1;
+
+	private AllAppsListAdapter mAllAppsListAdapter;
+	private ArrayList<ApplicationInfo> mAllApps;
+
+	private ArrayList<RelativeLayout> mFavIcons;
+
+	private ApplicationInfo[] mSelectedApps;
+
+	private EditFavoritesGridView mAllAppsGridView;
+
+	private int mDragOrigin;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		setContentView(R.layout.fp_edit_favorites);
+
+		mAllApps = AppDiscoverer.getInstance().getPackages();
+
+		mSelectedApps = FavoritesStorageHelper.loadSelectedApps(this, 4);
+
+		mFavIcons = new ArrayList<RelativeLayout>();
+
+		mFavIcons.add((RelativeLayout) findViewById(R.id.favouriteGroup1));
+		mFavIcons.add((RelativeLayout) findViewById(R.id.favouriteGroup2));
+		mFavIcons.add((RelativeLayout) findViewById(R.id.favouriteGroup3));
+		mFavIcons.add((RelativeLayout) findViewById(R.id.favouriteGroup4));
+
+		setupAllAppsList();
+
+		setupSelectedAppsList();
+	}
+
+	@Override
+	public void onPause() {
+		super.onPause();
+	}
+
+	/**
+	 * Setup the list with all the apps installed on the device.
+	 */
+	private void setupAllAppsList() {
+		mAllAppsGridView = (EditFavoritesGridView) findViewById(R.id.allAppsGridView);
+
+		mAllAppsListAdapter = new AllAppsListAdapter(this);
+
+		mAllAppsListAdapter.setAllApps(mAllApps);
+
+		mAllAppsGridView.setLongClickable(true);
+
+		mAllAppsGridView
+				.setOnItemLongClickListener(new OnItemLongClickListener() {
+					@Override
+					public boolean onItemLongClick(AdapterView<?> parent,
+							View v, int position, long id) {
+						startDraggingIcon(v, position);
+
+						return true;
+					}
+				});
+
+		mAllAppsGridView
+				.setOnEditFavouritesIconDraggedListener(new OnEditFavouritesIconDraggedListener() {
+
+					@Override
+					public void OnEditFavouritesIconDragged(
+							AdapterView<?> parent, View view, int position,
+							long id) {
+						startDraggingIcon(view, position);
+					}
+				});
+
+		mAllAppsGridView.setAdapter(mAllAppsListAdapter);
+
+		// set the drag listener to enable favorite icon removal
+		View allAppsGroupView = findViewById(R.id.allAppsGroup);
+		allAppsGroupView.setOnDragListener(new DropDragEventListener(this,
+				mFavIcons, mSelectedApps, mAllApps, true));
+
+	}
+
+	private void startDraggingIcon(View view, int position) {
+		// display a circle around the possible destinations
+		toggleFavoriteCircleSelection(-1, true);
+
+		View mainView = this.getWindow().getDecorView();
+		ApplicationInfo applicationInfo = mAllApps.get(position);
+
+		// set the item with the origin of the drag and the index of the dragged
+		// view
+		mDragOrigin = EditFavoritesActivity.ALL_APPS_DRAG;
+		String selectedItem = serializeItem(mDragOrigin, position);
+		ClipData.Item item = new ClipData.Item(selectedItem);
+		ClipData dragData = ClipData.newPlainText(
+				applicationInfo.getApplicationTitle(),
+				applicationInfo.getApplicationTitle());
+		dragData.addItem(item);
+
+		mainView.startDrag(dragData,
+				new IconDragShadowBuilder(view, new BitmapDrawable(
+						getResources(), applicationInfo.iconBitmap)), view, 0);
+
+		mainView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+	}
+
+	/**
+	 * Setup the list with the selected app list, which is the holder of the
+	 * apps that has been selected to become the favorite apps.
+	 */
+	private void setupSelectedAppsList() {
+		for (int i = 0; i < 4; i++) {
+			setupFavoriteIcon(mFavIcons.get(i), mSelectedApps[i], i, false);
+
+			// set the listeners
+			// The last argument is set to false since this hasn't the ability
+			// to remove icons, it only switches them
+			mFavIcons.get(i).setOnDragListener(
+					new DropDragEventListener(this, mFavIcons, mSelectedApps,
+							mAllApps, false));
+		}
+	}
+
+	@Override
+	public void setupFavoriteIcon(RelativeLayout rla,
+			ApplicationInfo applicationInfo, int idx, boolean performAnimation) {
+
+		if (applicationInfo == null) {
+			final View dragPlaceholderView = rla.getChildAt(0);
+			final View iconView = rla.getChildAt(1);
+
+			if (performAnimation) {
+				startViewFadeOutFadeInAnimation(dragPlaceholderView, iconView,
+						null);
+			} else {
+				dragPlaceholderView.setVisibility(View.VISIBLE);
+				iconView.setVisibility(View.INVISIBLE);
+			}
+
+			rla.setOnLongClickListener(null);
+			mSelectedApps[idx] = null;
+		} else {
+			final View dragPlaceholderView = rla.getChildAt(0);
+
+			final TextView iconView = (TextView) rla.getChildAt(1);
+
+//			Log.d(TAG, "Adding app : " + applicationInfo.getApplicationTitle());
+
+			if (mSelectedApps[idx] == null) {
+				updateFavoriteIcon(applicationInfo, iconView);
+				if (performAnimation) {
+					startViewFadeOutFadeInAnimation(iconView,
+							dragPlaceholderView, null);
+				} else {
+					dragPlaceholderView.setVisibility(View.INVISIBLE);
+					iconView.setVisibility(View.VISIBLE);
+				}
+			} else {
+				if (performAnimation) {
+					startViewFadeOutFadeInAnimation(null, iconView,
+							applicationInfo);
+				} else {
+					updateFavoriteIcon(applicationInfo, iconView);
+					dragPlaceholderView.setVisibility(View.INVISIBLE);
+					iconView.setVisibility(View.VISIBLE);
+				}
+			}
+			mSelectedApps[idx] = applicationInfo;
+
+			// Set the listener
+			// pass the main view and the instance setup the drag and visibility
+			// of some views
+			final View mainView = this.getWindow().getDecorView();
+			rla.setOnLongClickListener(new IdLongClickListener(idx, mainView,
+					this));
+		}
+
+		FavoritesStorageHelper.storeSelectedApps(this, mSelectedApps);
+	}
+
+	/**
+	 * Update the icon and label of a favorite
+	 * 
+	 * @param applicationInfo
+	 *            App information that contains the icon and label
+	 * @param icon
+	 *            the icon to update
+	 */
+	private void updateFavoriteIcon(ApplicationInfo applicationInfo,
+			final TextView icon) {
+		Drawable drawable = new BitmapDrawable(getResources(),
+				applicationInfo.iconBitmap);
+
+		Resources r = getResources();
+		float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
+				r.getDisplayMetrics());
+		drawable.setBounds(0, 0, Math.round(px), Math.round(px));
+
+		icon.setCompoundDrawables(null, drawable, null, null);
+		icon.setText(applicationInfo.getApplicationTitle());
+	}
+
+	/**
+	 * Performs the animation when replacing one favorite
+	 * 
+	 * @param viewToFadeIn
+	 *            view that will appear. When null it means that we are swapping
+	 *            two favorites
+	 * @param viewToFadeOut
+	 *            view that will disappear.
+	 * @param applicationInfo
+	 *            app info that is used to swap two favorites
+	 */
+	private void startViewFadeOutFadeInAnimation(final View viewToFadeIn,
+			final View viewToFadeOut, final ApplicationInfo applicationInfo) {
+		Animation fadeOutAnimation = AnimationUtils.loadAnimation(this,
+				R.anim.fade_out_fast);
+		fadeOutAnimation.setAnimationListener(new AnimationListener() {
+			@Override
+			public void onAnimationStart(Animation animation) {
+			}
+
+			@Override
+			public void onAnimationRepeat(Animation animation) {
+			}
+
+			@Override
+			public void onAnimationEnd(Animation animation) {
+				viewToFadeOut.setVisibility(View.INVISIBLE);
+
+				if (applicationInfo == null && viewToFadeIn != null) {
+					if (viewToFadeIn.getVisibility() != View.VISIBLE) {
+						viewToFadeIn.setVisibility(View.VISIBLE);
+						Animation fadeInAnimation = AnimationUtils
+								.loadAnimation(getApplicationContext(),
+										R.anim.fade_in_fast);
+						viewToFadeIn.startAnimation(fadeInAnimation);
+					}
+				} else if (applicationInfo != null) {
+					// get the new icon
+					updateFavoriteIcon(applicationInfo,
+							(TextView) viewToFadeOut);
+
+					viewToFadeOut.setVisibility(View.VISIBLE);
+					Animation fadeInAnimation = AnimationUtils.loadAnimation(
+							getApplicationContext(), R.anim.fade_in_fast);
+					viewToFadeOut.startAnimation(fadeInAnimation);
+				}
+			}
+		});
+		if (viewToFadeOut.getVisibility() == View.VISIBLE) {
+			viewToFadeOut.startAnimation(fadeOutAnimation);
+		}
+	}
+
+	/**
+	 * Capture the back button press, to make sure we save the selected apps
+	 * before exiting.
+	 */
+	@Override
+	public void onBackPressed() {
+
+		FavoritesStorageHelper.storeSelectedApps(this, mSelectedApps);
+
+		Intent intent = getIntent();
+		setResult(RESULT_OK, intent);
+
+		finish();
+	}
+
+	/**
+	 * Serializes the item id and origin that is being dragged.
+	 * 
+	 * @param appOrigin
+	 *            the origin: can be SELECT_APPS_DRAG or ALL_APPS_DRAG
+	 * @param appIndex
+	 *            the item index
+	 * @return the serialized item info
+	 */
+	public static String serializeItem(int appOrigin, int appIndex) {
+		String selectedItem = appOrigin + ";" + appIndex;
+		return selectedItem;
+	}
+
+	/**
+	 * Deserializes the item id and origin that is being dragged.
+	 * 
+	 * @param toDeserialize
+	 *            string to deserialize
+	 * @return an array containing {appOrign, appIndex}
+	 */
+	public static String[] deserializeItem(String toDeserialize) {
+		String[] selectedItem = toDeserialize.split(";");
+		return selectedItem;
+	}
+
+	class IdLongClickListener implements View.OnLongClickListener {
+		private int mId;
+		private View mMainView;
+		private DragDropItemLayoutListener mListener;
+
+		public IdLongClickListener(int id, View mainView,
+				DragDropItemLayoutListener listener) {
+			super();
+
+			mId = id;
+			mMainView = mainView;
+			mListener = listener;
+		}
+
+		@Override
+		public boolean onLongClick(View v) {
+			// Show the zone where favorites can be removed
+			mListener.showAllAppsRemoveZone();
+
+			// display a circle around the possible destinations
+			toggleFavoriteCircleSelection(-1, true);
+
+			// set the drag info
+			ApplicationInfo applicationInfo = mSelectedApps[mId];
+
+			// set the item with the origin of the drag and the index of the
+			// dragged view
+			mDragOrigin = EditFavoritesActivity.SELECTED_APPS_DRAG;
+			String selectedItem = serializeItem(mDragOrigin, mId);
+			ClipData.Item item = new ClipData.Item(selectedItem);
+			ClipData dragData = ClipData.newPlainText(
+					applicationInfo.getApplicationTitle(),
+					applicationInfo.getApplicationTitle());
+			dragData.addItem(item);
+
+			mMainView.startDrag(dragData, new IconDragShadowBuilder(v,
+					new BitmapDrawable(getResources(),
+							applicationInfo.iconBitmap)), v, 0);
+
+			mMainView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+
+			return true;
+		}
+	}
+
+	@Override
+	public boolean onDrag(View v, DragEvent event) {
+		return false;
+	}
+
+	private static class DropDragEventListener implements View.OnDragListener {
+
+		private ArrayList<RelativeLayout> mFavIcons;
+		private ApplicationInfo[] mSelectedApps;
+		private ArrayList<ApplicationInfo> mAllApps;
+		private DragDropItemLayoutListener mListener;
+		/**
+		 * True means that a favorite will be removed from the list.
+		 */
+		private boolean mIsToRemove;
+
+		public DropDragEventListener(DragDropItemLayoutListener listener,
+				ArrayList<RelativeLayout> favIcons,
+				ApplicationInfo[] mSelectedApps2,
+				ArrayList<ApplicationInfo> allApps,
+				boolean toDeleteFromFavorites) {
+			mFavIcons = favIcons;
+			mSelectedApps = mSelectedApps2;
+			mAllApps = allApps;
+			mListener = listener;
+			mIsToRemove = toDeleteFromFavorites;
+		}
+
+		@Override
+		public boolean onDrag(View v, DragEvent event) {
+			// Defines a variable to store the action type for the incoming
+			// event
+			final int action = event.getAction();
+
+			RelativeLayout rla = (RelativeLayout) v;
+
+			// Handles each of the expected events
+			switch (action) {
+
+			case DragEvent.ACTION_DRAG_STARTED: {
+				// Moving an icon to an occupied position replaces the
+				// current one
+				return true;
+			}
+			case DragEvent.ACTION_DRAG_ENTERED:
+				// toggle the red glow when removing favorites
+				int idx = mFavIcons.indexOf(rla);
+				if (idx == -1) {
+					mListener.toggleAllAppRemoveZoneRedGlow(event.getX(),
+							event.getY());
+				} else {
+					mListener.hideAllAppsRemoveZoneRedGlow();
+				}
+				break;
+			case DragEvent.ACTION_DRAG_EXITED:
+				mListener.hideAllAppsRemoveZoneRedGlow();
+				break;
+			case DragEvent.ACTION_DROP:
+				int id = mFavIcons.indexOf(rla);
+
+				// get the Item data
+				// 0 is the origin
+				// 1 is the index
+				String[] clipItemData = EditFavoritesActivity
+						.deserializeItem(event
+								.getClipData()
+								.getItemAt(
+										event.getClipData().getItemCount() - 1)
+								.getText().toString());
+
+				int position = -1;
+				ApplicationInfo info = null;
+
+				// obtain the applicationInfo
+				switch (Integer.parseInt(clipItemData[0])) {
+				case EditFavoritesActivity.SELECTED_APPS_DRAG:
+					position = Integer.parseInt(clipItemData[1]);
+
+					// when not removing an icon swap is performed
+					if (!mIsToRemove) {
+						info = mSelectedApps[position];
+						mListener.setupFavoriteIcon(mFavIcons.get(position),
+								mSelectedApps[id], position, true);
+					} else {
+						// remove the favorite
+						id = position;
+						rla = mFavIcons.get(id);
+					}
+					break;
+				case EditFavoritesActivity.ALL_APPS_DRAG:
+					position = Integer.parseInt(clipItemData[1]);
+					info = mAllApps.get(position);
+					break;
+				default:
+					Log.e(TAG,
+							"Unknown Icon Origin received by OnDragListener.");
+					break;
+				}
+
+				// only setup the icon if a valid id is obtained
+				if (id != -1) {
+					mListener.setupFavoriteIcon(rla, info, id, true);
+				}
+
+				return true;
+			case DragEvent.ACTION_DRAG_ENDED:
+				// hide zone remove zone
+				mListener.hideAllAppsRemoveZone();
+				return true;
+			default:
+				Log.e(TAG, "Unknown action type received by OnDragListener.");
+			}
+
+			return false;
+		}
+	}
+
+	private static class IconDragShadowBuilder extends View.DragShadowBuilder {
+
+		private Drawable mIcon;
+
+		public IconDragShadowBuilder(View v, Drawable icon) {
+			super(v);
+
+			// Creates a draggable image that will fill the Canvas provided by
+			// the system.
+			// shadow = new ColorDrawable(Color.LTGRAY);
+			mIcon = icon;
+		}
+
+		@Override
+		public void onProvideShadowMetrics(Point size, Point touch) {
+			// Defines local variables
+			int width;
+			int height;
+
+			// Sets the width of the shadow to half the width of the original
+			// View
+			width = 100;
+
+			// Sets the height of the shadow to half the height of the original
+			// View
+			height = 100;
+
+			// The drag shadow is a ColorDrawable. This sets its dimensions to
+			// be the same as the
+			// Canvas that the system will provide. As a result, the drag shadow
+			// will fill the
+			// Canvas.
+			mIcon.setBounds(0, 0, width, height);
+
+			// Sets the size parameter's width and height values. These get back
+			// to the system
+			// through the size parameter.
+			size.set(width, height);
+
+			// Sets the touch point's position to be in the middle of the drag
+			// shadow
+			touch.set(width / 2, height);
+		}
+
+		// Defines a callback that draws the drag shadow in a Canvas that the
+		// system constructs
+		// from the dimensions passed in onProvideShadowMetrics().
+		@Override
+		public void onDrawShadow(Canvas canvas) {
+
+			// Draws the ColorDrawable in the Canvas passed in from the system.
+			// shadow.draw(canvas);
+			mIcon.draw(canvas);
+		}
+
+	}
+
+	@Override
+	public void hideAllAppsRemoveZone() {
+		hideAllAppsRemoveZoneRedGlow();
+
+		View removeZoneView = findViewById(R.id.allAppsTextView);
+		removeZoneView.setVisibility(View.INVISIBLE);
+
+		mAllAppsGridView.setAlpha(1f);
+
+		// hide the circle around the possible destinations
+		toggleFavoriteCircleSelection(-1, false);
+	}
+
+	@Override
+	public void showAllAppsRemoveZone() {
+		View removeZoneView = findViewById(R.id.allAppsTextView);
+		removeZoneView.setVisibility(View.VISIBLE);
+
+		mAllAppsGridView.setAlpha(0.2f);
+	}
+
+	@Override
+	public void showAllAppsRemoveZoneRedGlow() {
+		View allAppsGroupView = findViewById(R.id.allAppsGroup);
+		allAppsGroupView.setBackground(getResources().getDrawable(R.drawable.fp_edit_favs_remove_red_bg));
+	}
+
+	@Override
+	public void hideAllAppsRemoveZoneRedGlow() {
+		View allAppsGroupView = findViewById(R.id.allAppsGroup);
+		allAppsGroupView.setBackground(getResources().getDrawable(
+				R.drawable.edit_menu_list_background));
+	}
+
+	@Override
+	public void toggleAllAppRemoveZoneRedGlow(float pointerX, float pointerY) {
+		// the red glow only makes sense when removing favorites
+		if (mDragOrigin == SELECTED_APPS_DRAG) {
+			if (isInRemoveZone(pointerX, pointerY)) {
+				showAllAppsRemoveZoneRedGlow();
+			} else {
+				hideAllAppsRemoveZoneRedGlow();
+			}
+		}
+	}
+
+	private boolean isInRemoveZone(float pointerX, float pointerY) {
+
+		boolean validX = false;
+		boolean validY = false;
+		View allAppsGroupView = findViewById(R.id.allAppsGroup);
+
+		validX = pointerX <= (allAppsGroupView.getX() + allAppsGroupView
+				.getWidth());
+		validY = pointerY >= allAppsGroupView.getY();
+
+		return validX && validY;
+	}
+
+	/**
+	 * Display a circle around the favorite possible positions when configuring
+	 * it
+	 * 
+	 * @param selectedFavorite
+	 *            the favorite position that will not be circled. -1 means that
+	 *            all circles will be shown.
+	 * @param showCircle
+	 *            true: displays a white circle; false: displays a faded white
+	 *            circle
+	 */
+	private void toggleFavoriteCircleSelection(int selectedFavorite,
+			boolean showCircle) {
+		for (int i = 0; i < mFavIcons.size(); i++) {
+			if (i != selectedFavorite && showCircle) {
+				mFavIcons.get(i)
+						.setBackground(
+								getResources().getDrawable(
+										R.drawable.edit_menu_circle));
+			} else {
+				mFavIcons.get(i).setBackground(
+						getResources().getDrawable(
+								R.drawable.edit_menu_circle_faded));
+			}
+		}
+	}
+
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/FavoritesStorageHelper.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/FavoritesStorageHelper.java
new file mode 100644
index 0000000..a14b859
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/edit/FavoritesStorageHelper.java
@@ -0,0 +1,189 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.edit;
+
+import java.util.ArrayList;
+
+import org.fairphone.launcher.ApplicationInfo;
+import org.fairphone.launcher.R;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+/**
+ * Favorites storage helper class implements methods to convert a string array
+ * into one string so it can be stored easily in the shared preferences. This is
+ * used to store the selected apps for the favorite app launcher.
+ */
+public abstract class FavoritesStorageHelper
+{
+    private static final String PACKAGE_AND_CLASS_NAME_DELIMITER = ",";
+    private static final String COMPONENT_NAME_DELIMITER = ";";
+
+    private static final String FAVORITES_APPS_SHARED_PREFERENCES_FILE_NAME = "FAVORITES_APPS_SHARED_PREFERENCES_FILE_NAME";
+
+    private static final String FAVORITES_APPS_KEY = "FAVORITES_APPS_KEY";
+
+	private static final String TAG = "FavoritesStorageHelper";
+
+    /**
+     * Load the favorites apps from the shared preferences and get the Android
+     * application info from each, so we can get the app name and icon.
+     */
+    public static ApplicationInfo[] loadSelectedApps(Context context, int maxApps)
+    {
+        ApplicationInfo[] selectedAppArray = new ApplicationInfo[maxApps];
+        
+        SharedPreferences sharedPreferences = context.getSharedPreferences(FAVORITES_APPS_SHARED_PREFERENCES_FILE_NAME, Activity.MODE_PRIVATE);
+
+        String componentNamesString = sharedPreferences.getString(FAVORITES_APPS_KEY, null);
+
+        if (componentNamesString == null || componentNamesString.length() == 0){
+        	componentNamesString = getDefaultEdgeSwipeApps(context);
+        }
+        
+        if (componentNamesString != null)
+        {
+//        	Log.d(TAG, "loading selected apps - {" + componentNamesString + "}");
+        	
+            ArrayList<ComponentName> componentNames = FavoritesStorageHelper.stringToComponentNameArray(componentNamesString);
+            
+            final PackageManager packageManager = context.getApplicationContext().getPackageManager();
+            
+            for (int i = 0; i < Math.min(componentNames.size(), selectedAppArray.length ); i++)
+            {
+            	ApplicationInfo applicationInfo = null;
+                ComponentName currentComponentName = componentNames.get(i);
+                if(currentComponentName != null){
+                	applicationInfo = AppDiscoverer.getInstance().getApplicationFromComponentName(currentComponentName);
+                }
+                
+                selectedAppArray[i] = applicationInfo;
+            }
+        }
+        
+        return selectedAppArray;
+    }
+
+    public static String getDefaultEdgeSwipeApps(Context context) {
+    	return context.getResources().getString(R.string.edge_swipe_default_apps);
+	}
+
+	/**
+     * Store the selected apps in the shared preferences as strings which is the
+     * package names of the apps. The package name of an app serves as the
+     * unique identifier of the app.
+     */
+    public static void storeSelectedApps(Context context, ApplicationInfo[] mSelectedApps)
+    {
+        if ((mSelectedApps != null) && (mSelectedApps.length > 0))
+        {
+            ArrayList<ComponentName> componentNamesArray = new ArrayList<ComponentName>();
+            
+            for (int i = 0; i < mSelectedApps.length; i++) {
+            	
+            	ApplicationInfo applicationInfo = mSelectedApps[i];
+
+            	if(applicationInfo != null) {
+            		componentNamesArray.add(applicationInfo.componentName);
+            	}
+            	else{
+            		componentNamesArray.add(null);
+            	}
+            }
+
+            String componentNamesString = FavoritesStorageHelper.componentNamesArrayToString(componentNamesArray);
+
+            SharedPreferences sharedPreferences = context.getSharedPreferences(FAVORITES_APPS_SHARED_PREFERENCES_FILE_NAME, Activity.MODE_PRIVATE);
+            SharedPreferences.Editor editor = sharedPreferences.edit();
+            
+            editor.putString(FAVORITES_APPS_KEY, componentNamesString);
+            editor.commit();
+        }
+    }
+
+    /**
+     * Convert string array into a single string, where each element in the
+     * string array is separated by the delimiter string.
+     */
+    public static String arrayToString(String[] array, String delimiter)
+    {
+        StringBuilder sb = new StringBuilder();
+        for (String s : array)
+        {
+            if (sb.length() > 0)
+            {
+                sb.append(delimiter);
+            }
+            sb.append(s);
+        }
+
+        return sb.toString();
+    }
+
+    public static String componentNamesArrayToString(ArrayList<ComponentName> array)
+    {
+    	String[] componentNamesStringArray = new String[array.size()];
+        for (int i=0; i < array.size(); i++){
+        	String[] componentNameArray = {"",""};
+        	if(array.get(i) != null){
+        		componentNameArray[0] = array.get(i).getPackageName();
+        		componentNameArray[1] = array.get(i).getClassName();
+        	}
+        	String stringToStore = FavoritesStorageHelper.arrayToString(componentNameArray, PACKAGE_AND_CLASS_NAME_DELIMITER);
+        	componentNamesStringArray[i] = stringToStore.isEmpty()? PACKAGE_AND_CLASS_NAME_DELIMITER : stringToStore;
+        }
+
+        return FavoritesStorageHelper.arrayToString(componentNamesStringArray, COMPONENT_NAME_DELIMITER);
+    }
+    
+    /**
+     * Convert a string into an array of strings, using the delimiter as
+     * separator.
+     */
+    public static String[] stringToArray(String input, String delimiter){
+        return input.split(delimiter);
+    }
+	
+	public static ArrayList<ComponentName> stringToComponentNameArray(String input) {
+		String[] componentNamesStringArray = FavoritesStorageHelper.stringToArray(input, COMPONENT_NAME_DELIMITER);
+		ArrayList<ComponentName> componentNamesArray = new ArrayList<ComponentName>();
+		for (int i=0; i< componentNamesStringArray.length; i++) {
+			if(!componentNamesStringArray[i].equals(PACKAGE_AND_CLASS_NAME_DELIMITER)){
+				String[] componentNameArray = FavoritesStorageHelper.stringToArray(componentNamesStringArray[i], PACKAGE_AND_CLASS_NAME_DELIMITER);
+				ComponentName compName = new ComponentName(componentNameArray[0], componentNameArray[1]);
+				componentNamesArray.add(compName);
+			}else{
+				componentNamesArray.add(null);
+			}
+		}
+		return componentNamesArray;
+	}
+
+	public static void resetFavoritesToDefault(Context context) {
+		SharedPreferences sharedPreferences = context.getSharedPreferences(FAVORITES_APPS_SHARED_PREFERENCES_FILE_NAME, Activity.MODE_PRIVATE);
+		
+		SharedPreferences.Editor editor = sharedPreferences.edit();
+		editor.putString(FAVORITES_APPS_KEY, null);
+		editor.commit();
+		
+		loadSelectedApps(context, 4);
+	}
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView.java
new file mode 100644
index 0000000..728cd0a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/CircularCountdownTimerView.java
@@ -0,0 +1,275 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.ui;
+
+import org.fairphone.launcher.R;
+import org.fairphone.launcher.util.KWMathUtils;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class CircularCountdownTimerView extends View {
+	public interface CircularCountdownListener {
+		public void onCountdownFinished(CircularCountdownTimerView countdownView);
+	}
+
+	private Drawable timerDrawable;
+	private RectF clipBounds = new RectF();
+	private RectF viewBounds = new RectF();
+	private Rect viewBoundsI = new Rect();
+	private Paint clipPaint;
+	private Paint sourcePaint;
+
+	private Bitmap viewBitmap;
+	private BitmapShader timerShader;
+
+	private float curFillRatio = 1.0f;
+	private float startFillRatio = 1.0f;
+	private float endFillRatio = 0.0f;
+	private long animationDuration = 0;
+	private long animationDelay = 0;
+	private long curAnimationTime = 0;
+	private long prevFrame = 0;
+	private boolean isAnimating = false;
+
+	private int prevWidth = 0;
+	private int prevHeight = 0;
+
+	CircularCountdownListener listener;
+
+	public CircularCountdownTimerView(Context context) {
+		super(context);
+		init();
+	}
+
+	public CircularCountdownTimerView(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		init();
+	}
+
+	public CircularCountdownTimerView(Context context, AttributeSet attrs,
+			int defStyle) {
+		super(context, attrs, defStyle);
+		init();
+	}
+
+	public void startCountdownAnimation(long duration) {
+		startCountdownAnimation(duration, 0);
+	}
+
+	public void startCountdownAnimation(long duration, long delay) {
+		prevFrame = System.currentTimeMillis();
+		animationDelay = delay;
+		startFillRatio = 1.0f;
+		curFillRatio = 1.0f;
+		endFillRatio = 0.0f;
+		isAnimating = true;
+		curAnimationTime = 0;
+		animationDuration = duration;
+
+		postInvalidate();
+	}
+
+	public boolean isCountingDown() {
+		return isAnimating;
+	}
+
+	public boolean isFinished() {
+		return curFillRatio == 0.0f;
+	}
+
+	public float getCountdownRatio() {
+		return curFillRatio;
+	}
+
+	public void pauseCountdownAnimation() {
+		isAnimating = false;
+		postInvalidate();
+	}
+
+	public void resumeCountdownAnimation() {
+		isAnimating = true;
+		prevFrame = System.currentTimeMillis();
+		postInvalidate();
+	}
+
+	public void cancelCountdownAnimation() {
+		alpha = 0;
+		isAnimating = false;
+		curFillRatio = 1.0f;
+		curAnimationTime = 0;
+		postInvalidate();
+	}
+
+	public void finishCountdownAnimation() {
+		alpha = 0;
+		postInvalidate();
+		curAnimationTime = animationDuration;
+		curFillRatio = 0.0f;
+	}
+
+	public void forceCountdownBegin() {
+		alpha = 0;
+		curFillRatio = 1.0f;
+		isAnimating = false;
+		postInvalidate();
+	}
+
+	public void forceCountdownEnd() {
+		alpha = 0;
+		curFillRatio = 0.0f;
+		isAnimating = false;
+		postInvalidate();
+	}
+
+	public CircularCountdownListener getCircularCountdownListener() {
+		return listener;
+	}
+
+	public void setCircularCountdownListener(CircularCountdownListener listener) {
+		this.listener = listener;
+	}
+
+	@Override
+	protected void onAttachedToWindow() {
+		super.onAttachedToWindow();
+	}
+
+	@Override
+	protected void onDetachedFromWindow() {
+		clipPaint.setShader(null);
+		timerShader = null;
+		viewBitmap.recycle();
+		viewBitmap = null;
+		super.onDetachedFromWindow();
+	}
+
+	private void init() {
+		timerDrawable = getContext().getResources().getDrawable(
+				R.drawable.fp_fav_icon_ring);
+
+		clipPaint = new Paint();
+		clipPaint.setColor(0xFFFFFFFF);
+		sourcePaint = new Paint();
+		sourcePaint.setColor(0xFFFFFFFF);
+	}
+
+	@Override
+	protected void onLayout(boolean changed, int left, int top, int right,
+			int bottom) {
+		super.onLayout(changed, left, top, right, bottom);
+
+		float w = getWidth();
+		float h = getHeight();
+		float w2 = w / 2;
+		float h2 = h / 2;
+		timerDrawable.setBounds(0, 0, (int) w, (int) h);
+
+		float radius = (float) Math.sqrt(w2 * w2 + h2 * h2);
+		clipBounds.set(w2 - radius, h2 - radius, w2 + radius, h2 + radius);
+		viewBounds.set(0, 0, (int) w, (int) h);
+		viewBoundsI.set(0, 0, (int) w, (int) h);
+
+		if (getWidth() != prevWidth || getHeight() != prevHeight
+				|| viewBitmap == null) {
+			if (viewBitmap != null) {
+				viewBitmap.recycle();
+			}
+
+			viewBitmap = Bitmap.createBitmap(getWidth(), getHeight(),
+					Bitmap.Config.ARGB_8888);
+			Canvas canvas = new Canvas(viewBitmap);
+			// canvas.drawBitmap(sourceBitmap, auxRectI, viewBoundsI,
+			// sourcePaint);
+			timerDrawable.setBounds(viewBoundsI);
+			timerDrawable.draw(canvas);
+
+			timerShader = new BitmapShader(viewBitmap, Shader.TileMode.CLAMP,
+					Shader.TileMode.CLAMP);
+			clipPaint.setShader(timerShader);
+		}
+
+		prevWidth = getWidth();
+		prevHeight = getHeight();
+	}
+
+	@Override
+	public void draw(Canvas canvas) {
+		super.draw(canvas);
+		updateAnimation();
+
+		if (curAnimationTime - animationDelay > 0) {
+			alpha += 0.03f;
+			
+			if(alpha > 1.0f){
+				alpha = 1.0f;
+			}
+			
+			
+		}
+		
+		setAlpha(alpha);
+		
+		if (timerShader != null) {
+			canvas.drawArc(viewBounds, 0, 360.f * curFillRatio, true,
+					clipPaint);
+		}
+	}
+	float alpha = 0;
+	
+	private void updateAnimation() {
+		long curTime = System.currentTimeMillis();
+		long dt = curTime - prevFrame;
+		if (dt > 500) {
+			dt = 1000 / 60;
+		}
+		if (isAnimating) {
+			curAnimationTime += dt;
+			boolean isFinished = false;
+			long curAnimTime = Math.max(curAnimationTime - animationDelay, 0);
+			if (curAnimTime >= animationDuration) {
+				curAnimTime = animationDuration;
+				curAnimTime = animationDuration + animationDelay;
+				isFinished = true;
+				isAnimating = false;
+				alpha = 0;
+			}
+
+			float timeRatio = KWMathUtils.getLongRatio(0, animationDuration,
+					curAnimTime);
+			curFillRatio = KWMathUtils.blend(startFillRatio, endFillRatio,
+					timeRatio);
+
+			invalidate();
+			if (isFinished) {
+				alpha = 0;
+				if (listener != null) {
+					listener.onCountdownFinished(this);
+				}
+			}
+		}
+		prevFrame = curTime;
+	}
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/EdgeSwipeInterceptorViewListener.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/EdgeSwipeInterceptorViewListener.java
new file mode 100644
index 0000000..c3471f9
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/EdgeSwipeInterceptorViewListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.ui;
+
+public interface EdgeSwipeInterceptorViewListener
+{
+    public void onSelectionStarted(float pointerX, float pointerY);
+
+    public void onSelectionUpdate(float pointerX, float pointerY);
+
+    public void onSelectionFinished(float pointerX, float pointerY);
+};
\ No newline at end of file
diff --git a/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView.java b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView.java
new file mode 100644
index 0000000..be64e8b
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/edgeswipe/ui/EditFavoritesGridView.java
@@ -0,0 +1,125 @@
+/*
+ * 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 org.fairphone.launcher.edgeswipe.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.GridView;
+
+public class EditFavoritesGridView extends GridView
+{
+    public interface OnEditFavouritesIconDraggedListener
+    {
+        public void OnEditFavouritesIconDragged(AdapterView<?> parent, View view, int position, long id);
+    }
+    
+    
+    private float touchStartX = 0;
+    private float touchStartY = 0;
+    private int selectedChild = INVALID_POSITION;
+    private boolean hasStartedDraggingOut = false;
+    private boolean ignoreDragging = false;
+    private OnEditFavouritesIconDraggedListener listener=null;
+    private float xBias = 2.0f;
+    private float minMoveDistance = 15;
+    
+    
+    public EditFavoritesGridView(Context context)
+    {
+        super(context);
+    }
+
+    public EditFavoritesGridView(Context context, AttributeSet attrs)
+    {
+        super(context, attrs);
+    }
+
+    public EditFavoritesGridView(Context context, AttributeSet attrs, int defStyle)
+    {
+        super(context, attrs, defStyle);
+    }
+    
+    
+    
+    
+    public void setOnEditFavouritesIconDraggedListener(OnEditFavouritesIconDraggedListener listener) 
+    {
+        this.listener = listener;
+    }
+    
+    @Override
+    public boolean onTouchEvent(MotionEvent ev)
+    {
+        switch(ev.getAction())
+        {
+            case MotionEvent.ACTION_DOWN:
+            {
+                touchStartX = ev.getX();
+                touchStartY = ev.getY();
+                selectedChild = pointToPosition((int)touchStartX, (int)touchStartY);
+                ignoreDragging = (selectedChild==INVALID_POSITION);
+                hasStartedDraggingOut = false;
+            }
+            break;
+            
+            case MotionEvent.ACTION_MOVE:
+            {
+                if(!ignoreDragging && !hasStartedDraggingOut)
+                {
+                    float xDif = ev.getX()-touchStartX;
+                    float yDif = ev.getY()-touchStartY;
+                    
+                    float absYDif = Math.abs(yDif);
+                    float absXDif = Math.abs(xDif)*xBias;
+                    
+                    
+                    if(absXDif>absYDif && xDif>minMoveDistance)//are we dragging mostly to the right?
+                    {
+                        hasStartedDraggingOut = true;
+                        MotionEvent cancelEvent = MotionEvent.obtain(ev.getDownTime(), ev.getEventTime(), MotionEvent.ACTION_CANCEL, ev.getX(), ev.getY(), ev.getMetaState());
+                        super.onTouchEvent(cancelEvent);
+                        if(listener!=null)
+                        {
+                            View childView = getChildAt(selectedChild-getFirstVisiblePosition());
+                            if(childView!=null)
+                            {
+                                listener.OnEditFavouritesIconDragged(this, childView, selectedChild, getAdapter().getItemId(selectedChild));
+                            }
+                        }
+                    }
+                    else if(absXDif<absYDif && absYDif>minMoveDistance)
+                    {
+                        ignoreDragging = true;
+                    }
+                }
+            }
+            break;
+        }
+        
+        if(!hasStartedDraggingOut)
+        {
+            return super.onTouchEvent(ev);
+        }
+        else
+        {
+            return true;
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/gappsinstaller/GappsInstallationAssets.java b/FairphoneHome/src/org/fairphone/launcher/gappsinstaller/GappsInstallationAssets.java
new file mode 100644
index 0000000..e6ffa21
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/gappsinstaller/GappsInstallationAssets.java
@@ -0,0 +1,154 @@
+/*
+ * 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 org.fairphone.launcher.gappsinstaller;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class GappsInstallationAssets {
+	public static final String MOUNT_SYSTEM_RO = "mount -o remount,ro /system";
+	public static final String MOUNT_SYSTEM_RW = "mount -o remount,rw /system";
+	public static final String SUPER_USER_COMMAND = "su";
+	
+	// install jars
+		public static String [] install_files = {
+				// app
+			"system/app/ChromeBookmarksSyncAdapter.apk",
+			"system/app/ConfigUpdater.apk",
+			"system/app/GenieWidget.apk",
+			"system/app/Gmail.apk",
+			"system/app/GmsCore.apk",
+			"system/app/GoogleBackupTransport.apk",
+			"system/app/GoogleCalendarSyncAdapter.apk",
+			"system/app/GoogleContactsSyncAdapter.apk",
+			"system/app/GoogleEars.apk",
+			"system/app/GoogleFeedback.apk",
+			"system/app/GoogleLoginService.apk",
+			"system/app/GooglePartnerSetup.apk",
+			"system/app/GooglePlus.apk",
+			"system/app/GoogleServicesFramework.apk",
+			"system/app/GoogleTTS.apk",
+			"system/app/LatinImeDictionaryPack.apk",
+			"system/app/MediaUploader.apk",
+			"system/app/NetworkLocation.apk",
+			"system/app/OneTimeInitializer.apk",
+			"system/app/Phonesky.apk",
+			"system/app/QuickSearchBox.apk",
+			"system/app/SetupWizard.apk",
+			"system/app/TalkBack.apk",
+			"system/app/VoiceSearchStub.apk",
+			"system/app/GoogleMaps.apk",
+			    // etc
+			"system/etc/g.prop",
+			"system/etc/permissions/com.google.android.maps.xml",
+			"system/etc/permissions/com.google.android.media.effects.xml",
+			"system/etc/permissions/com.google.widevine.software.drm.xml",
+			"system/etc/permissions/features.xml",
+//			"system/etc/preferred-apps/google.xml",
+				// framework
+			"system/framework/com.google.android.maps.jar",
+			"system/framework/com.google.android.media.effects.jar",
+			"system/framework/com.google.widevine.software.drm.jar",
+				// libs
+			"system/lib/libAppDataSearch.so",
+			"system/lib/libfilterpack_facedetect.so",
+			"system/lib/libfrsdk.so",
+			"system/lib/libgames_rtmp_jni.so",
+			"system/lib/libgcomm_jni.so",
+			"system/lib/libgoogle_recognizer_jni_l.so",
+			"system/lib/libgoogle_recognizer_jni.so",
+			"system/lib/libgtalk_jni.so",
+			"system/lib/libgtalk_stabilize.so",
+			"system/lib/libjni_latinime.so",
+			"system/lib/libpatts_engine_jni_api.so",
+			"system/lib/libplus_jni_v8.so",
+			"system/lib/librs.antblur_constant.so",
+			"system/lib/librs.antblur_drama.so",
+			"system/lib/librs.antblur.so",
+			"system/lib/librs.drama.so",
+			"system/lib/librs.film_base.so",
+			"system/lib/librs.fixedframe.so",
+			"system/lib/librs.grey.so",
+			"system/lib/librs.image_wrapper.so",
+			"system/lib/librs.retrolux.so",
+			"system/lib/librsjni.so",
+			"system/lib/libRSSupport.so",
+			"system/lib/libspeexwrapper.so",
+			"system/lib/libvcdecoder_jni.so",
+			"system/lib/libvorbisencoder.so",
+			"system/lib/libwebp_android.so",
+				// tts
+			"system/tts/lang_pico/de-DE_gl0_sg.bin",
+			"system/tts/lang_pico/de-DE_ta.bin",
+			"system/tts/lang_pico/es-ES_ta.bin",
+			"system/tts/lang_pico/es-ES_zl0_sg.bin",
+			"system/tts/lang_pico/fr-FR_nk0_sg.bin",
+			"system/tts/lang_pico/fr-FR_ta.bin",
+			"system/tts/lang_pico/it-IT_cm0_sg.bin",
+			"system/tts/lang_pico/it-IT_ta.bin",
+				// usr
+			"system/usr/srec/en-US/acoustic_model",
+			"system/usr/srec/en-US/c_fst",
+			"system/usr/srec/en-US/clg",
+			"system/usr/srec/en-US/compile_grammar.config",
+			"system/usr/srec/en-US/contacts.abnf",
+			"system/usr/srec/en-US/dict",
+			"system/usr/srec/en-US/dictation.config",
+			"system/usr/srec/en-US/embed_phone_nn_model",
+			"system/usr/srec/en-US/embed_phone_nn_state_sym",
+			"system/usr/srec/en-US/endpointer_dictation.config",
+			"system/usr/srec/en-US/endpointer_voicesearch.config",
+			"system/usr/srec/en-US/ep_acoustic_model",
+			"system/usr/srec/en-US/g2p_fst",
+			"system/usr/srec/en-US/google_hotword_clg",
+			"system/usr/srec/en-US/google_hotword_logistic",
+			"system/usr/srec/en-US/google_hotword.config",
+			"system/usr/srec/en-US/grammar.config",
+			"system/usr/srec/en-US/hmmsyms",
+			"system/usr/srec/en-US/hotword_symbols",
+			"system/usr/srec/en-US/lintrans_model",
+			"system/usr/srec/en-US/metadata",
+			"system/usr/srec/en-US/norm_fst",
+			"system/usr/srec/en-US/normalizer",
+			"system/usr/srec/en-US/offensive_word_normalizer",
+			"system/usr/srec/en-US/phonelist",
+			"system/usr/srec/en-US/rescoring_lm",
+			"system/usr/srec/en-US/symbols"
+		};		
+		
+		public static void executeSingleCommand(DataOutputStream os, InputStream is,
+				String tmpCmd, boolean cmdRequiresAnOutput) throws IOException {
+			os.writeBytes(tmpCmd+"\n");
+			int readed = 0;
+			byte[] buff = new byte[4096];
+
+			// if cmd requires an output
+			// due to the blocking behaviour of read(...)
+			if (cmdRequiresAnOutput) {
+			    while( is.available() <= 0) {
+			        try { Thread.sleep(200); } catch(Exception ex) {}
+			    }
+
+			    while( is.available() > 0) {
+			        readed = is.read(buff);
+			        if ( readed <= 0 ) 
+			        	break;
+			    }
+			}
+		}
+		
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper.java b/FairphoneHome/src/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper.java
new file mode 100644
index 0000000..e2f5dbc
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/gappsinstaller/GappsInstallerHelper.java
@@ -0,0 +1,967 @@
+/*
+ * 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 org.fairphone.launcher.gappsinstaller;
+
+import com.stericson.RootTools.RootTools;
+import com.stericson.RootTools.exceptions.RootDeniedException;
+import com.stericson.RootTools.execution.CommandCapture;
+import com.stericson.RootTools.execution.Shell;
+
+import org.fairphone.launcher.R;
+import org.fairphone.launcher.rsa.utils.RSAUtils;
+import org.fairphone.widgets.gapps.GoogleAppsInstallerWidget;
+
+import android.app.AlertDialog;
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.appwidget.AppWidgetManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+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.Environment;
+import android.os.PowerManager;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
+import java.util.concurrent.TimeoutException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class GappsInstallerHelper {
+
+	private static final String GOOGLE_APPS_DOWNLOAD_ID = "org.fairphone.launcher.gapps.DOWNLOAD_ID";
+
+	public static final String GAPPS_ACTION_DISCLAIMER = "org.fairphone.launcher.gapps.DISCLAIMER";
+	public static final String GAPPS_ACTION_DOWNLOAD_CONFIGURATION_FILE = "org.fairphone.launcher.gapps.START_DONWLOAD_CONFIGURATION";
+	public static final String GOOGLE_APPS_INSTALL_DOWNLOAD_CANCEL = "org.fairphone.launcher.gapps.START_DOWNLOAD_CANCEL";
+	public static final String GOOGLE_APPS_INSTALL_REBOOT = "org.fairphone.launcher.gapps.REBOOT";
+
+	public static final String PREFS_GOOGLE_APPS_INSTALLER_DATA = "FAIRPHONE_GOOGLE_APPS_INSTALLER_DATA";
+	public static final String GOOGLE_APPS_INSTALLER_STATE = "org.fairphone.launcher.gapps.WIDGET_STATE";
+	public static final String GOOGLE_APPS_INSTALLER_PROGRESS = "org.fairphone.launcher.gapps.WIDGET_SEEKBAR_PROGRESS";
+	public static final String GOOGLE_APPS_INSTALLER_PROGRESS_MAX = "org.fairphone.launcher.gapps.WIDGET_SEEKBAR_PROGRESS_MAX";
+	public static final String GAPPS_ACTION_GO_PERMISSIONS = "org.fairphone.launcher.gaps.GAPPS_ACTION_GO_PERMISSIONS";
+
+	public static final int GAPPS_STATES_INITIAL = 0;
+	public static final int GAPPS_STATES_DOWNLOAD_CONFIGURATION_FILE = 1;
+	public static final int GAPPS_STATES_DOWNLOAD_GOOGLE_APPS_FILE = 2;
+	public static final int GAPPS_STATES_EXTRACT_FILES = 3;
+	public static final int GAPPS_STATES_PERMISSION_CHECK = 4;
+	public static final int GAPPS_STATE_INSTALLATION = 5;
+
+	public static final int GAPPS_REBOOT_STATE = 6;
+	public static final int GAPPS_INSTALLED_STATE = 7;
+	public static final int GAPPS_INSTALLATION_FAILED_STATE = 8;
+	public static final int GAPPS_DOWNLOAD_FAILED_STATE = 9;
+	protected static final String TAG = GappsInstallerHelper.class
+			.getSimpleName();
+
+	private static String DOWNLOAD_PATH = Environment
+			.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
+			.getAbsolutePath();
+
+	private static String RECOVERY_PATH = "sdcard/Download/";
+
+	private static String ZIP_CONTENT_PATH = "/googleapps/";
+
+	private DownloadManager mDownloadManager;
+	private Context mContext;
+	private SharedPreferences mSharedPrefs;
+
+	private DownloadBroadCastReceiver mDownloadBroacastReceiver;
+	private long mConfigFileDownloadId;
+	private long mGappsFileDownloadId;
+	private String mMD5hash;
+
+	public GappsInstallerHelper(Context context) {
+		mContext = context;
+
+		mSharedPrefs = mContext.getSharedPreferences(
+				PREFS_GOOGLE_APPS_INSTALLER_DATA, Context.MODE_PRIVATE);
+
+		resume();
+
+		int currentState = getInstallerState();
+
+		if (currentState == GAPPS_REBOOT_STATE) {
+			updateWidgetState(GAPPS_STATES_PERMISSION_CHECK);
+		}
+
+		if (currentState != GAPPS_STATE_INSTALLATION &&
+			currentState != GAPPS_INSTALLED_STATE) {
+
+			// clean files that must be rechecked
+			forceCleanUnzipDirectory();
+			forceCleanConfigurationFile();
+
+			updateInstallerState(GAPPS_STATES_INITIAL);
+		}
+		
+		checkGappsAreInstalled();
+	}
+
+	private void checkGappsAreInstalled() {
+
+		File f = new File("/system/app/OneTimeInitializer.apk");
+
+		if (f.exists()) {
+			updateWidgetState(GAPPS_INSTALLED_STATE);
+		}
+	}
+
+	public void resume() {
+		// setup the download manager
+		setupDownloadManager();
+
+		// setup the states broadcasts receivers
+		setupTheStatesBroadCasts();
+	}
+
+	public void pause() {
+		// clear the download manager
+		clearDownloadManager();
+
+		// clean the broadcast receivers
+		clearBroadcastReceivers();
+	}
+
+	private int getCurrentState() {
+		return mSharedPrefs.getInt(GOOGLE_APPS_INSTALLER_STATE,
+				GAPPS_STATES_INITIAL);
+	}
+
+	private void setupDownloadManager() {
+		mDownloadManager = (DownloadManager) mContext
+				.getSystemService(Context.DOWNLOAD_SERVICE);
+
+		mDownloadBroacastReceiver = new DownloadBroadCastReceiver();
+
+		mContext.registerReceiver(mDownloadBroacastReceiver, new IntentFilter(
+				DownloadManager.ACTION_DOWNLOAD_COMPLETE));
+	}
+
+	private void clearDownloadManager() {
+		mContext.unregisterReceiver(mDownloadBroacastReceiver);
+
+		mDownloadBroacastReceiver = null;
+	}
+
+	private boolean isWiFiEnabled() {
+
+		ConnectivityManager manager = (ConnectivityManager) mContext
+				.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+		boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
+				.isConnectedOrConnecting();
+
+		return isWifi;
+	}
+
+	private boolean hasAlreadyDownloadedZipFile(String mMD5hash, String filename) {
+
+		File file = new File(DOWNLOAD_PATH + "/" + filename);
+		return GappsInstallerHelper.checkMD5(mMD5hash, file);
+	}
+
+	private String[] getGappsUrlFromConfigFile(String filePath) {
+
+		String[] result = new String[2];
+
+		File configFile = new File(filePath);
+
+		try {
+			BufferedReader br = new BufferedReader(new FileReader(configFile));
+
+			result[0] = br.readLine();
+			result[1] = br.readLine();
+
+			br.close();
+		} catch (FileNotFoundException e) {
+			Log.e(TAG, "Configuration file not find", e);
+			result = null;
+		} catch (IOException e) {
+			Log.e(TAG, "Configuration file could not be read", e);
+			result = null;
+		}
+
+		return result;
+	}
+
+	private void deleteFile(String file, String location) {
+		File f = new File(location + file);
+
+		if (f.exists()) {
+			deleteRecursive(f);
+		}
+	}
+
+	private void deleteRecursive(File fileOrDirectory) {
+		if (fileOrDirectory.isDirectory()) {
+			for (File child : fileOrDirectory.listFiles()) {
+				deleteRecursive(child);
+			}
+		}
+
+		fileOrDirectory.delete();
+	}
+
+	private void forceCleanConfigurationFile() {
+
+		if (mConfigFileDownloadId != 0) {
+			mDownloadManager.remove(mConfigFileDownloadId);
+		}
+
+		String configFileName = mContext.getResources().getString(
+				R.string.gapps_installer_config_file);
+		String configFileZip = mContext.getResources().getString(
+                R.string.gapps_installer_zip);
+		String configFileCfg = mContext.getResources().getString(
+                R.string.gapps_installer_cfg);
+		String configFileSig = mContext.getResources().getString(
+                R.string.gapps_installer_sig);
+
+		deleteFile("/" + configFileName + configFileZip, DOWNLOAD_PATH);
+		deleteFile("/" + configFileName + configFileCfg, DOWNLOAD_PATH);
+		deleteFile("/" + configFileName + configFileSig, DOWNLOAD_PATH);
+	}
+
+	private void forceCleanGappsZipFile() {
+
+		long downloadID = mSharedPrefs.getLong(GOOGLE_APPS_DOWNLOAD_ID, 0);
+
+		if (downloadID != 0) {
+			mDownloadManager.remove(downloadID);
+		}
+
+		String gappsFileName = mContext.getResources().getString(
+				R.string.gapps_installer_filename);
+
+		deleteFile("/" + gappsFileName, DOWNLOAD_PATH);
+	}
+
+	private void forceCleanUnzipDirectory() {
+		deleteFile(ZIP_CONTENT_PATH, DOWNLOAD_PATH);
+	}
+
+	private BroadcastReceiver mBCastDisclaimer;
+	private BroadcastReceiver mBCastDownloadConfiguration;
+	private BroadcastReceiver mBCastInstallDownloadCancel;
+	private BroadcastReceiver mBCastGoPermissions;
+	private BroadcastReceiver mBCastGappsInstallReboot;
+
+	private void setupTheStatesBroadCasts() {
+		// launching the application
+
+		mBCastDisclaimer = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+				Resources resources = mContext.getResources();
+
+				AlertDialog disclaimerDialog = new AlertDialog.Builder(mContext)
+						.create();
+
+				disclaimerDialog.setTitle(resources
+						.getText(R.string.google_apps_disclaimer_title));
+
+				// Setting Dialog Message
+				disclaimerDialog.setMessage(resources
+						.getText(R.string.google_apps_disclaimer_description));
+
+				disclaimerDialog
+						.setButton(
+								AlertDialog.BUTTON_POSITIVE,
+								resources
+										.getString(R.string.google_apps_disclaimer_agree),
+								new DialogInterface.OnClickListener() {
+
+									@Override
+									public void onClick(DialogInterface dialog,
+											int which) {
+
+										Intent startDownloadOkIntent = new Intent();
+										startDownloadOkIntent
+												.setAction(GappsInstallerHelper.GAPPS_ACTION_DOWNLOAD_CONFIGURATION_FILE);
+
+										mContext.sendBroadcast(startDownloadOkIntent);
+									}
+								});
+
+				disclaimerDialog.setButton(AlertDialog.BUTTON_NEGATIVE,
+						resources.getString(android.R.string.cancel),
+						new DialogInterface.OnClickListener() {
+
+							@Override
+							public void onClick(DialogInterface dialog,
+									int which) {
+								updateWidgetState(GAPPS_STATES_INITIAL);
+							}
+						});
+
+				disclaimerDialog.show();
+
+			}
+		};
+
+		mContext.registerReceiver(mBCastDisclaimer, new IntentFilter(
+				GAPPS_ACTION_DISCLAIMER));
+
+		mBCastDownloadConfiguration = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+				// clean the configuration files
+				forceCleanConfigurationFile();
+
+				if (isWiFiEnabled()) {
+					String url = mContext.getResources().getString(
+							R.string.gapps_installer_download_url);
+
+					String configFileName = mContext.getResources().getString(
+							R.string.gapps_installer_config_file);
+					String configFileZip = mContext.getResources().getString(
+			                R.string.gapps_installer_zip);
+
+					Request request = createDownloadRequest(url, configFileName + configFileZip);
+					mConfigFileDownloadId = mDownloadManager.enqueue(request);
+
+					updateWidgetState(GAPPS_STATES_DOWNLOAD_CONFIGURATION_FILE);
+				} else {
+
+					AlertDialog disclaimerDialog = new AlertDialog.Builder(
+							mContext).create();
+
+					Resources resources = mContext.getResources();
+
+					disclaimerDialog.setTitle(resources
+							.getText(R.string.google_apps_connection_title));
+
+					// Setting Dialog Message
+					disclaimerDialog
+							.setMessage(resources
+									.getText(R.string.google_apps_connection_description));
+
+					disclaimerDialog.setButton(AlertDialog.BUTTON_POSITIVE,
+							resources.getString(android.R.string.ok),
+							new DialogInterface.OnClickListener() {
+
+								@Override
+								public void onClick(DialogInterface dialog,
+										int which) {
+									updateWidgetState(GAPPS_STATES_INITIAL);
+								}
+							});
+
+					disclaimerDialog.show();
+
+				}
+			}
+		};
+
+		mContext.registerReceiver(mBCastDownloadConfiguration,
+				new IntentFilter(GAPPS_ACTION_DOWNLOAD_CONFIGURATION_FILE));
+
+		mBCastInstallDownloadCancel = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+				updateWidgetState(GAPPS_STATES_INITIAL);
+			}
+
+		};
+
+		mContext.registerReceiver(mBCastInstallDownloadCancel,
+				new IntentFilter(GOOGLE_APPS_INSTALL_DOWNLOAD_CANCEL));
+
+		mBCastGoPermissions = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+
+				String filename = mContext.getResources().getString(
+						R.string.gapps_installer_filename);
+
+				pushFileToRecovery(filename);
+			}
+		};
+
+		mContext.registerReceiver(mBCastGoPermissions, new IntentFilter(
+				GAPPS_ACTION_GO_PERMISSIONS));
+
+		mBCastGappsInstallReboot = new BroadcastReceiver() {
+
+			@Override
+			public void onReceive(Context context, Intent intent) {
+				
+//				String filename = mContext.getResources().getString(
+//						R.string.gapps_installer_filename);
+//
+//				pushFileToRecovery(filename);
+				
+				// alter State
+				updateWidgetState(GAPPS_INSTALLED_STATE);
+				
+				// reboot
+				rebootToRecovery();
+			}
+		};
+
+		mContext.registerReceiver(mBCastGappsInstallReboot, new IntentFilter(
+				GOOGLE_APPS_INSTALL_REBOOT));
+
+	}
+
+	public void pushFileToRecovery(String fileName) {
+		if (RootTools.isAccessGiven()) {
+			// 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=/" + RECOVERY_PATH
+						+ fileName + "' >> /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();
+			}
+		}
+
+		updateWidgetState(GAPPS_REBOOT_STATE);
+	}
+
+	public void rebootToRecovery() {
+		if (RootTools.isAccessGiven()) {
+			updateWidgetState(GAPPS_INSTALLED_STATE);
+
+			// reboot
+			try {
+				((PowerManager) mContext
+						.getSystemService(Context.POWER_SERVICE))
+						.reboot("recovery");
+			} catch (Throwable t) {
+				Log.e(TAG, "Could not access files", t);
+			}
+		} else {
+			Resources resources = mContext.getResources();
+
+			AlertDialog permissionsDialog = new AlertDialog.Builder(mContext)
+					.create();
+
+			permissionsDialog.setTitle(resources
+					.getText(R.string.google_apps_denied_permissions_title));
+
+			// Setting Dialog Message
+			permissionsDialog
+					.setMessage(resources
+							.getText(R.string.google_apps_denied_permissions_description));
+
+			permissionsDialog.setButton(AlertDialog.BUTTON_POSITIVE,
+					resources.getString(android.R.string.ok),
+					new DialogInterface.OnClickListener() {
+
+						@Override
+						public void onClick(DialogInterface dialog, int which) {
+
+							forceCleanConfigurationFile();
+							// forceCleanUnzipDirectory();
+
+							updateWidgetState(GAPPS_STATES_INITIAL);
+
+						}
+					});
+
+			permissionsDialog.show();
+		}
+	}
+
+	private void clearBroadcastReceivers() {
+		mContext.unregisterReceiver(mBCastDisclaimer);
+		mContext.unregisterReceiver(mBCastDownloadConfiguration);
+		mContext.unregisterReceiver(mBCastGoPermissions);
+		mContext.unregisterReceiver(mBCastGappsInstallReboot);
+		mContext.unregisterReceiver(mBCastInstallDownloadCancel);
+	}
+
+	private void updateGoogleAppsIntallerWidgets() {
+		AppWidgetManager appWidgetManager = AppWidgetManager
+				.getInstance(mContext);
+		int[] appWidgetIds = appWidgetManager
+				.getAppWidgetIds(new ComponentName(mContext,
+						GoogleAppsInstallerWidget.class));
+		if (appWidgetIds.length > 0) {
+			new GoogleAppsInstallerWidget().onUpdate(mContext,
+					appWidgetManager, appWidgetIds);
+		}
+	}
+
+	private Request createDownloadRequest(String url, String fileName) {
+
+		Request request = new Request(Uri.parse(url));
+		Environment.getExternalStoragePublicDirectory(
+				Environment.DIRECTORY_DOWNLOADS).mkdirs();
+
+		request.setDestinationInExternalPublicDir(
+				Environment.DIRECTORY_DOWNLOADS, fileName);
+		request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
+		request.setAllowedOverRoaming(false);
+
+		String download = mContext.getResources().getString(
+				R.string.google_apps_download_title);
+		request.setTitle(download);
+
+		return request;
+	}
+
+	private void startDownloadProgressUpdateThread(final long download_id) {
+		new Thread(new Runnable() {
+
+			@Override
+			public void run() {
+
+				boolean downloading = true;
+
+				while (downloading) {
+
+					DownloadManager.Query q = new DownloadManager.Query();
+					q.setFilterById(download_id);
+
+					Cursor cursor = mDownloadManager.query(q);
+					if (cursor != null) {
+						cursor.moveToFirst();
+						int bytes_downloaded = cursor.getInt(cursor
+								.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
+						int bytes_total = cursor.getInt(cursor
+								.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
+
+						if (cursor.getInt(cursor
+								.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
+							downloading = false;
+
+							bytes_downloaded = 0;
+							bytes_total = 0;
+						}
+
+						SharedPreferences.Editor prefEdit = mSharedPrefs.edit();
+						prefEdit.putInt(
+								GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS,
+								bytes_downloaded);
+						prefEdit.putInt(
+								GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS_MAX,
+								bytes_total);
+						prefEdit.commit();
+
+						updateGoogleAppsIntallerWidgets();
+
+						cursor.close();
+						try {
+							Thread.sleep(1000);
+						} catch (InterruptedException e) {
+							e.printStackTrace();
+						}
+					}
+				}
+			}
+		}).start();
+	}
+
+	boolean unzipped = false;
+
+	private void installAppsToLocations() {
+
+		Thread thread = new Thread(new Runnable() {
+
+			@Override
+			public void run() {
+				try {
+					updateInstallerState(GAPPS_STATE_INSTALLATION);
+
+					runCommandsAsRoot(GappsInstallationAssets.install_files);
+
+				} catch (Throwable t) {
+					Log.e(TAG, "Error while installing the files", t);
+				}
+			}
+		});
+
+		thread.start();
+	}
+
+	private void runCommandsAsRoot(String[] files) throws IOException,
+			TimeoutException, RootDeniedException {
+
+		String downloadPath = DOWNLOAD_PATH + ZIP_CONTENT_PATH;
+
+		int maxFiles = files.length;
+		int currentCount = 0;
+
+		Shell.runRootCommand(new CommandCapture(0,
+				GappsInstallationAssets.MOUNT_SYSTEM_RW));
+
+		for (String filePath : files) {
+			Log.d(this.getClass().getSimpleName(), "[INST]installing file :"
+					+ downloadPath + filePath + " to " + filePath);
+
+			Shell.runRootCommand(new CommandCapture(0, "cat " + downloadPath
+					+ filePath + " > /" + filePath));
+			currentCount++;
+
+			// update progress bar
+			Editor editor = mSharedPrefs.edit();
+
+			editor.putInt(GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS,
+					currentCount);
+			editor.putInt(
+					GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS_MAX,
+					maxFiles);
+
+			editor.commit();
+
+			updateGoogleAppsIntallerWidgets();
+		}
+
+		// update the status of the files
+
+		for (String filePath : files) {
+			Log.d(this.getClass().getSimpleName(),
+					"[CHMOD]changing permissions for file :" + filePath);
+
+			Shell.runRootCommand(new CommandCapture(0, "chmod 644 /" + filePath));
+		}
+
+		Shell.runRootCommand(new CommandCapture(0,
+				GappsInstallationAssets.MOUNT_SYSTEM_RO));
+	}
+
+	private void updateInstallerState(int state) {
+		// alter State
+		SharedPreferences.Editor prefEdit = mSharedPrefs.edit();
+		prefEdit.putInt(GOOGLE_APPS_INSTALLER_STATE, state);
+		prefEdit.commit();
+	}
+
+	private int getInstallerState() {
+		return mSharedPrefs.getInt(GOOGLE_APPS_INSTALLER_STATE,
+				GAPPS_STATES_INITIAL);
+	}
+
+	private void updateWidgetState(int state) {
+		updateInstallerState(state);
+
+		updateGoogleAppsIntallerWidgets();
+	}
+
+	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;
+		}
+
+		Log.i(TAG, "Calculated digest: " + calculatedDigest);
+		Log.i(TAG, "Provided digest: " + md5);
+
+		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);
+			}
+		}
+	}
+
+	private class DownloadBroadCastReceiver extends BroadcastReceiver {
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			DownloadManager.Query query = new DownloadManager.Query();
+
+			long downloadID = 0;
+
+			switch (getCurrentState()) {
+			case GAPPS_STATES_DOWNLOAD_CONFIGURATION_FILE:
+				downloadID = mConfigFileDownloadId;
+				break;
+			default:
+				downloadID = mSharedPrefs.getLong(GOOGLE_APPS_DOWNLOAD_ID, 0);
+			}
+
+			Cursor cursor = mDownloadManager.query(query);
+			query.setFilterById(downloadID);
+
+			if (cursor.moveToFirst()) {
+				int columnIndex = cursor
+						.getColumnIndex(DownloadManager.COLUMN_STATUS);
+				int status = cursor.getInt(columnIndex);
+				int columnReason = cursor
+						.getColumnIndex(DownloadManager.COLUMN_REASON);
+				int reason = cursor.getInt(columnReason);
+
+				if (status == DownloadManager.STATUS_SUCCESSFUL) {
+					// file to where the download happened
+					String filePath = mDownloadManager.getUriForDownloadedFile(
+							downloadID).getPath();
+
+					// Retrieve the saved download id
+					if (downloadID == mConfigFileDownloadId) {
+					    
+					    String targetPath = DOWNLOAD_PATH + ZIP_CONTENT_PATH;
+					    String cfgFilename = mContext.getResources().getString(R.string.gapps_installer_config_file);
+                        String fileCfgExt = mContext.getResources().getString(R.string.gapps_installer_cfg);
+					    
+                        String cfgFile = targetPath + cfgFilename + fileCfgExt;
+					    
+                        if(!checkFileSignature(filePath, targetPath)){
+                            Toast.makeText(mContext,
+                                    R.string.google_apps_download_error,
+                                    Toast.LENGTH_LONG).show();
+
+                            updateWidgetState(GAPPS_STATES_INITIAL);
+                            return;
+                        }
+
+						// read the gapps url
+						String[] downloadData = getGappsUrlFromConfigFile(cfgFile);
+
+						if (downloadData == null) {
+							Toast.makeText(mContext,
+									R.string.google_apps_download_error,
+									Toast.LENGTH_LONG).show();
+
+							updateWidgetState(GAPPS_STATES_INITIAL);
+
+							return;
+						}
+                        
+
+						// read the md5
+						mMD5hash = downloadData[1];
+
+						String filename = mContext.getResources().getString(
+								R.string.gapps_installer_filename);
+
+						if (hasAlreadyDownloadedZipFile(mMD5hash, filename)) {
+							updateWidgetState(GAPPS_STATES_PERMISSION_CHECK);
+//							updateWidgetState(GAPPS_REBOOT_STATE);
+						} else {
+							Log.d(TAG, "GAPPS> file does not match");
+
+							forceCleanGappsZipFile();
+
+							// enqueue of gapps request
+							Request request = createDownloadRequest(
+									downloadData[0], filename);
+
+							mGappsFileDownloadId = mDownloadManager
+									.enqueue(request);
+
+							SharedPreferences.Editor prefEdit = mSharedPrefs
+									.edit();
+							// Save the download id
+							prefEdit.putLong(GOOGLE_APPS_DOWNLOAD_ID,
+									mGappsFileDownloadId);
+
+							startDownloadProgressUpdateThread(mGappsFileDownloadId);
+
+							prefEdit.putInt(
+									GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS,
+									0);
+							prefEdit.putInt(
+									GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS_MAX,
+									0);
+
+							prefEdit.commit();
+
+							// alter Widget State
+							updateGoogleAppsIntallerWidgets();
+							updateWidgetState(GAPPS_STATES_DOWNLOAD_GOOGLE_APPS_FILE);
+						}
+					} else {
+						updateWidgetState(GAPPS_STATES_PERMISSION_CHECK);
+//						updateWidgetState(GAPPS_REBOOT_STATE);
+					}
+				} else if (status == DownloadManager.STATUS_FAILED) {
+					Toast.makeText(mContext,
+							"FAILED!\n" + "reason of " + reason,
+							Toast.LENGTH_LONG).show();
+
+					forceCleanConfigurationFile();
+
+					forceCleanUnzipDirectory();
+
+					updateWidgetState(GAPPS_STATES_INITIAL);
+
+				} else if (status == DownloadManager.STATUS_PAUSED) {
+					Toast.makeText(mContext,
+							"PAUSED!\n" + "reason of " + reason,
+							Toast.LENGTH_LONG).show();
+				} else if (status == DownloadManager.STATUS_PENDING) {
+					Toast.makeText(mContext, "PENDING!", Toast.LENGTH_LONG)
+							.show();
+				} else if (status == DownloadManager.STATUS_RUNNING) {
+					Toast.makeText(mContext, "RUNNING!", Toast.LENGTH_LONG)
+							.show();
+				}
+			}
+		}
+	}
+	
+    private boolean  checkFileSignature(String filePath, String targetPath){
+        boolean valid = false;
+
+        unzip(filePath, targetPath);
+        
+        try {
+            String cfgFilename = mContext.getResources().getString(R.string.gapps_installer_config_file);
+            String fileCfgExt = mContext.getResources().getString(R.string.gapps_installer_cfg);
+            String fileSigExt = mContext.getResources().getString(R.string.gapps_installer_sig);
+            
+            PublicKey pubKey = RSAUtils.readPublicKeyFromPemFormat(mContext, R.raw.public_key);
+            byte[] sign = RSAUtils.readSignature(targetPath + cfgFilename + fileSigExt);
+            valid =  RSAUtils.verifySignature(targetPath + cfgFilename + fileCfgExt, 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;
+    }
+    
+    public 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 void _dirChecker(String dir, String location) {
+        File f = new File(location + dir);
+
+        if (!f.isDirectory()) {
+            f.mkdirs();
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/launcher/rsa/utils/RSAUtils.java b/FairphoneHome/src/org/fairphone/launcher/rsa/utils/RSAUtils.java
new file mode 100644
index 0000000..f15b0e2
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/rsa/utils/RSAUtils.java
@@ -0,0 +1,111 @@
+package org.fairphone.launcher.rsa.utils;

+

+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.FileInputStream;

+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;

+

+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;

+    }

+

+}

diff --git a/FairphoneHome/src/org/fairphone/launcher/util/KWMathUtils.java b/FairphoneHome/src/org/fairphone/launcher/util/KWMathUtils.java
new file mode 100644
index 0000000..5448d9e
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/launcher/util/KWMathUtils.java
@@ -0,0 +1,117 @@
+/*
+ * 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 org.fairphone.launcher.util;
+
+public class KWMathUtils
+{
+    public static double degToRad(double angleDeg)
+    {
+        return angleDeg/180*Math.PI;
+    }
+    
+    public static double radToDeg(double angleRad)
+    {
+        return angleRad/Math.PI*180;
+    }
+
+    public static float speedUp(float ratio)
+    {
+        return ratio * ratio;
+    }
+
+    public static float slowDown(float ratio)
+    {
+        return 1.0f - ((ratio - 1.0f) * (ratio - 1.0f));
+    }
+
+    public static float smoothStep(float ratio)
+    {
+        return ratio * ratio * (3 - 2 * ratio);
+    }
+
+    public static float blend(float start, float end, float ratio)
+    {
+        return start + (end - start) * ratio;
+    }
+    
+    public static float clamp(float start,float end, float value)
+    {
+        if(value<start)
+            return start;
+        if(value>end)
+            return end;
+        return value;
+    }
+    
+    public static float getLongRatio(long startTime, long endTime, long time)
+    {
+        long duration = endTime - startTime;
+        if (duration > 0)
+        {
+            float ratio = (float) (time-startTime) / (float) duration;
+            if(ratio<=0)
+                return 0;
+            if(ratio>=1.0f)
+                return 1.0f;
+            return ratio;
+        }
+        return 1.0f;
+    }
+    
+    public static float getFloatRatio(float min, float max, float value)
+    {
+        float dif = max - min;
+        if (dif > 0)
+        {
+            float ratio = (float) (value-min) / (float) dif;
+            if(ratio<=0)
+                return 0;
+            if(ratio>=1.0f)
+                return 1.0f;
+            return ratio;
+        }
+        return 1.0f;
+    }
+
+    public static float getSpeedFromPositionAndTimeI(float start, float end, long duration)
+    {
+        return (end-start)/((float)duration/1000.0f);
+    }
+    
+    public static float getSpeedFromPositionAndTimeF(float start, float end, float duration)
+    {
+        return (end-start)/duration;
+    }
+    
+    public static double getDistance(float x1, float y1, float x2, float y2)
+    {
+        float xd=x1-x2;
+        float yd=y1-y2;
+        
+        return Math.sqrt(xd*xd+yd*yd);
+    }
+    
+    public static long calcTimeFromVelocityAndLength(float velocity, float length)
+    {
+        return (long) (Math.abs(2 * length / velocity) * 1000);
+    }
+
+    public static float calcLengthFromTimeAndVelocity(long time, float velocity)
+    {
+        float timef = (float) time / 1000.0f;
+        return (timef * velocity / 2.0f);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/OOBEActivity.java b/FairphoneHome/src/org/fairphone/oobe/OOBEActivity.java
new file mode 100644
index 0000000..c75bde6
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/OOBEActivity.java
@@ -0,0 +1,658 @@
+/*
+ * 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 org.fairphone.oobe;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.animation.AddFavTutorialAnimationHelper;
+import org.fairphone.oobe.animation.EdgeSwipeTutorialAnimationHelper;
+import org.fairphone.oobe.animation.MoveFavTutorialAnimationHelper;
+import org.fairphone.oobe.animation.OpenAppTutorialAnimationHelper;
+import org.fairphone.oobe.animation.RemoveFavTutorialAnimationHelper;
+import org.fairphone.oobe.animation.TutorialAnimationHelper;
+import org.fairphone.oobe.animation.TutorialAnimationHelper.TutorialAnimationHelperListener;
+import org.fairphone.oobe.animation.TutorialAnimationHelper.TutorialState;
+import org.fairphone.oobe.utils.KWFontsManager;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.RelativeLayout;
+import android.widget.VideoView;
+
+public class OOBEActivity extends Activity implements TutorialAnimationHelperListener
+{
+
+    public static enum OOBESteps
+    {
+        SELECT_LANGUAGE, SETUP_WIFI, DEVICE_INTRO, EDGE_SWIPE_APPEAR, EDGE_SWIPE_SELECTION, EDIT_INTRO, EDIT_DRAG_NEW_FAVORITE, EDIT_DRAG_REMOVE_FAVORITE, EDIT_DRAG_TRADE_FAVORITE
+    };
+
+    public static final String OOBE_TUTORIAL = "OOBE_Tutorial";
+    public static final int OOBE_FULL_TUTORIAL = 0;
+    public static final int OOBE_DEVICE_TUTORIAL = 1;
+    public static final int OOBE_EDIT_FAVORITES_TUTORIAL = 2;
+    public static final int OOBE_APP_SWITCHER_TUTORIAL = 3;
+	private static final int RESULT_WIFI_SETUP = 500;
+	private static final int RESULT_LANGUAGE_SETUP = 501;
+
+    private int mCurrentStep;
+    private ArrayList<OOBESteps> mAnimationSteps;
+
+    private View mOOBETextGroup1;
+    private View mOOBETextGroup2;
+    private View mOOBETextGroup3;
+    private View mOOBETextGroup4;
+    private View mOOBETextGroup5;
+    private View mOOBETextGroup6;
+    private View mOOBETextGroup7;
+    private View mOOBETextGroup8;
+    private View mOOBETextGroup9;
+
+    private ImageButton mSelectLanguageButton;
+    private ImageButton mSetupWifiButton;
+
+    private Button mStartButton;
+    private Button mSkipButton;
+    private Button mNextButton;
+    private Button mBackButton;
+    private int mTutorialToShow;
+
+    private TutorialAnimationHelper mCurAnimHelper;
+    private TutorialAnimationHelper mNextAnimHelper;
+
+    private ViewGroup mAnimationHolder;
+
+    private VideoView mVideo;
+    private Button mSkipVideoButton;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fp_oobe_activity);
+
+        Bundle extra = getIntent() != null ? getIntent().getExtras() : null;
+        if (extra != null)
+        {
+            mTutorialToShow = extra.getInt(OOBE_TUTORIAL);
+        }
+        else
+        {
+            mTutorialToShow = OOBE_FULL_TUTORIAL;
+        }
+
+        mAnimationSteps = new ArrayList<OOBEActivity.OOBESteps>();
+
+        mCurrentStep = 0;
+
+        mCurAnimHelper = null;
+        mNextAnimHelper = null;
+
+        setupLayout();
+
+        setupListeners();
+
+        setupAnimationStart();
+
+        setupFonts();
+    }
+
+    private void setupFonts()
+    {
+        ViewGroup root = (ViewGroup) ((ViewGroup) getWindow().getDecorView()).getChildAt(0);
+        KWFontsManager.prepareFonts(this, root);
+
+    }
+
+    @Override
+    public void onBackPressed()
+    {
+
+    }
+
+    private void setupLayout()
+    {
+
+        mAnimationHolder = (ViewGroup) findViewById(R.id.tutorialAnimationViewContainer);
+
+        mStartButton = (Button) findViewById(R.id.startButton);
+        mSkipButton = (Button) findViewById(R.id.skipButton);
+        mNextButton = (Button) findViewById(R.id.nextButton);
+        mBackButton = (Button) findViewById(R.id.backButton);
+
+        mOOBETextGroup1 = (View) findViewById(R.id.oobeTextGroup1);
+        mOOBETextGroup2 = (View) findViewById(R.id.oobeTextGroup2);
+        mOOBETextGroup3 = (View) findViewById(R.id.oobeTextGroup3);
+        mOOBETextGroup4 = (View) findViewById(R.id.oobeTextGroup4);
+        mOOBETextGroup5 = (View) findViewById(R.id.oobeTextGroup5);
+        mOOBETextGroup6 = (View) findViewById(R.id.oobeTextGroup6);
+        mOOBETextGroup7 = (View) findViewById(R.id.oobeTextGroup7);
+        mOOBETextGroup8 = (View) findViewById(R.id.oobeTextGroup8);
+        mOOBETextGroup9 = (View) findViewById(R.id.oobeTextGroup9);
+
+        mSelectLanguageButton = (ImageButton) findViewById(R.id.selectLanguageButton);
+        mSetupWifiButton = (ImageButton) findViewById(R.id.setupWifiButton);
+
+        mSkipButton.setVisibility(View.GONE);
+        mBackButton.setVisibility(View.GONE);
+        mNextButton.setVisibility(View.GONE);
+
+        mSelectLanguageButton.setOnClickListener(new OnClickListener()
+        {
+
+            @Override
+            public void onClick(View v)
+            {
+                startActivityForResult(new Intent(Settings.ACTION_LOCALE_SETTINGS), RESULT_LANGUAGE_SETUP);
+            }
+        });
+
+        mSetupWifiButton.setOnClickListener(new OnClickListener()
+        {
+
+            @Override
+            public void onClick(View v)
+            {
+                startActivityForResult(new Intent(Settings.ACTION_WIFI_SETTINGS), RESULT_WIFI_SETUP);
+            }
+        });
+    }
+    
+    
+    @Override
+	protected void onActivityResult(final int requestCode,
+			final int resultCode, final Intent data) {
+    	
+    	switch(requestCode){
+    		case RESULT_WIFI_SETUP:
+    			jumpToNextSlide();
+    			break;
+    		case RESULT_LANGUAGE_SETUP:
+    			jumpToNextSlide();
+    			break;
+    	}
+    }
+
+    private void setupAnimationStart()
+    {
+        switch (mTutorialToShow)
+        {
+            case OOBE_FULL_TUTORIAL:
+            {
+                setupTheVideo();
+                setupFullTutorialSteps();
+                break;
+            }
+            case OOBE_DEVICE_TUTORIAL:
+            {
+                setupTheVideo();
+                setupDefinitionsSteps();
+                setupEdgeSwipeTutorialSteps();
+                break;
+            }
+            case OOBE_EDIT_FAVORITES_TUTORIAL:
+            {
+                hideVideo();
+                setupEditFavoritesTutorialSteps();
+                startTutorialInitialAnimation();
+                break;
+            }
+            default:
+            {
+                mTutorialToShow = OOBE_FULL_TUTORIAL;
+                setupTheVideo();
+                setupFullTutorialSteps();
+                break;
+            }
+        }
+
+        startStepAnimation(mAnimationSteps.get(0));
+
+    }
+
+    private void hideVideo()
+    {
+        RelativeLayout rl = (RelativeLayout) findViewById(R.id.oobeVideoViewGroup);
+        rl.setVisibility(View.GONE);
+    }
+
+    private void setupEditFavoritesTutorialSteps()
+    {
+        mAnimationSteps.add(OOBESteps.EDIT_INTRO);
+        mAnimationSteps.add(OOBESteps.EDIT_DRAG_NEW_FAVORITE);
+        mAnimationSteps.add(OOBESteps.EDIT_DRAG_REMOVE_FAVORITE);
+        mAnimationSteps.add(OOBESteps.EDIT_DRAG_TRADE_FAVORITE);
+    }
+
+    private void setupDefinitionsSteps()
+    {
+        mAnimationSteps.add(OOBESteps.SELECT_LANGUAGE);
+        mAnimationSteps.add(OOBESteps.SETUP_WIFI);
+    }
+
+    private void setupEdgeSwipeTutorialSteps()
+    {
+        mAnimationSteps.add(OOBESteps.DEVICE_INTRO);
+        mAnimationSteps.add(OOBESteps.EDGE_SWIPE_APPEAR);
+        mAnimationSteps.add(OOBESteps.EDGE_SWIPE_SELECTION);
+    }
+
+    private void setupTheVideo()
+    {
+
+        RelativeLayout rl = (RelativeLayout) findViewById(R.id.oobeVideoViewGroup);
+        rl.setVisibility(View.VISIBLE);
+
+        mVideo = (VideoView) findViewById(R.id.fp_oobe_video);
+
+        Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.fp_buy_a_phone_start_a_movement);
+
+        mVideo.setMediaController(null);
+        mVideo.requestFocus();
+        mVideo.setVideoURI(uri);
+
+        mVideo.setOnTouchListener(new OnTouchListener()
+        {
+
+            @Override
+            public boolean onTouch(View v, MotionEvent event)
+            {
+                return true;
+            }
+        });
+
+        mVideo.start();
+
+        mVideo.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
+        {
+
+            @Override
+            public void onCompletion(MediaPlayer mp)
+            {
+                stopIntroVideo();
+            }
+        });
+
+        // button
+        mSkipVideoButton = (Button) findViewById(R.id.fp_oobe_video_skip_button);
+
+        mSkipVideoButton.setOnClickListener(new OnClickListener()
+        {
+
+            @Override
+            public void onClick(View v)
+            {
+                stopIntroVideo();
+            }
+        });
+    }
+
+    private void stopIntroVideo()
+    {
+        mVideo.stopPlayback();
+
+        final RelativeLayout rl = (RelativeLayout) findViewById(R.id.oobeVideoViewGroup);
+        Animation fadeOutAnimation = AnimationUtils.loadAnimation(OOBEActivity.this, R.anim.fade_out_slow);
+        rl.startAnimation(fadeOutAnimation);
+
+        fadeOutAnimation.setAnimationListener(new AnimationListener()
+        {
+
+            @Override
+            public void onAnimationStart(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation)
+            {
+                rl.setVisibility(View.GONE);
+                mVideo.setVisibility(View.GONE);
+                mSkipVideoButton.setVisibility(View.GONE);
+            }
+        });
+
+        startTutorialInitialAnimation();
+    }
+
+    private void startTutorialInitialAnimation()
+    {
+        Animation oobeAnimation = AnimationUtils.loadAnimation(this, R.anim.fade_in_slow);
+        findViewById(R.id.oobe_background).startAnimation(oobeAnimation);
+    }
+
+    private void setupFullTutorialSteps()
+    {
+        setupEdgeSwipeTutorialSteps();
+        setupEditFavoritesTutorialSteps();
+    }
+
+    private void jumpToNextSlide() {
+		// increment the step counter
+        mCurrentStep++;
+
+        if (mCurrentStep < mAnimationSteps.size())
+        {
+            startStepAnimation(mAnimationSteps.get(mCurrentStep));
+        }
+	}
+    
+    private void setupListeners()
+    {
+        mSkipButton.setOnClickListener(new OnClickListener()
+        {
+            @Override
+            public void onClick(View v)
+            {
+            	if(mCurrentStep < 2 && (mTutorialToShow == OOBE_DEVICE_TUTORIAL)){
+            		jumpToNextSlide();
+            	}else {
+            		endOOBEActivity();
+            	}
+            }
+        });
+
+        mStartButton.setOnClickListener(new OnClickListener()
+        {
+            @Override
+            public void onClick(View v)
+            {
+                jumpToNextSlide();
+            }
+
+			
+
+        });
+
+        mNextButton.setOnClickListener(new OnClickListener()
+        {
+            @Override
+            public void onClick(View v)
+            {
+                // increment the step counter
+                mCurrentStep++;
+
+                if (mCurrentStep < mAnimationSteps.size())
+                {
+                    startStepAnimation(mAnimationSteps.get(mCurrentStep));
+                }
+                else
+                {
+                    endOOBEActivity();
+                }
+            }
+
+        });
+
+        mBackButton.setOnClickListener(new OnClickListener()
+        {
+            @Override
+            public void onClick(View v)
+            {
+
+                // decrement the step counter
+                mCurrentStep--;
+
+                if (mCurrentStep >= 0)
+                {
+                    startStepAnimation(mAnimationSteps.get(mCurrentStep));
+                }
+                else
+                {
+                    endOOBEActivity();
+                }
+            }
+
+        });
+    }
+
+    private void startStepAnimation(OOBESteps step)
+    {
+        switch (step)
+        {
+            case SELECT_LANGUAGE:
+                startAnimation(null);
+                setTextView(mOOBETextGroup1);
+                break;
+            case SETUP_WIFI:
+                startAnimation(null);
+                setTextView(mOOBETextGroup2);
+                break;
+            case DEVICE_INTRO:
+                startAnimation(null);
+                setTextView(mOOBETextGroup3);
+                break;
+            case EDGE_SWIPE_APPEAR:
+                startAnimation(new EdgeSwipeTutorialAnimationHelper());
+                setTextView(mOOBETextGroup4);
+                break;
+            case EDGE_SWIPE_SELECTION:
+                startAnimation(new OpenAppTutorialAnimationHelper());
+                setTextView(mOOBETextGroup5);
+                break;
+            case EDIT_INTRO:
+                startAnimation(null);
+                setTextView(mOOBETextGroup6);
+                break;
+            case EDIT_DRAG_NEW_FAVORITE:
+                startAnimation(new AddFavTutorialAnimationHelper());
+                setTextView(mOOBETextGroup7);
+                break;
+            case EDIT_DRAG_REMOVE_FAVORITE:
+                startAnimation(new RemoveFavTutorialAnimationHelper());
+                setTextView(mOOBETextGroup8);
+                break;
+            case EDIT_DRAG_TRADE_FAVORITE:
+                startAnimation(new MoveFavTutorialAnimationHelper());
+                setTextView(mOOBETextGroup9);
+                break;
+            default:
+
+        }
+
+        setupButtons();
+    }
+
+    private void setupButtons() {
+
+		int visibilityNext = View.VISIBLE;
+		int visibilityBack = View.VISIBLE;
+		int visibilityStart = View.VISIBLE;
+		int visibilitySkip = View.VISIBLE;
+
+		if (mCurrentStep <= 0) {
+
+			if (mTutorialToShow == OOBE_DEVICE_TUTORIAL) {
+				if (mCurrentStep < 1) {
+					visibilityBack = View.GONE;
+					visibilityStart = View.GONE;
+					visibilityNext = View.GONE;
+				} else {
+					visibilityStart = View.GONE;
+					visibilitySkip = View.GONE;
+					visibilityNext = View.GONE;
+				}
+			} else {
+				visibilityNext = View.GONE;
+				visibilityBack = View.GONE;
+				visibilitySkip = View.GONE;
+			}
+		} else if (mCurrentStep >= (mAnimationSteps.size() - 1)) {
+
+			mSkipButton.setText(getResources().getString(R.string.oobe_done));
+			visibilityNext = View.GONE;
+			visibilityStart = View.GONE;
+		} else {
+			mSkipButton.setText(getResources().getString(R.string.oobe_skip));
+			visibilityStart = View.GONE;
+			if (mTutorialToShow == OOBE_DEVICE_TUTORIAL) {
+				if (mCurrentStep < 2) {
+					visibilityStart = View.GONE;
+					visibilityNext = View.GONE;
+				}
+				
+				if (mCurrentStep < 1) {
+					visibilityBack = View.GONE;
+				}
+			}
+
+		}
+
+		mNextButton.setVisibility(visibilityNext);
+		mBackButton.setVisibility(visibilityBack);
+		mStartButton.setVisibility(visibilityStart);
+		mSkipButton.setVisibility(visibilitySkip);
+	}
+
+
+    private void setTextView(View targetTextView)
+    {
+        mOOBETextGroup1.setVisibility(targetTextView == mOOBETextGroup1 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup1 is " + (mOOBETextGroup1.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+        mOOBETextGroup2.setVisibility(targetTextView == mOOBETextGroup2 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup2 is " + (mOOBETextGroup2.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+        mOOBETextGroup3.setVisibility(targetTextView == mOOBETextGroup3 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup3 is " + (mOOBETextGroup3.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+        mOOBETextGroup4.setVisibility(targetTextView == mOOBETextGroup4 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup4 is " + (mOOBETextGroup4.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+        mOOBETextGroup5.setVisibility(targetTextView == mOOBETextGroup5 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup5 is " + (mOOBETextGroup5.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+        mOOBETextGroup6.setVisibility(targetTextView == mOOBETextGroup6 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup6 is " + (mOOBETextGroup6.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+        mOOBETextGroup7.setVisibility(targetTextView == mOOBETextGroup7 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup7 is " + (mOOBETextGroup7.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+
+        mOOBETextGroup8.setVisibility(targetTextView == mOOBETextGroup8 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup8 is " + (mOOBETextGroup8.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+
+        mOOBETextGroup9.setVisibility(targetTextView == mOOBETextGroup9 ? View.VISIBLE : View.GONE);
+//        Log.d("OOBE", "mTextGroup9 is " + (mOOBETextGroup9.getVisibility() == View.VISIBLE ? " visible" : " gone"));
+
+        Animation oobeAnimation = AnimationUtils.loadAnimation(this, R.anim.fade_in_fast);
+
+        targetTextView.startAnimation(oobeAnimation);
+
+        targetTextView.setVisibility(View.VISIBLE);
+    }
+
+    private void endOOBEActivity()
+    {
+        mSkipButton.setVisibility(View.GONE);
+        mNextButton.setVisibility(View.GONE);
+        mBackButton.setVisibility(View.GONE);
+
+        finish();
+    }
+
+    void startAnimation(TutorialAnimationHelper anim)
+    {
+        if (anim != null)
+        {
+            if (mCurAnimHelper == null)
+            {
+                mCurAnimHelper = anim;
+                mCurAnimHelper.setTutorialAnimationHelperListener(this);
+                View animHelperRootView = mCurAnimHelper.setup(getApplicationContext());
+                mAnimationHolder.addView(animHelperRootView);
+                mCurAnimHelper.playIntro();
+            }
+            else
+            {
+                mCurAnimHelper.playOutro();
+                mNextAnimHelper = anim;
+            }
+        }
+        else
+        {
+            if (mCurAnimHelper != null)
+            {
+                mCurAnimHelper.playOutro();
+                mNextAnimHelper = null;
+            }
+        }
+    }
+
+    @Override
+    public void onTutorialAnimationFinished(TutorialAnimationHelper helper, TutorialState state)
+    {
+        if (helper == mCurAnimHelper)
+        {
+            if (state == TutorialState.Outro)
+            {
+                mAnimationHolder.removeAllViews();
+                mCurAnimHelper = mNextAnimHelper;
+                mNextAnimHelper = null;
+                if (mCurAnimHelper != null)
+                {
+                    View animHelperRootView = mCurAnimHelper.setup(getApplicationContext());
+                    mCurAnimHelper.setTutorialAnimationHelperListener(this);
+                    mAnimationHolder.addView(animHelperRootView);
+                    mCurAnimHelper.playIntro();
+                }
+            }
+            else if (state == TutorialState.Intro)
+            {
+                mCurAnimHelper.playMain();
+            }
+        }
+    }
+
+    public static void changeLocale(Locale locale)
+    {
+        try
+        {
+            Class<?> activityManagerNative = Class.forName("android.app.ActivityManagerNative");
+
+            Object am = activityManagerNative.getMethod("getDefault").invoke(activityManagerNative);
+
+            Object config = am.getClass().getMethod("getConfiguration").invoke(am);
+            config.getClass().getDeclaredField("locale").set(config, locale);
+            config.getClass().getDeclaredField("userSetLocale").setBoolean(config, true);
+
+            am.getClass().getMethod("updateConfiguration", android.content.res.Configuration.class).invoke(am, config);
+//            Log.i("", "send change locale request");
+        } catch (Exception e)
+        {
+            Log.e("", "change locale error:", e);
+        }
+    }
+
+	public TutorialAnimationHelper getCurrentAnimationHelper() {
+		return mCurAnimHelper;
+	}
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper.java b/FairphoneHome/src/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper.java
new file mode 100644
index 0000000..c21dd53
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/AddFavTutorialAnimationHelper.java
@@ -0,0 +1,214 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.animation.EditFavsTutorialAnimationView.EditFavsTutorialAnimationViewListener;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+
+public class AddFavTutorialAnimationHelper implements TutorialAnimationHelper, EditFavsTutorialAnimationViewListener
+{
+    EditFavsTutorialAnimationView animView;
+    View rootView;
+    Context context;
+    TutorialAnimationHelperListener listener;
+    TutorialState curState = TutorialState.IdleInvisible;
+    
+    
+    @Override
+    public View setup(Context context)
+    {
+        this.context = context;
+        
+        rootView = LayoutInflater.from(context).inflate(R.layout.tutorial_edit_fav_add_layout, null);
+        animView = (EditFavsTutorialAnimationView)rootView.findViewById(R.id.editFavAddAnimationView);
+        
+        animView.playAddFavAnimation();
+        animView.stopAnimations();
+        
+        animView.setEditFavsTutorialAnimationViewListener(this);
+        
+        return rootView;
+    }
+
+
+    @Override
+    public void setTutorialAnimationHelperListener(TutorialAnimationHelperListener listener)
+    {
+        this.listener = listener;
+    }
+
+    int curAnimationId = 0;
+    TutorialViewAnimationListener curStateAnimationListener;
+    
+    private TutorialViewAnimationListener getCurStateAnimationListener()
+    {
+        return curStateAnimationListener;
+    }
+    
+    @Override
+    public boolean playIntro()
+    {
+        if(curState==TutorialState.Intro)
+            return false;
+        startAnimationState(TutorialState.Intro,null);
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_intro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.setVisibility(View.VISIBLE);
+        rootView.startAnimation(fadeAnim);
+        return true;
+    }
+
+
+    @Override
+    public boolean playMain()
+    {
+        if(curState!=TutorialState.IdleVisible)
+            return false;
+        
+        startAnimationState(TutorialState.Main,null);
+        animView.playAddFavAnimation();
+        return true;
+    }
+    
+    @Override
+    public boolean playOutro()
+    {
+        if(curState==TutorialState.Outro)
+            return false;
+        
+        startAnimationState(TutorialState.Outro, new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                rootView.setVisibility(View.GONE);
+            }
+        });
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_outro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.startAnimation(fadeAnim);
+        
+        return true;
+    }
+    
+    private void startState(TutorialState newState)
+    {
+        curState = newState;
+        curAnimationId++;
+    }
+    
+    private void startAnimationState(TutorialState newState, Runnable runnable)
+    {
+        curState = newState;
+        curAnimationId++;
+        curStateAnimationListener = new TutorialViewAnimationListener(curAnimationId,runnable);
+    }
+
+    private void onAnimationFinished(int animationId)
+    {
+        if(animationId!=curAnimationId)
+        {
+            return;
+        }
+        
+        if(curState==TutorialState.Intro)
+        {
+            startState(TutorialState.IdleVisible);
+            playMain();
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Intro);
+            }
+        }
+        else if(curState==TutorialState.Main)
+        {
+            startState(TutorialState.IdleVisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Main);
+            }
+            playMain();
+        }
+        else if(curState==TutorialState.Outro)
+        {
+            startState(TutorialState.IdleInvisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Outro);
+            }
+        }
+    }
+    
+
+    private class TutorialViewAnimationListener implements AnimationListener
+    {
+        int startNum = 0;
+        int finishNum=0;
+        int animationId;
+        Runnable runnable;
+        
+        public TutorialViewAnimationListener(int animationid, Runnable runnable)
+        {
+            this.animationId = animationid;
+            this.runnable = runnable;
+        }
+        
+        int getAnimationId()
+        {
+            return animationId;
+        }
+        
+        @Override
+        public void onAnimationStart(Animation animation)
+        {
+            startNum++;
+        }
+
+        @Override
+        public void onAnimationEnd(Animation animation)
+        {
+            finishNum++;
+            if(finishNum==startNum)
+            {
+                if(runnable!=null)
+                {
+                    runnable.run();
+                }
+                onAnimationFinished(animationId);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation)
+        {
+        }
+    }
+
+
+    @Override
+    public void OnAnimationFinished(EditFavsTutorialAnimationView view)
+    {
+        animView.playAddFavAnimation();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper.java b/FairphoneHome/src/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper.java
new file mode 100644
index 0000000..60225b2
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/EdgeSwipeTutorialAnimationHelper.java
@@ -0,0 +1,215 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.animation.MenuTutorialAnimationView.MenuTutorialAnimationViewListener;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+
+public class EdgeSwipeTutorialAnimationHelper implements TutorialAnimationHelper, MenuTutorialAnimationViewListener
+{
+    MenuTutorialAnimationView animView;
+    View rootView;
+    Context context;
+    TutorialAnimationHelperListener listener;
+    TutorialState curState = TutorialState.IdleInvisible;
+    
+    
+    @Override
+    public View setup(Context context)
+    {
+        this.context = context;
+        
+        rootView = LayoutInflater.from(context).inflate(R.layout.tutorial_open_app_layout, null);
+        animView = (MenuTutorialAnimationView)rootView.findViewById(R.id.openAppAnimationView);
+        
+        animView.playSwipeAnimation();
+        animView.stopAnimations();
+        
+        animView.setMenuTutorialAnimationViewListener(this);
+        
+        return rootView;
+    }
+
+
+    @Override
+    public void setTutorialAnimationHelperListener(TutorialAnimationHelperListener listener)
+    {
+        this.listener = listener;
+    }
+
+    int curAnimationId = 0;
+    TutorialViewAnimationListener curStateAnimationListener;
+    
+    private TutorialViewAnimationListener getCurStateAnimationListener()
+    {
+        return curStateAnimationListener;
+    }
+    
+    @Override
+    public boolean playIntro()
+    {
+        if(curState==TutorialState.Intro)
+            return false;
+        startAnimationState(TutorialState.Intro,null);
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_intro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.setVisibility(View.VISIBLE);
+        rootView.startAnimation(fadeAnim);
+        
+        return true;
+    }
+
+
+    @Override
+    public boolean playMain()
+    {
+        if(curState!=TutorialState.IdleVisible)
+            return false;
+        
+        startAnimationState(TutorialState.Main,null);
+        animView.playSwipeAnimation();
+        return true;
+    }
+    
+    @Override
+    public boolean playOutro()
+    {
+        if(curState==TutorialState.Outro)
+            return false;
+        
+        startAnimationState(TutorialState.Outro, new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                rootView.setVisibility(View.GONE);
+            }
+        });
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_outro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.startAnimation(fadeAnim);
+        
+        return true;
+    }
+    
+    private void startState(TutorialState newState)
+    {
+        curState = newState;
+        curAnimationId++;
+    }
+    
+    private void startAnimationState(TutorialState newState, Runnable runnable)
+    {
+        curState = newState;
+        curAnimationId++;
+        curStateAnimationListener = new TutorialViewAnimationListener(curAnimationId,runnable);
+    }
+
+    private void onAnimationFinished(int animationId)
+    {
+        if(animationId!=curAnimationId)
+        {
+            return;
+        }
+        
+        if(curState==TutorialState.Intro)
+        {
+            startState(TutorialState.IdleVisible);
+            playMain();
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Intro);
+            }
+        }
+        else if(curState==TutorialState.Main)
+        {
+            startState(TutorialState.IdleVisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Main);
+            }
+            playMain();
+        }
+        else if(curState==TutorialState.Outro)
+        {
+            startState(TutorialState.IdleInvisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Outro);
+            }
+        }
+    }
+    
+
+    private class TutorialViewAnimationListener implements AnimationListener
+    {
+        int startNum = 0;
+        int finishNum=0;
+        int animationId;
+        Runnable runnable;
+        
+        public TutorialViewAnimationListener(int animationid, Runnable runnable)
+        {
+            this.animationId = animationid;
+            this.runnable = runnable;
+        }
+        
+        int getAnimationId()
+        {
+            return animationId;
+        }
+        
+        @Override
+        public void onAnimationStart(Animation animation)
+        {
+            startNum++;
+        }
+
+        @Override
+        public void onAnimationEnd(Animation animation)
+        {
+            finishNum++;
+            if(finishNum==startNum)
+            {
+                if(runnable!=null)
+                {
+                    runnable.run();
+                }
+                onAnimationFinished(animationId);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation)
+        {
+        }
+    }
+
+
+    @Override
+    public void OnAnimationFinished(MenuTutorialAnimationView view)
+    {
+        animView.playSwipeAnimation();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/EditFavsTutorialAnimationView.java b/FairphoneHome/src/org/fairphone/oobe/animation/EditFavsTutorialAnimationView.java
new file mode 100644
index 0000000..ef5907a
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/EditFavsTutorialAnimationView.java
@@ -0,0 +1,665 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.utils.KWAnimation;
+import org.fairphone.oobe.utils.KWAnimation.KWValueAnimation;
+import org.fairphone.oobe.utils.KWAnimation.KWValueType;
+import org.fairphone.oobe.utils.KWAnimationGroup;
+import org.fairphone.oobe.utils.KWAnimationGroup.KWAnimationGroupListener;
+import org.fairphone.oobe.utils.KWAnimationManager;
+import org.fairphone.oobe.utils.KWSprite;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+public class EditFavsTutorialAnimationView extends FrameLayout
+{
+
+    public interface EditFavsTutorialAnimationViewListener
+    {
+        public void OnAnimationFinished(EditFavsTutorialAnimationView view);
+    }
+
+    private static final int SCREEN_WIDTH = 540;
+    private static final int SCREEN_HEIGHT = 960;
+
+    KWSprite spriteRoot;
+
+    KWSprite spriteArrow;
+    KWSprite spriteHand;
+    KWSprite spriteHandShadow;
+    KWSprite spriteAllApps;
+    KWSprite spriteFavApps;
+    KWSprite spriteAppIconAll1;
+    KWSprite spriteAppIconFav1;
+    KWSprite spriteAppIconFav2;
+    KWSprite spriteAppIconFav3;
+    KWSprite spriteAppIconFavSelected1;
+    KWSprite spriteAppIconFavSelected2;
+    KWSprite spriteAppIconFavSelected3;
+    KWSprite spriteDeleteHighlight;
+    KWSprite spriteDeleteX;
+
+    Paint spritePaint;
+
+    KWAnimationGroup animationGroupRemoveFav;
+    KWAnimationGroup animationGroupAddFav;
+    KWAnimationGroup animationGroupMoveFav;
+    KWAnimationManager animationManager;
+
+    private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
+    private AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
+    private AccelerateDecelerateInterpolator accelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
+    long prevFrame = 0;
+
+    EditFavsTutorialAnimationViewListener listener;
+
+    public EditFavsTutorialAnimationView(Context context)
+    {
+        super(context);
+        init();
+    }
+
+    public EditFavsTutorialAnimationView(Context context, AttributeSet attrs)
+    {
+        super(context, attrs);
+        init();
+    }
+
+    public EditFavsTutorialAnimationView(Context context, AttributeSet attrs, int defStyle)
+    {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    public void setEditFavsTutorialAnimationViewListener(EditFavsTutorialAnimationViewListener listener)
+    {
+        this.listener = listener;
+    }
+
+    public void playAddFavAnimation()
+    {
+        stopAnimations();
+        animationGroupAddFav.start();
+    }
+
+    public void playRemoveFavAnimation()
+    {
+        stopAnimations();
+        animationGroupRemoveFav.start();
+    }
+
+    public void playMoveFavAnimation()
+    {
+        stopAnimations();
+        animationGroupMoveFav.start();
+    }
+
+    public void stopAnimations()
+    {
+        animationGroupRemoveFav.stop();
+        animationGroupAddFav.stop();
+        animationGroupMoveFav.stop();
+    }
+
+    private void init()
+    {
+        if (getBackground() == null)
+        {
+            setBackgroundColor(0x00000000);
+        }
+
+        spritePaint = new Paint();
+        spritePaint.setColor(0xffffffff);
+
+        spriteRoot = new KWSprite();
+        spriteArrow = new KWSprite();
+        spriteHand = new KWSprite();
+        spriteHandShadow = new KWSprite();
+        spriteAllApps = new KWSprite();
+        spriteFavApps = new KWSprite();
+        spriteAppIconAll1 = new KWSprite();
+        spriteAppIconFav1 = new KWSprite();
+        spriteAppIconFav2 = new KWSprite();
+        spriteAppIconFav3 = new KWSprite();
+        spriteAppIconFavSelected1 = new KWSprite();
+        spriteAppIconFavSelected2 = new KWSprite();
+        spriteAppIconFavSelected3 = new KWSprite();
+        spriteDeleteHighlight = new KWSprite();
+        spriteDeleteX = new KWSprite();
+
+        spriteArrow.drawable = getResources().getDrawable(R.drawable.oobe_arrow_big);
+        spriteArrow.applySizeFromDrawable();
+        spriteHand.drawable = getResources().getDrawable(R.drawable.oobe_hand);
+        spriteHand.applySizeFromDrawable();
+        spriteHandShadow.drawable = getResources().getDrawable(R.drawable.oobe_hand_shadow);
+        spriteHandShadow.applySizeFromDrawable();
+        spriteAllApps.drawable = getResources().getDrawable(R.drawable.oobe_edit_all_apps);
+        spriteAllApps.applySizeFromDrawable();
+        spriteFavApps.drawable = getResources().getDrawable(R.drawable.oobe_edit_favourite_apps);
+        spriteFavApps.applySizeFromDrawable();
+        spriteAppIconAll1.drawable = getResources().getDrawable(R.drawable.oobe_app_icon_small);
+        spriteAppIconAll1.applySizeFromDrawable();
+        spriteAppIconFav1.drawable = getResources().getDrawable(R.drawable.oobe_app_icon);
+        spriteAppIconFav1.applySizeFromDrawable();
+        spriteAppIconFav2.drawable = getResources().getDrawable(R.drawable.oobe_app_icon);
+        spriteAppIconFav2.applySizeFromDrawable();
+        spriteAppIconFav3.drawable = getResources().getDrawable(R.drawable.oobe_app_icon);
+        spriteAppIconFav3.applySizeFromDrawable();
+        spriteAppIconFavSelected1.drawable = getResources().getDrawable(R.drawable.oobe_icon_select);
+        spriteAppIconFavSelected1.applySizeFromDrawable();
+        spriteAppIconFavSelected2.drawable = getResources().getDrawable(R.drawable.oobe_icon_select);
+        spriteAppIconFavSelected2.applySizeFromDrawable();
+        spriteAppIconFavSelected3.drawable = getResources().getDrawable(R.drawable.oobe_icon_select);
+        spriteAppIconFavSelected3.applySizeFromDrawable();
+        spriteDeleteHighlight.drawable = getResources().getDrawable(R.drawable.oobe_delete_higlight);
+        spriteDeleteHighlight.applySizeFromDrawable();
+        spriteDeleteX.drawable = getResources().getDrawable(R.drawable.oobe_delete_x);
+        spriteDeleteX.applySizeFromDrawable();
+
+        spriteRoot.addChild(spriteArrow);
+        spriteRoot.addChild(spriteHand);
+        spriteRoot.addChild(spriteHandShadow);
+        spriteRoot.addChild(spriteAllApps);
+        spriteRoot.addChild(spriteFavApps);
+        spriteAllApps.addChild(spriteAppIconAll1);
+        spriteFavApps.addChild(spriteAppIconFav1);
+        spriteFavApps.addChild(spriteAppIconFavSelected1);
+        spriteFavApps.addChild(spriteAppIconFav2);
+        spriteFavApps.addChild(spriteAppIconFavSelected2);
+        spriteFavApps.addChild(spriteAppIconFav3);
+        spriteFavApps.addChild(spriteAppIconFavSelected3);
+        spriteAllApps.addChild(spriteDeleteHighlight);
+        spriteDeleteHighlight.addChild(spriteDeleteX);
+
+        spriteRoot.alpha = 0;
+
+        // Animation setup
+
+        animationManager = new KWAnimationManager();
+        animationGroupAddFav = new KWAnimationGroup(animationManager);
+        animationGroupRemoveFav = new KWAnimationGroup(animationManager);
+        animationGroupMoveFav = new KWAnimationGroup(animationManager);
+
+        setupRemoveFavAnimation();
+        setupAddFavAnimation();
+        setupMoveFavAnimation();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
+    {
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas)
+    {
+        spriteRoot.resetMatrix();
+        spriteArrow.draw(canvas, spritePaint);
+        spriteAllApps.draw(canvas, spritePaint);
+        spriteFavApps.draw(canvas, spritePaint);
+        spriteAppIconAll1.draw(canvas, spritePaint);
+        spriteDeleteHighlight.draw(canvas, spritePaint);
+        spriteDeleteX.draw(canvas, spritePaint);
+        spriteAppIconFav3.draw(canvas, spritePaint);
+        spriteAppIconFavSelected3.draw(canvas, spritePaint);
+        spriteAppIconFav2.draw(canvas, spritePaint);
+        spriteAppIconFavSelected2.draw(canvas, spritePaint);
+        spriteAppIconFav1.draw(canvas, spritePaint);
+        spriteAppIconFavSelected1.draw(canvas, spritePaint);
+        spriteHandShadow.draw(canvas, spritePaint);
+        spriteHand.draw(canvas, spritePaint);
+        animationManager.update();
+        postInvalidate();
+    }
+
+    /*****************************************
+     * 
+     * setupRemoveFavAnimation()
+     * 
+     *****************************************/
+
+    private void setupRemoveFavAnimation()
+    {
+        long startTime = 400;
+        long endTime = 1700;
+
+        KWValueAnimation alphaAnim;
+        KWValueAnimation xAnim;
+        KWValueAnimation yAnim;
+        KWValueAnimation scaleAnim;
+
+        KWAnimation deleteHighlightAnimation = new KWAnimation(spriteDeleteHighlight);
+        alphaAnim = deleteHighlightAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 1000, null);
+        alphaAnim.addKeyframe(1, 1200, accelerateInterpolator);
+        alphaAnim.addKeyframe(1, endTime, null);
+        alphaAnim.addKeyframe(0, endTime + 500, accelerateInterpolator);
+
+        KWAnimation fingerAnimation = new KWAnimation(spriteHand);
+        xAnim = fingerAnimation.addValueAnimation(KWValueType.X);
+        yAnim = fingerAnimation.addValueAnimation(KWValueType.Y);
+        xAnim.addKeyframe(441, startTime + 200, null);
+        yAnim.addKeyframe(388, startTime + 200, null);
+        xAnim.addKeyframe(206, startTime + 1200, accelerateDecelerateInterpolator);
+        yAnim.addKeyframe(388, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = fingerAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime, null);
+        alphaAnim.addKeyframe(1, endTime, null);
+        alphaAnim.addKeyframe(0, endTime + 500, accelerateInterpolator);
+
+        KWAnimation arrowAnimation = new KWAnimation(spriteArrow);
+        alphaAnim = arrowAnimation.addValueAnimation(KWValueType.Alpha);
+        xAnim = arrowAnimation.addValueAnimation(KWValueType.X);
+        alphaAnim.addKeyframe(0, startTime + 400, null);
+        xAnim.addKeyframe(332, startTime + 400, null);
+        alphaAnim.addKeyframe(1, startTime + 1300, accelerateDecelerateInterpolator);
+        xAnim.addKeyframe(266, startTime + 1300, accelerateDecelerateInterpolator);
+        alphaAnim.addKeyframe(0, endTime + 350, accelerateInterpolator);
+
+        KWAnimation favIconSelected2Animation = new KWAnimation(spriteAppIconFavSelected2);
+        xAnim = favIconSelected2Animation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(0, startTime + 200, null);
+        xAnim.addKeyframe(-238, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = favIconSelected2Animation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime + 100, decelerateInterpolator);
+        alphaAnim.addKeyframe(1, endTime - 100, null);
+        alphaAnim.addKeyframe(0, endTime + 400, decelerateInterpolator);
+
+        animationGroupRemoveFav.addAnimation(fingerAnimation);
+        animationGroupRemoveFav.addAnimation(arrowAnimation);
+        animationGroupRemoveFav.addAnimation(deleteHighlightAnimation);
+        animationGroupRemoveFav.addAnimation(favIconSelected2Animation);
+
+        animationGroupRemoveFav.setAnimationGroupListener(new KWAnimationGroupListener()
+        {
+            @Override
+            public void onAnimationGroupStarted(KWAnimationGroup group)
+            {
+                spriteRoot.clearTransform(true);
+                spriteRoot.alpha = 1;
+                spriteArrow.alpha = 0;
+                spriteHand.alpha = 0;
+                spriteHandShadow.alpha = 0;
+                spriteAllApps.alpha = 1;
+                spriteFavApps.alpha = 1;
+                spriteAppIconAll1.alpha = 1;
+                spriteAppIconFav1.alpha = 1;
+                spriteAppIconFavSelected1.alpha = 0;
+                spriteAppIconFav2.alpha = 0;
+                spriteAppIconFavSelected2.alpha = 0;
+                spriteAppIconFav3.alpha = 1;
+                spriteAppIconFavSelected3.alpha = 0;
+                spriteDeleteHighlight.alpha = 0;
+                spriteDeleteX.alpha = 1;
+
+                spriteArrow.y = 388;
+                spriteArrow.pivotX = 0;
+                spriteArrow.pivotY = 0.5f;
+                spriteArrow.scaleX = 0.8f;
+                spriteArrow.scaleY = 0.8f;
+
+                spriteHand.pivotX = 18.0f / spriteHand.width;
+                spriteHand.pivotY = 21.0f / spriteHand.height;
+
+                spriteHandShadow.pivotX = 54.0f / spriteHandShadow.width;
+                spriteHandShadow.pivotY = 53.0f / spriteHandShadow.height;
+
+                spriteAllApps.x = 60;
+                spriteAllApps.y = (SCREEN_HEIGHT - spriteAllApps.height) / 2;
+                spriteAppIconAll1.x = 110;
+                spriteAppIconAll1.y = 97;
+
+                spriteFavApps.x = SCREEN_WIDTH - spriteFavApps.width - 50;
+                spriteFavApps.y = (SCREEN_HEIGHT - spriteFavApps.height) / 2;
+                spriteAppIconFav1.x = 0;
+                spriteAppIconFav1.y = 0;
+                spriteAppIconFavSelected1.x = 0;
+                spriteAppIconFavSelected1.y = 0;
+
+                spriteAppIconFav2.x = 0;
+                spriteAppIconFav2.y = 96;
+                spriteAppIconFavSelected2.x = 0;
+                spriteAppIconFavSelected2.y = 96;
+
+                spriteAppIconFav3.x = 0;
+                spriteAppIconFav3.y = 286;
+                spriteAppIconFavSelected3.x = 0;
+                spriteAppIconFavSelected3.y = 286;
+
+                spriteDeleteHighlight.pivotX = 0.5f;
+                spriteDeleteHighlight.pivotY = 0.5f;
+                spriteDeleteHighlight.x = spriteAllApps.width / 2;
+                spriteDeleteHighlight.y = spriteAllApps.height / 2;
+
+                spriteDeleteX.pivotX = 0.5f;
+                spriteDeleteX.pivotY = 0.5f;
+                spriteDeleteX.x = 0;
+                spriteDeleteX.y = 0;
+            }
+
+            @Override
+            public void onAnimationGroupFinished(KWAnimationGroup group)
+            {
+                if (listener != null)
+                {
+                    listener.OnAnimationFinished(EditFavsTutorialAnimationView.this);
+                }
+            }
+        });
+    }
+
+    /*****************************************
+     * 
+     * setupAddFavAnimation()
+     * 
+     *****************************************/
+
+    private void setupAddFavAnimation()
+    {
+        long startTime = 500;
+        long endTime = 1800;
+
+        KWValueAnimation alphaAnim;
+        KWValueAnimation xAnim;
+        KWValueAnimation yAnim;
+        KWValueAnimation scaleAnim;
+
+        KWAnimation fingerAnimation = new KWAnimation(spriteHand);
+        xAnim = fingerAnimation.addValueAnimation(KWValueType.X);
+        yAnim = fingerAnimation.addValueAnimation(KWValueType.Y);
+        xAnim.addKeyframe(206, startTime + 200, null);
+        yAnim.addKeyframe(388, startTime + 200, null);
+        xAnim.addKeyframe(441, startTime + 1200, accelerateDecelerateInterpolator);
+        yAnim.addKeyframe(388, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = fingerAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime, null);
+        alphaAnim.addKeyframe(1, endTime, null);
+        alphaAnim.addKeyframe(0, endTime + 500, accelerateInterpolator);
+
+        KWAnimation arrowAnimation = new KWAnimation(spriteArrow);
+        alphaAnim = arrowAnimation.addValueAnimation(KWValueType.Alpha);
+        xAnim = arrowAnimation.addValueAnimation(KWValueType.X);
+        alphaAnim.addKeyframe(0, startTime + 400, null);
+        xAnim.addKeyframe(156, startTime + 400, null);
+        alphaAnim.addKeyframe(1, startTime + 1300, accelerateDecelerateInterpolator);
+        xAnim.addKeyframe(232, startTime + 1300, accelerateDecelerateInterpolator);
+        alphaAnim.addKeyframe(0, endTime + 350, accelerateInterpolator);
+
+        KWAnimation favIconSelected2Animation = new KWAnimation(spriteAppIconFavSelected2);
+        xAnim = favIconSelected2Animation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(-238, startTime + 200, null);
+        xAnim.addKeyframe(0, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = favIconSelected2Animation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime + 100, decelerateInterpolator);
+        alphaAnim.addKeyframe(1, endTime - 100, null);
+        alphaAnim.addKeyframe(0, endTime + 400, decelerateInterpolator);
+
+        animationGroupAddFav.addAnimation(fingerAnimation);
+        animationGroupAddFav.addAnimation(arrowAnimation);
+        animationGroupAddFav.addAnimation(favIconSelected2Animation);
+
+        animationGroupAddFav.setAnimationGroupListener(new KWAnimationGroupListener()
+        {
+            @Override
+            public void onAnimationGroupStarted(KWAnimationGroup group)
+            {
+                spriteRoot.clearTransform(true);
+                spriteRoot.alpha = 1;
+                spriteArrow.alpha = 0;
+                spriteHand.alpha = 0;
+                spriteHandShadow.alpha = 0;
+                spriteAllApps.alpha = 1;
+                spriteFavApps.alpha = 1;
+                spriteAppIconAll1.alpha = 0;
+                spriteAppIconFav1.alpha = 1;
+                spriteAppIconFavSelected1.alpha = 0;
+                spriteAppIconFav2.alpha = 0;
+                spriteAppIconFavSelected2.alpha = 0;
+                spriteAppIconFav3.alpha = 1;
+                spriteAppIconFavSelected3.alpha = 0;
+                spriteDeleteHighlight.alpha = 0;
+                spriteDeleteX.alpha = 1;
+
+                spriteArrow.y = 388;
+                spriteArrow.pivotX = 1;
+                spriteArrow.pivotY = 0.5f;
+                spriteArrow.scaleX = -0.8f;
+                spriteArrow.scaleY = 0.8f;
+
+                spriteHand.pivotX = 18.0f / spriteHand.width;
+                spriteHand.pivotY = 21.0f / spriteHand.height;
+
+                spriteHandShadow.pivotX = 54.0f / spriteHandShadow.width;
+                spriteHandShadow.pivotY = 53.0f / spriteHandShadow.height;
+
+                spriteAllApps.x = 60;
+                spriteAllApps.y = (SCREEN_HEIGHT - spriteAllApps.height) / 2;
+                spriteAppIconAll1.x = 110;
+                spriteAppIconAll1.y = 97;
+
+                spriteFavApps.x = SCREEN_WIDTH - spriteFavApps.width - 50;
+                spriteFavApps.y = (SCREEN_HEIGHT - spriteFavApps.height) / 2;
+                spriteAppIconFav1.x = 0;
+                spriteAppIconFav1.y = 0;
+                spriteAppIconFavSelected1.x = 0;
+                spriteAppIconFavSelected1.y = 0;
+
+                spriteAppIconFav2.x = 0;
+                spriteAppIconFav2.y = 96;
+                spriteAppIconFavSelected2.x = 0;
+                spriteAppIconFavSelected2.y = 96;
+
+                spriteAppIconFav3.x = 0;
+                spriteAppIconFav3.y = 286;
+                spriteAppIconFavSelected3.x = 0;
+                spriteAppIconFavSelected3.y = 286;
+
+                spriteDeleteHighlight.pivotX = 0.5f;
+                spriteDeleteHighlight.pivotY = 0.5f;
+                spriteDeleteHighlight.x = spriteAllApps.width / 2;
+                spriteDeleteHighlight.y = spriteAllApps.height / 2;
+
+                spriteDeleteX.pivotX = 0.5f;
+                spriteDeleteX.pivotY = 0.5f;
+                spriteDeleteX.x = 0;
+                spriteDeleteX.y = 0;
+            }
+
+            @Override
+            public void onAnimationGroupFinished(KWAnimationGroup group)
+            {
+                if (listener != null)
+                {
+                    listener.OnAnimationFinished(EditFavsTutorialAnimationView.this);
+                }
+            }
+        });
+    }
+
+    /*****************************************
+     * 
+     * setupMoveFavAnimation()
+     * 
+     *****************************************/
+
+    private void setupMoveFavAnimation()
+    {
+        long startTime = 500;
+        long endTime = 2000;
+
+        KWValueAnimation alphaAnim;
+        KWValueAnimation xAnim;
+        KWValueAnimation yAnim;
+        KWValueAnimation scaleAnim;
+
+        KWAnimation fingerAnimation = new KWAnimation(spriteHand);
+        xAnim = fingerAnimation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(441, startTime + 200, null);
+        xAnim.addKeyframe(411, startTime + 700, accelerateDecelerateInterpolator);
+        xAnim.addKeyframe(441, startTime + 1200, accelerateDecelerateInterpolator);
+        yAnim = fingerAnimation.addValueAnimation(KWValueType.Y);
+        yAnim.addKeyframe(292, startTime + 200, null);
+        yAnim.addKeyframe(578, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = fingerAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime, null);
+        alphaAnim.addKeyframe(1, endTime, null);
+        alphaAnim.addKeyframe(0, endTime + 500, accelerateInterpolator);
+
+        KWAnimation arrowAnimation = new KWAnimation(spriteArrow);
+        yAnim = arrowAnimation.addValueAnimation(KWValueType.Y);
+        yAnim.addKeyframe(300, startTime + 400, null);
+        yAnim.addKeyframe(420, startTime + 1300, accelerateDecelerateInterpolator);
+        alphaAnim = arrowAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, startTime + 400, null);
+        alphaAnim.addKeyframe(1, startTime + 1300, accelerateDecelerateInterpolator);
+        alphaAnim.addKeyframe(0, endTime + 350, accelerateInterpolator);
+
+        KWAnimation favIconSelected1Animation = new KWAnimation(spriteAppIconFavSelected1);
+        xAnim = favIconSelected1Animation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(0, startTime + 200, null);
+        xAnim.addKeyframe(-30, startTime + 700, accelerateDecelerateInterpolator);
+        xAnim.addKeyframe(0, startTime + 1200, accelerateDecelerateInterpolator);
+
+        yAnim = favIconSelected1Animation.addValueAnimation(KWValueType.Y);
+        yAnim.addKeyframe(0, startTime + 200, null);
+        yAnim.addKeyframe(286, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = favIconSelected1Animation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime + 100, decelerateInterpolator);
+        alphaAnim.addKeyframe(1, endTime - 100, null);
+        alphaAnim.addKeyframe(0, endTime + 400, decelerateInterpolator);
+
+        KWAnimation favIcon3Animation = new KWAnimation(spriteAppIconFav3);
+        xAnim = favIcon3Animation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(0, startTime + 900, null);
+        xAnim.addKeyframe(+30, startTime + 1050, accelerateDecelerateInterpolator);
+        xAnim.addKeyframe(0, startTime + 1200, accelerateDecelerateInterpolator);
+
+        yAnim = favIcon3Animation.addValueAnimation(KWValueType.Y);
+        yAnim.addKeyframe(286, startTime + 900, null);
+        yAnim.addKeyframe(0, startTime + 1200, accelerateDecelerateInterpolator);
+
+        alphaAnim = favIcon3Animation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 100, null);
+        alphaAnim.addKeyframe(1, startTime + 100, decelerateInterpolator);
+        alphaAnim.addKeyframe(1, endTime - 100, null);
+        alphaAnim.addKeyframe(0, endTime + 400, decelerateInterpolator);
+
+        animationGroupMoveFav.addAnimation(fingerAnimation);
+        animationGroupMoveFav.addAnimation(arrowAnimation);
+        animationGroupMoveFav.addAnimation(favIconSelected1Animation);
+        animationGroupMoveFav.addAnimation(favIcon3Animation);
+
+        animationGroupMoveFav.setAnimationGroupListener(new KWAnimationGroupListener()
+        {
+            @Override
+            public void onAnimationGroupStarted(KWAnimationGroup group)
+            {
+                spriteRoot.clearTransform(true);
+                spriteRoot.alpha = 1;
+                spriteArrow.alpha = 0;
+                spriteHand.alpha = 0;
+                spriteHandShadow.alpha = 0;
+                spriteAllApps.alpha = 1;
+                spriteFavApps.alpha = 1;
+                spriteAppIconAll1.alpha = 1;
+                spriteAppIconFav1.alpha = 0;
+                spriteAppIconFavSelected1.alpha = 0;
+                spriteAppIconFav2.alpha = 1;
+                spriteAppIconFavSelected2.alpha = 0;
+                spriteAppIconFav3.alpha = 0;
+                spriteAppIconFavSelected3.alpha = 0;
+                spriteDeleteHighlight.alpha = 0;
+                spriteDeleteX.alpha = 1;
+
+                spriteArrow.x = 350;
+                spriteArrow.pivotX = 0.5f;
+                spriteArrow.pivotY = 0.5f;
+                spriteArrow.scaleX = 1.0f;
+                spriteArrow.scaleY = 0.8f;
+                spriteArrow.rotation = -90;
+
+                spriteHand.pivotX = 18.0f / spriteHand.width;
+                spriteHand.pivotY = 21.0f / spriteHand.height;
+
+                spriteHandShadow.pivotX = 54.0f / spriteHandShadow.width;
+                spriteHandShadow.pivotY = 53.0f / spriteHandShadow.height;
+
+                spriteAllApps.x = 60;
+                spriteAllApps.y = (SCREEN_HEIGHT - spriteAllApps.height) / 2;
+                spriteAppIconAll1.x = 110;
+                spriteAppIconAll1.y = 97;
+
+                spriteFavApps.x = SCREEN_WIDTH - spriteFavApps.width - 50;
+                spriteFavApps.y = (SCREEN_HEIGHT - spriteFavApps.height) / 2;
+                spriteAppIconFav1.x = 0;
+                spriteAppIconFav1.y = 0;
+                spriteAppIconFavSelected1.x = 0;
+                spriteAppIconFavSelected1.y = 0;
+
+                spriteAppIconFav2.x = 0;
+                spriteAppIconFav2.y = 96;
+                spriteAppIconFavSelected2.x = 0;
+                spriteAppIconFavSelected2.y = 96;
+
+                spriteAppIconFav3.x = 0;
+                spriteAppIconFav3.y = 286;
+                spriteAppIconFavSelected3.x = 0;
+                spriteAppIconFavSelected3.y = 286;
+
+                spriteDeleteHighlight.pivotX = 0.5f;
+                spriteDeleteHighlight.pivotY = 0.5f;
+                spriteDeleteHighlight.x = spriteAllApps.width / 2;
+                spriteDeleteHighlight.y = spriteAllApps.height / 2;
+
+                spriteDeleteX.pivotX = 0.5f;
+                spriteDeleteX.pivotY = 0.5f;
+                spriteDeleteX.x = 0;
+                spriteDeleteX.y = 0;
+            }
+
+            @Override
+            public void onAnimationGroupFinished(KWAnimationGroup group)
+            {
+                if (listener != null)
+                {
+                    listener.OnAnimationFinished(EditFavsTutorialAnimationView.this);
+                }
+            }
+        });
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/MenuTutorialAnimationView.java b/FairphoneHome/src/org/fairphone/oobe/animation/MenuTutorialAnimationView.java
new file mode 100644
index 0000000..ee86401
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/MenuTutorialAnimationView.java
@@ -0,0 +1,382 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.utils.KWAnimation;
+import org.fairphone.oobe.utils.KWAnimation.KWValueAnimation;
+import org.fairphone.oobe.utils.KWAnimation.KWValueType;
+import org.fairphone.oobe.utils.KWAnimationGroup;
+import org.fairphone.oobe.utils.KWAnimationGroup.KWAnimationGroupListener;
+import org.fairphone.oobe.utils.KWAnimationManager;
+import org.fairphone.oobe.utils.KWSprite;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+public class MenuTutorialAnimationView extends FrameLayout
+{
+
+    public interface MenuTutorialAnimationViewListener
+    {
+        public void OnAnimationFinished(MenuTutorialAnimationView view);
+    }
+
+    private static final int SCREEN_WIDTH = 540;
+    private static final int SCREEN_HEIGHT = 960;
+
+    KWSprite spriteRoot;
+
+    KWSprite spriteArrow;
+    KWSprite spriteHand;
+    KWSprite spriteHandShadow;
+    KWSprite spriteMenu;
+    KWSprite spriteAppIcon;
+    KWSprite spriteAppIconSelected;
+
+    Paint spritePaint;
+
+    KWAnimationGroup animationGroupSwipe;
+    KWAnimationGroup animationGroupSelectApp;
+    KWAnimationManager animationManager;
+
+    private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
+    private AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
+    private AccelerateDecelerateInterpolator accelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
+    long prevFrame = 0;
+
+    MenuTutorialAnimationViewListener listener;
+
+    public MenuTutorialAnimationView(Context context)
+    {
+        super(context);
+        init();
+    }
+
+    public MenuTutorialAnimationView(Context context, AttributeSet attrs)
+    {
+        super(context, attrs);
+        init();
+    }
+
+    public MenuTutorialAnimationView(Context context, AttributeSet attrs, int defStyle)
+    {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    void setMenuTutorialAnimationViewListener(MenuTutorialAnimationViewListener listener)
+    {
+        this.listener = listener;
+    }
+
+    private void init()
+    {
+        if (getBackground() == null)
+        {
+            setBackgroundColor(0x00000000);
+        }
+
+        spritePaint = new Paint();
+        spritePaint.setColor(0xffffffff);
+
+        spriteRoot = new KWSprite();
+        spriteArrow = new KWSprite();
+        spriteHand = new KWSprite();
+        spriteHandShadow = new KWSprite();
+        spriteMenu = new KWSprite();
+        spriteAppIcon = new KWSprite();
+        spriteAppIconSelected = new KWSprite();
+
+        spriteArrow.drawable = getResources().getDrawable(R.drawable.oobe_arrow_big);
+        spriteArrow.applySizeFromDrawable();
+        spriteHand.drawable = getResources().getDrawable(R.drawable.oobe_hand);
+        spriteHand.applySizeFromDrawable();
+        spriteHandShadow.drawable = getResources().getDrawable(R.drawable.oobe_hand_shadow);
+        spriteHandShadow.applySizeFromDrawable();
+        spriteMenu.drawable = getResources().getDrawable(R.drawable.oobe_menu);
+        spriteMenu.applySizeFromDrawable();
+        spriteAppIcon.drawable = getResources().getDrawable(R.drawable.oobe_app_icon);
+        spriteAppIcon.applySizeFromDrawable();
+        spriteAppIconSelected.drawable = getResources().getDrawable(R.drawable.oobe_icon_select);
+        spriteAppIconSelected.applySizeFromDrawable();
+
+        spriteRoot.addChild(spriteArrow);
+        spriteRoot.addChild(spriteHand);
+        spriteRoot.addChild(spriteHandShadow);
+        spriteRoot.addChild(spriteMenu);
+        spriteMenu.addChild(spriteAppIcon);
+        spriteMenu.addChild(spriteAppIconSelected);
+
+        spriteRoot.alpha = 0;
+
+        spriteAppIconSelected.alpha = 0;
+
+        // Animation setup
+
+        animationManager = new KWAnimationManager();
+        animationGroupSwipe = new KWAnimationGroup(animationManager);
+        animationGroupSelectApp = new KWAnimationGroup(animationManager);
+
+        setupSwipeAnimation();
+        setupAppOpenAnimation();
+    }
+
+    public void playSwipeAnimation()
+    {
+        animationGroupSwipe.start();
+    }
+
+    public void playAppOpenAnimation()
+    {
+        animationGroupSelectApp.start();
+    }
+
+    public void stopAnimations()
+    {
+        animationGroupSwipe.stop();
+        animationGroupSelectApp.stop();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
+    {
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas)
+    {
+        spriteRoot.resetMatrix();
+        spriteArrow.draw(canvas, spritePaint);
+        spriteMenu.draw(canvas, spritePaint);
+        spriteAppIcon.draw(canvas, spritePaint);
+        spriteAppIconSelected.draw(canvas, spritePaint);
+        spriteHandShadow.draw(canvas, spritePaint);
+        spriteHand.draw(canvas, spritePaint);
+        animationManager.update();
+        postInvalidate();
+    }
+
+    private void setupSwipeAnimation()
+    {
+        KWAnimation rootSwipeAnimation = new KWAnimation(spriteRoot);
+        KWValueAnimation alphaAnim = rootSwipeAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(1, 1700, null);
+        alphaAnim.addKeyframe(0, 2000, accelerateInterpolator);
+
+        KWAnimation fingerSwipeAnimation = new KWAnimation(spriteHand);
+        KWValueAnimation xAnim = fingerSwipeAnimation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(SCREEN_WIDTH, 350, null);
+        xAnim.addKeyframe(SCREEN_WIDTH - 200, 700, decelerateInterpolator);
+        xAnim.addKeyframe(SCREEN_WIDTH - 200, 1700, null);
+
+        KWAnimation arrowSwipeAnimation = new KWAnimation(spriteArrow);
+        xAnim = arrowSwipeAnimation.addValueAnimation(KWValueType.X);
+        xAnim.addKeyframe(SCREEN_WIDTH, 0, null);
+        xAnim.addKeyframe(SCREEN_WIDTH - 220, 500, decelerateInterpolator);
+
+        KWAnimation menuSwipeAnimation = new KWAnimation(spriteMenu);
+        KWValueAnimation scaleAnim = menuSwipeAnimation.addValueAnimation(KWValueType.Scale);
+        scaleAnim.addKeyframe(0.8f, 600, null);
+        scaleAnim.addKeyframe(1.0f, 800, decelerateInterpolator);
+        alphaAnim = menuSwipeAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 600, null);
+        alphaAnim.addKeyframe(1.0f, 750, decelerateInterpolator);
+
+        animationGroupSwipe.addAnimation(fingerSwipeAnimation);
+        animationGroupSwipe.addAnimation(arrowSwipeAnimation);
+        animationGroupSwipe.addAnimation(rootSwipeAnimation);
+        animationGroupSwipe.addAnimation(menuSwipeAnimation);
+
+        animationGroupSwipe.setAnimationGroupListener(new KWAnimationGroupListener()
+        {
+            @Override
+            public void onAnimationGroupStarted(KWAnimationGroup group)
+            {
+                spriteRoot.clearTransform(true);
+                spriteRoot.alpha = 0;
+                spriteArrow.alpha = 1;
+                spriteHand.alpha = 1;
+                spriteHandShadow.alpha = 0;
+                spriteMenu.alpha = 1;
+                spriteAppIcon.alpha = 1;
+                spriteAppIconSelected.alpha = 0;
+
+                spriteHand.y = SCREEN_HEIGHT / 2;
+                spriteArrow.y = SCREEN_HEIGHT / 2;
+                spriteArrow.pivotY = 0.5f;
+                spriteMenu.y = SCREEN_HEIGHT / 2;
+                spriteMenu.x = SCREEN_WIDTH - 100;
+                spriteMenu.pivotX = 1.0f;
+                spriteMenu.pivotY = 0.5f;
+                spriteAppIcon.x = -spriteMenu.pivotX * spriteMenu.width + 53;
+                spriteAppIcon.y = -spriteMenu.pivotY * spriteMenu.height + 68;
+                spriteAppIconSelected.x = -spriteMenu.pivotX * spriteMenu.width + 53;
+                spriteAppIconSelected.y = -spriteMenu.pivotY * spriteMenu.height + 68;
+            }
+
+            @Override
+            public void onAnimationGroupFinished(KWAnimationGroup group)
+            {
+                if (listener != null)
+                {
+                    listener.OnAnimationFinished(MenuTutorialAnimationView.this);
+                }
+            }
+        });
+    }
+
+    private void setupAppOpenAnimation()
+    {
+        KWValueAnimation alphaAnim;
+        KWValueAnimation xAnim;
+        KWValueAnimation yAnim;
+        KWValueAnimation scaleAnim;
+
+        KWAnimation rootAnimation = new KWAnimation(spriteRoot);
+        alphaAnim = rootAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 0, null);
+        alphaAnim.addKeyframe(1, 300, decelerateInterpolator);
+        alphaAnim.addKeyframe(1, 1950, null);
+        alphaAnim.addKeyframe(0, 2250, decelerateInterpolator);
+
+        KWAnimation handAnimation = new KWAnimation(spriteHand);
+        xAnim = handAnimation.addValueAnimation(KWValueType.X);
+        yAnim = handAnimation.addValueAnimation(KWValueType.Y);
+        scaleAnim = handAnimation.addValueAnimation(KWValueType.Scale);
+        xAnim.addKeyframe(SCREEN_WIDTH - 200, 300, null);
+        yAnim.addKeyframe(SCREEN_HEIGHT / 2, 300, null);
+
+        xAnim.addKeyframe(286, 700, accelerateDecelerateInterpolator);
+        yAnim.addKeyframe(350, 700, accelerateDecelerateInterpolator);
+
+        xAnim.addKeyframe(286, 1300, accelerateDecelerateInterpolator);
+        yAnim.addKeyframe(350, 1300, accelerateDecelerateInterpolator);
+        scaleAnim.addKeyframe(1.0f, 1300, null);
+
+        scaleAnim.addKeyframe(1.3f, 1700, accelerateDecelerateInterpolator);
+        xAnim.addKeyframe(311, 1700, accelerateDecelerateInterpolator);
+        yAnim.addKeyframe(323, 1700, accelerateDecelerateInterpolator);
+
+        KWAnimation handShadowAnimation = new KWAnimation(spriteHandShadow);
+        alphaAnim = handShadowAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0, 1300, null);
+        alphaAnim.addKeyframe(1.0f, 1700, accelerateInterpolator);
+
+        KWAnimation appIconAnimation = new KWAnimation(spriteAppIcon);
+        alphaAnim = appIconAnimation.addValueAnimation(KWValueType.Alpha);
+        scaleAnim = appIconAnimation.addValueAnimation(KWValueType.Scale);
+        alphaAnim.addKeyframe(1.0f, 0, null);
+        scaleAnim.addKeyframe(1.0f, 0, null);
+        alphaAnim.addKeyframe(1.0f, 650, null);
+        scaleAnim.addKeyframe(1.0f, 650, null);
+        alphaAnim.addKeyframe(0, 650, null);
+        scaleAnim.addKeyframe(0.9f, 650, null);
+        alphaAnim.addKeyframe(1.0f, 830, decelerateInterpolator);
+        scaleAnim.addKeyframe(1.4f, 1000, decelerateInterpolator);
+        scaleAnim.addKeyframe(1.4f, 1550, null);
+        alphaAnim.addKeyframe(1.0f, 1550, null);
+        scaleAnim.addKeyframe(3.5f, 1900, decelerateInterpolator);
+        alphaAnim.addKeyframe(0.0f, 1850, accelerateInterpolator);
+
+        KWAnimation appIconSelectedAnimation = new KWAnimation(spriteAppIconSelected);
+        alphaAnim = appIconSelectedAnimation.addValueAnimation(KWValueType.Alpha);
+        scaleAnim = appIconSelectedAnimation.addValueAnimation(KWValueType.Scale);
+        alphaAnim.addKeyframe(0, 650, null);
+        scaleAnim.addKeyframe(0.9f, 650, null);
+        alphaAnim.addKeyframe(1.0f, 730, accelerateInterpolator);
+        scaleAnim.addKeyframe(1.0f, 750, decelerateInterpolator);
+
+        KWAnimation menuAnimation = new KWAnimation(spriteMenu);
+        alphaAnim = menuAnimation.addValueAnimation(KWValueType.Alpha);
+        alphaAnim.addKeyframe(0.0f, 200, accelerateInterpolator);
+        alphaAnim.addKeyframe(1, 400, null);
+        alphaAnim.addKeyframe(1, 1900, null);
+        alphaAnim.addKeyframe(0.0f, 2000, decelerateInterpolator);
+
+        animationGroupSelectApp.addAnimation(rootAnimation);
+        animationGroupSelectApp.addAnimation(handAnimation);
+        animationGroupSelectApp.addAnimation(handShadowAnimation);
+        animationGroupSelectApp.addAnimation(appIconAnimation);
+        animationGroupSelectApp.addAnimation(appIconSelectedAnimation);
+        animationGroupSelectApp.addAnimation(menuAnimation);
+
+        animationGroupSelectApp.setAnimationGroupListener(new KWAnimationGroupListener()
+        {
+            @Override
+            public void onAnimationGroupStarted(KWAnimationGroup group)
+            {
+                spriteRoot.clearTransform(true);
+                spriteRoot.alpha = 0;
+                spriteArrow.alpha = 0;
+                spriteHand.alpha = 1;
+                spriteHandShadow.alpha = 0;
+                spriteMenu.alpha = 1;
+                spriteAppIcon.alpha = 1;
+                spriteAppIconSelected.alpha = 0;
+
+                spriteHand.x = SCREEN_WIDTH - 200;
+                spriteHand.y = SCREEN_HEIGHT / 2;
+
+                spriteHand.pivotX = 18.0f / spriteHand.width;
+                spriteHand.pivotY = 21.0f / spriteHand.height;
+
+                spriteHandShadow.x = 286;
+                spriteHandShadow.y = 350;
+                spriteHandShadow.pivotX = 54.0f / spriteHandShadow.width;
+                spriteHandShadow.pivotY = 53.0f / spriteHandShadow.height;
+
+                spriteArrow.x = SCREEN_WIDTH - 220;
+                spriteArrow.y = SCREEN_HEIGHT / 2;
+
+                spriteArrow.pivotX = 0.0f;
+                spriteArrow.pivotY = 0.5f;
+
+                spriteMenu.y = SCREEN_HEIGHT / 2;
+                spriteMenu.x = SCREEN_WIDTH - 100;
+
+                spriteMenu.pivotX = 1.0f;
+                spriteMenu.pivotY = 0.5f;
+
+                spriteAppIcon.pivotX = 0.5f;
+                spriteAppIcon.pivotY = 0.5f;
+                spriteAppIcon.x = -spriteMenu.pivotX * spriteMenu.width + 53 + spriteAppIcon.pivotX * spriteAppIcon.width;
+                spriteAppIcon.y = -spriteMenu.pivotY * spriteMenu.height + 68 + spriteAppIcon.pivotX * spriteAppIcon.width;
+
+                spriteAppIconSelected.pivotX = 0.5f;
+                spriteAppIconSelected.pivotY = 0.5f;
+                spriteAppIconSelected.x = -spriteMenu.pivotX * spriteMenu.width + 53 + spriteAppIconSelected.pivotX * spriteAppIconSelected.width;
+                spriteAppIconSelected.y = -spriteMenu.pivotY * spriteMenu.height + 68 + spriteAppIconSelected.pivotX * spriteAppIconSelected.width;
+            }
+
+            @Override
+            public void onAnimationGroupFinished(KWAnimationGroup group)
+            {
+                if (listener != null)
+                {
+                    listener.OnAnimationFinished(MenuTutorialAnimationView.this);
+                }
+            }
+        });
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper.java b/FairphoneHome/src/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper.java
new file mode 100644
index 0000000..0eca4b8
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/MoveFavTutorialAnimationHelper.java
@@ -0,0 +1,214 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.animation.EditFavsTutorialAnimationView.EditFavsTutorialAnimationViewListener;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+
+public class MoveFavTutorialAnimationHelper implements TutorialAnimationHelper, EditFavsTutorialAnimationViewListener
+{
+    EditFavsTutorialAnimationView animView;
+    View rootView;
+    Context context;
+    TutorialAnimationHelperListener listener;
+    TutorialState curState = TutorialState.IdleInvisible;
+    
+    
+    @Override
+    public View setup(Context context)
+    {
+        this.context = context;
+        
+        rootView = LayoutInflater.from(context).inflate(R.layout.tutorial_edit_fav_move_layout, null);
+        animView = (EditFavsTutorialAnimationView)rootView.findViewById(R.id.editFavMoveAnimationView);
+        
+        animView.playMoveFavAnimation();
+        animView.stopAnimations();
+        
+        animView.setEditFavsTutorialAnimationViewListener(this);
+        
+        return rootView;
+    }
+
+
+    @Override
+    public void setTutorialAnimationHelperListener(TutorialAnimationHelperListener listener)
+    {
+        this.listener = listener;
+    }
+
+    int curAnimationId = 0;
+    TutorialViewAnimationListener curStateAnimationListener;
+    
+    private TutorialViewAnimationListener getCurStateAnimationListener()
+    {
+        return curStateAnimationListener;
+    }
+    
+    @Override
+    public boolean playIntro()
+    {
+        if(curState==TutorialState.Intro)
+            return false;
+        startAnimationState(TutorialState.Intro,null);
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_intro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.setVisibility(View.VISIBLE);
+        rootView.startAnimation(fadeAnim);
+        return true;
+    }
+
+
+    @Override
+    public boolean playMain()
+    {
+        if(curState!=TutorialState.IdleVisible)
+            return false;
+        
+        startAnimationState(TutorialState.Main,null);
+        animView.playMoveFavAnimation();
+        return true;
+    }
+    
+    @Override
+    public boolean playOutro()
+    {
+        if(curState==TutorialState.Outro)
+            return false;
+        
+        startAnimationState(TutorialState.Outro, new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                rootView.setVisibility(View.GONE);
+            }
+        });
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_outro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.startAnimation(fadeAnim);
+        
+        return true;
+    }
+    
+    private void startState(TutorialState newState)
+    {
+        curState = newState;
+        curAnimationId++;
+    }
+    
+    private void startAnimationState(TutorialState newState, Runnable runnable)
+    {
+        curState = newState;
+        curAnimationId++;
+        curStateAnimationListener = new TutorialViewAnimationListener(curAnimationId,runnable);
+    }
+
+    private void onAnimationFinished(int animationId)
+    {
+        if(animationId!=curAnimationId)
+        {
+            return;
+        }
+        
+        if(curState==TutorialState.Intro)
+        {
+            startState(TutorialState.IdleVisible);
+            playMain();
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Intro);
+            }
+        }
+        else if(curState==TutorialState.Main)
+        {
+            startState(TutorialState.IdleVisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Main);
+            }
+            playMain();
+        }
+        else if(curState==TutorialState.Outro)
+        {
+            startState(TutorialState.IdleInvisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Outro);
+            }
+        }
+    }
+    
+
+    private class TutorialViewAnimationListener implements AnimationListener
+    {
+        int startNum = 0;
+        int finishNum=0;
+        int animationId;
+        Runnable runnable;
+        
+        public TutorialViewAnimationListener(int animationid, Runnable runnable)
+        {
+            this.animationId = animationid;
+            this.runnable = runnable;
+        }
+        
+        int getAnimationId()
+        {
+            return animationId;
+        }
+        
+        @Override
+        public void onAnimationStart(Animation animation)
+        {
+            startNum++;
+        }
+
+        @Override
+        public void onAnimationEnd(Animation animation)
+        {
+            finishNum++;
+            if(finishNum==startNum)
+            {
+                if(runnable!=null)
+                {
+                    runnable.run();
+                }
+                onAnimationFinished(animationId);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation)
+        {
+        }
+    }
+
+
+    @Override
+    public void OnAnimationFinished(EditFavsTutorialAnimationView view)
+    {
+        animView.playMoveFavAnimation();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper.java b/FairphoneHome/src/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper.java
new file mode 100644
index 0000000..42d6e44
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/OpenAppTutorialAnimationHelper.java
@@ -0,0 +1,214 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.animation.MenuTutorialAnimationView.MenuTutorialAnimationViewListener;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+
+public class OpenAppTutorialAnimationHelper implements TutorialAnimationHelper, MenuTutorialAnimationViewListener
+{
+    MenuTutorialAnimationView animView;
+    View rootView;
+    Context context;
+    TutorialAnimationHelperListener listener;
+    TutorialState curState = TutorialState.IdleInvisible;
+    
+    
+    @Override
+    public View setup(Context context)
+    {
+        this.context = context;
+        
+        rootView = LayoutInflater.from(context).inflate(R.layout.tutorial_open_app_layout, null);
+        animView = (MenuTutorialAnimationView)rootView.findViewById(R.id.openAppAnimationView);
+        
+        animView.playAppOpenAnimation();
+        animView.stopAnimations();
+        
+        animView.setMenuTutorialAnimationViewListener(this);
+        
+        return rootView;
+    }
+
+
+    @Override
+    public void setTutorialAnimationHelperListener(TutorialAnimationHelperListener listener)
+    {
+        this.listener = listener;
+    }
+
+    int curAnimationId = 0;
+    TutorialViewAnimationListener curStateAnimationListener;
+    
+    private TutorialViewAnimationListener getCurStateAnimationListener()
+    {
+        return curStateAnimationListener;
+    }
+    
+    @Override
+    public boolean playIntro()
+    {
+        if(curState==TutorialState.Intro)
+            return false;
+        startAnimationState(TutorialState.Intro,null);
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_intro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.setVisibility(View.VISIBLE);
+        rootView.startAnimation(fadeAnim);
+        return true;
+    }
+
+
+    @Override
+    public boolean playMain()
+    {
+        if(curState!=TutorialState.IdleVisible)
+            return false;
+        
+        startAnimationState(TutorialState.Main,null);
+        animView.playAppOpenAnimation();
+        return true;
+    }
+    
+    @Override
+    public boolean playOutro()
+    {
+        if(curState==TutorialState.Outro)
+            return false;
+        
+        startAnimationState(TutorialState.Outro, new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                rootView.setVisibility(View.GONE);
+            }
+        });
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_outro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.startAnimation(fadeAnim);
+        
+        return true;
+    }
+    
+    private void startState(TutorialState newState)
+    {
+        curState = newState;
+        curAnimationId++;
+    }
+    
+    private void startAnimationState(TutorialState newState, Runnable runnable)
+    {
+        curState = newState;
+        curAnimationId++;
+        curStateAnimationListener = new TutorialViewAnimationListener(curAnimationId,runnable);
+    }
+
+    private void onAnimationFinished(int animationId)
+    {
+        if(animationId!=curAnimationId)
+        {
+            return;
+        }
+        
+        if(curState==TutorialState.Intro)
+        {
+            startState(TutorialState.IdleVisible);
+            playMain();
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Intro);
+            }
+        }
+        else if(curState==TutorialState.Main)
+        {
+            startState(TutorialState.IdleVisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Main);
+            }
+            playMain();
+        }
+        else if(curState==TutorialState.Outro)
+        {
+            startState(TutorialState.IdleInvisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Outro);
+            }
+        }
+    }
+    
+
+    private class TutorialViewAnimationListener implements AnimationListener
+    {
+        int startNum = 0;
+        int finishNum=0;
+        int animationId;
+        Runnable runnable;
+        
+        public TutorialViewAnimationListener(int animationid, Runnable runnable)
+        {
+            this.animationId = animationid;
+            this.runnable = runnable;
+        }
+        
+        int getAnimationId()
+        {
+            return animationId;
+        }
+        
+        @Override
+        public void onAnimationStart(Animation animation)
+        {
+            startNum++;
+        }
+
+        @Override
+        public void onAnimationEnd(Animation animation)
+        {
+            finishNum++;
+            if(finishNum==startNum)
+            {
+                if(runnable!=null)
+                {
+                    runnable.run();
+                }
+                onAnimationFinished(animationId);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation)
+        {
+        }
+    }
+
+
+    @Override
+    public void OnAnimationFinished(MenuTutorialAnimationView view)
+    {
+        animView.playAppOpenAnimation();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper.java b/FairphoneHome/src/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper.java
new file mode 100644
index 0000000..47ff6e7
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/RemoveFavTutorialAnimationHelper.java
@@ -0,0 +1,214 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import org.fairphone.launcher.R;
+import org.fairphone.oobe.animation.EditFavsTutorialAnimationView.EditFavsTutorialAnimationViewListener;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+
+public class RemoveFavTutorialAnimationHelper implements TutorialAnimationHelper, EditFavsTutorialAnimationViewListener
+{
+    EditFavsTutorialAnimationView animView;
+    View rootView;
+    Context context;
+    TutorialAnimationHelperListener listener;
+    TutorialState curState = TutorialState.IdleInvisible;
+    
+    
+    @Override
+    public View setup(Context context)
+    {
+        this.context = context;
+        
+        rootView = LayoutInflater.from(context).inflate(R.layout.tutorial_edit_fav_remove_layout, null);
+        animView = (EditFavsTutorialAnimationView)rootView.findViewById(R.id.editFavRemoveAnimationView);
+        
+        animView.playRemoveFavAnimation();
+        animView.stopAnimations();
+        
+        animView.setEditFavsTutorialAnimationViewListener(this);
+        
+        return rootView;
+    }
+
+
+    @Override
+    public void setTutorialAnimationHelperListener(TutorialAnimationHelperListener listener)
+    {
+        this.listener = listener;
+    }
+
+    int curAnimationId = 0;
+    TutorialViewAnimationListener curStateAnimationListener;
+    
+    private TutorialViewAnimationListener getCurStateAnimationListener()
+    {
+        return curStateAnimationListener;
+    }
+    
+    @Override
+    public boolean playIntro()
+    {
+        if(curState==TutorialState.Intro)
+            return false;
+        startAnimationState(TutorialState.Intro,null);
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_intro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.setVisibility(View.VISIBLE);
+        rootView.startAnimation(fadeAnim);
+        return true;
+    }
+
+
+    @Override
+    public boolean playMain()
+    {
+        if(curState!=TutorialState.IdleVisible)
+            return false;
+        
+        startAnimationState(TutorialState.Main,null);
+        animView.playRemoveFavAnimation();
+        return true;
+    }
+    
+    @Override
+    public boolean playOutro()
+    {
+        if(curState==TutorialState.Outro)
+            return false;
+        
+        startAnimationState(TutorialState.Outro, new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                rootView.setVisibility(View.GONE);
+            }
+        });
+        Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.tutorial_outro);
+        fadeAnim.setAnimationListener(getCurStateAnimationListener());
+        rootView.startAnimation(fadeAnim);
+        
+        return true;
+    }
+    
+    private void startState(TutorialState newState)
+    {
+        curState = newState;
+        curAnimationId++;
+    }
+    
+    private void startAnimationState(TutorialState newState, Runnable runnable)
+    {
+        curState = newState;
+        curAnimationId++;
+        curStateAnimationListener = new TutorialViewAnimationListener(curAnimationId,runnable);
+    }
+
+    private void onAnimationFinished(int animationId)
+    {
+        if(animationId!=curAnimationId)
+        {
+            return;
+        }
+        
+        if(curState==TutorialState.Intro)
+        {
+            startState(TutorialState.IdleVisible);
+            playMain();
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Intro);
+            }
+        }
+        else if(curState==TutorialState.Main)
+        {
+            startState(TutorialState.IdleVisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Main);
+            }
+            playMain();
+        }
+        else if(curState==TutorialState.Outro)
+        {
+            startState(TutorialState.IdleInvisible);
+            if(listener!=null)
+            {
+                listener.onTutorialAnimationFinished(this, TutorialState.Outro);
+            }
+        }
+    }
+    
+
+    private class TutorialViewAnimationListener implements AnimationListener
+    {
+        int startNum = 0;
+        int finishNum=0;
+        int animationId;
+        Runnable runnable;
+        
+        public TutorialViewAnimationListener(int animationid, Runnable runnable)
+        {
+            this.animationId = animationid;
+            this.runnable = runnable;
+        }
+        
+        int getAnimationId()
+        {
+            return animationId;
+        }
+        
+        @Override
+        public void onAnimationStart(Animation animation)
+        {
+            startNum++;
+        }
+
+        @Override
+        public void onAnimationEnd(Animation animation)
+        {
+            finishNum++;
+            if(finishNum==startNum)
+            {
+                if(runnable!=null)
+                {
+                    runnable.run();
+                }
+                onAnimationFinished(animationId);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation)
+        {
+        }
+    }
+
+
+    @Override
+    public void OnAnimationFinished(EditFavsTutorialAnimationView view)
+    {
+        animView.playRemoveFavAnimation();
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/animation/TutorialAnimationHelper.java b/FairphoneHome/src/org/fairphone/oobe/animation/TutorialAnimationHelper.java
new file mode 100644
index 0000000..b9cabcd
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/animation/TutorialAnimationHelper.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.fairphone.oobe.animation;
+
+import android.content.Context;
+import android.view.View;
+
+public interface TutorialAnimationHelper
+{
+    public enum TutorialState
+    {
+        IdleInvisible,IdleVisible,Intro,Outro,Main
+    };
+    
+    public interface TutorialAnimationHelperListener
+    {
+        public void onTutorialAnimationFinished(TutorialAnimationHelper helper, TutorialState state);
+    }
+    
+    public View setup(Context context);
+    public void setTutorialAnimationHelperListener(TutorialAnimationHelperListener listener);
+    public boolean playIntro();
+    public boolean playMain();
+    public boolean playOutro();
+}
\ No newline at end of file
diff --git a/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimation.java b/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimation.java
new file mode 100644
index 0000000..a0170ff
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimation.java
@@ -0,0 +1,300 @@
+/*
+ * 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 org.fairphone.oobe.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+
+
+import android.view.animation.Interpolator;
+
+public class KWAnimation
+{  
+    public interface KWAnimationListener
+    {
+        public void onAnimationStart(KWAnimation animation);
+        public void onAnimationUpdate(KWAnimation animation, float curAnimationProgress);
+        public void onAnimationEnd(KWAnimation animation);
+    }
+    
+    public enum KWValueType
+    {
+        X,Y,Rotation,Scale,ScaleX,ScaleY,PivotX,PivotY, Alpha, Width,Height
+    };
+    
+
+    public static class KWValueAnimation
+    {
+        KWValueType type;
+        ArrayList<KWKeyframe> keyframes = new ArrayList<KWAnimation.KWKeyframe>();
+        long duration = 0;
+        
+        KWValueAnimation(KWValueType type)
+        {
+            this.type = type;
+        }
+        
+        public KWValueAnimation addKeyframe(float value, long time, Interpolator interpolator)
+        {
+            if(time>duration)
+            {
+                duration = time;
+            }
+            keyframes.add(new KWKeyframe(time,value,interpolator));
+            Collections.sort(keyframes,new KWKeyComparator());
+            return this;
+        }
+        
+        public float getValueAt(long time)
+        {
+            if(keyframes.isEmpty())
+            {
+                return 0;
+            }
+            
+            int key=0;
+            
+            for(int i=0;i<keyframes.size();i++)
+            {
+                key = i;
+                if(keyframes.get(i).time>time)
+                {
+                    break;
+                }
+            }
+            
+            KWKeyframe keyA = keyframes.get(key);
+            KWKeyframe keyB = keyframes.get(key);
+            
+            if(key>0)
+            {
+                keyA = keyframes.get(key-1);
+            }
+            
+            float ratio = KWMathUtils.getLongRatio(keyA.time, keyB.time, time);
+            if(keyB.interpolator!=null)
+            {
+                ratio = keyB.interpolator.getInterpolation(ratio);
+            }
+            float val = keyA.value+(keyB.value-keyA.value)*ratio;
+            return val;
+        }
+        
+        public void applyValueAt(long time, KWSprite sprite)
+        {
+            switch(type)
+            {
+                case X:
+                {
+                    sprite.x = getValueAt(time);
+                }
+                break;
+                
+                case Y:
+                {
+                    sprite.y = getValueAt(time);
+                }
+                break;
+                
+                case Rotation:
+                {
+                    sprite.rotation = getValueAt(time);
+                }
+                break;
+                
+                case Scale:
+                {
+                    sprite.scaleX = getValueAt(time);
+                    sprite.scaleY = sprite.scaleX;
+                }
+                break;
+                
+                case ScaleX:
+                {
+                    sprite.scaleX = getValueAt(time);
+                }
+                break;
+                
+                case ScaleY:
+                {
+                    sprite.scaleY = getValueAt(time);
+                }
+                break;
+                
+                case PivotX:
+                {
+                    sprite.pivotX = getValueAt(time);
+                }
+                break;
+                
+                case PivotY:
+                {
+                    sprite.pivotY = getValueAt(time);
+                }
+                break;
+                
+                case Alpha:
+                {
+                    sprite.alpha = getValueAt(time);
+                }
+                break;
+                
+                case Width:
+                {
+                    sprite.width = getValueAt(time);
+                }
+                break;
+                
+                case Height:
+                {
+                    sprite.height = getValueAt(time);
+                }
+                break;
+            }
+        }
+    }
+    
+    private static class KWKeyComparator implements Comparator<KWKeyframe>
+    {
+        @Override
+        public int compare(KWKeyframe lhs, KWKeyframe rhs)
+        {
+            long dif = (lhs.time-rhs.time);
+            return dif>0?1:dif<0?-1:0;
+        }
+    }
+    
+    private static class KWKeyframe
+    {
+        long  time;
+        float value;
+        Interpolator interpolator;
+        private KWKeyframe(long time, float value, Interpolator interpolator)
+        {
+            this.time = time;
+            this.value = value;
+            this.interpolator = interpolator;
+        }
+    }
+    
+    private long curAnimTime=0;
+    private boolean isRunning = false;
+    private LinkedList<KWValueAnimation> animations = new LinkedList<KWAnimation.KWValueAnimation>();
+    private KWAnimationListener listener;
+    private KWSprite sprite;
+    
+    
+    public KWAnimation(KWSprite animatedSprite)
+    {
+        curAnimTime=0;
+        this.sprite = animatedSprite;
+    }
+    
+    public KWValueAnimation addValueAnimation(KWValueType type)
+    {
+        KWValueAnimation anim = new KWValueAnimation(type);
+        animations.add(anim);
+        return anim;
+    }
+    
+    public void setAnimationListener(KWAnimationListener listener)
+    {
+        this.listener = listener;
+    }
+    
+    public KWSprite getSprite()
+    {
+        return sprite;
+    }
+    
+    public boolean isRunning()
+    {
+        return isRunning;
+    }
+    
+    public long getCurAnimTime()
+    {
+        return curAnimTime;
+    }
+    
+    public void start()
+    {
+        isRunning = true;
+        curAnimTime=0;
+        
+        if(listener!=null)
+        {
+            listener.onAnimationStart(this);
+        }
+    }
+    
+    public void pause()
+    {
+        isRunning = false;
+    }
+    
+    public void unpause()
+    {
+        isRunning = true;
+    }
+    
+    public void stop()
+    {
+        reset();
+        isRunning = false;
+    }
+    
+    public void reset()
+    {
+        curAnimTime = 0;
+    }
+    
+    public void update(long dt)
+    {
+        if(isRunning)
+        {
+            curAnimTime+=dt;
+            long maxDuration = 0;
+            for(KWValueAnimation anim: animations)
+            {
+                anim.applyValueAt(curAnimTime, sprite);
+                if(anim.duration>maxDuration)
+                {
+                    maxDuration = anim.duration;
+                }
+            }
+            if(curAnimTime>=maxDuration)
+            {
+                curAnimTime = maxDuration;
+                isRunning = false;
+                if(listener!=null)
+                {
+                    listener.onAnimationEnd(this);
+                }
+            }
+            else
+            {
+                if(listener!=null)
+                {
+                    float curAnimationProgress = KWMathUtils.getLongRatio(0, maxDuration, curAnimTime);
+                    listener.onAnimationUpdate(this, curAnimationProgress);
+                }
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimationGroup.java b/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimationGroup.java
new file mode 100644
index 0000000..6aeec39
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimationGroup.java
@@ -0,0 +1,116 @@
+/*
+ * 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 org.fairphone.oobe.utils;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import org.fairphone.oobe.utils.KWAnimation.KWAnimationListener;
+
+import android.util.Log;
+
+public class KWAnimationGroup implements KWAnimationListener
+{
+    public interface KWAnimationGroupListener
+    {
+        public void onAnimationGroupStarted(KWAnimationGroup group);
+        public void onAnimationGroupFinished(KWAnimationGroup group);
+        
+    }
+    
+    int startedAnimNum=0;
+    KWAnimationManager manager;
+    LinkedList<KWAnimation> animations = new LinkedList<KWAnimation>();
+    KWAnimationGroupListener listener=null;
+    
+    public KWAnimationGroup(KWAnimationManager manager)
+    {
+        this.manager = manager;
+        startedAnimNum = 0;
+    }
+    
+    public void setAnimationGroupListener(KWAnimationGroupListener listener)
+    {
+        this.listener = listener;
+    }
+    
+    public void addAnimation(KWAnimation anim)
+    {
+        animations.add(anim);
+        anim.setAnimationListener(this);
+        manager.addAnimation(anim);
+    }
+    
+    public void removeAnimation(KWAnimation anim)
+    {
+        animations.remove(anim);
+        anim.setAnimationListener(null);
+    }
+    
+    public Collection<KWAnimation> getAnimations()
+    {
+        return animations;
+    }
+    
+    public void start()
+    {
+        startedAnimNum=0;
+        for(KWAnimation anim: animations)
+        {
+            anim.start();
+            anim.update(0);
+        }
+        
+        if(listener!=null)
+        {
+            listener.onAnimationGroupStarted(this);
+        }
+    }
+    
+    public void stop()
+    {
+        for(KWAnimation anim: animations)
+        {
+            anim.stop();
+        }
+    }
+    
+    @Override
+    public void onAnimationStart(KWAnimation animation)
+    {
+        startedAnimNum++;
+    }
+
+    @Override
+    public void onAnimationUpdate(KWAnimation animation, float curAnimationProgress)
+    {
+    }
+
+    @Override
+    public void onAnimationEnd(KWAnimation animation)
+    {
+        startedAnimNum--;
+        
+        if(startedAnimNum<=0)
+        {
+            if(listener!=null)
+            {
+                listener.onAnimationGroupFinished(this);
+            }
+        }
+    }
+    
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimationManager.java b/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimationManager.java
new file mode 100644
index 0000000..18ecdbf
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/utils/KWAnimationManager.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.fairphone.oobe.utils;
+
+import java.util.LinkedList;
+
+public class KWAnimationManager
+{
+
+    LinkedList<KWAnimation> animations = new LinkedList<KWAnimation>();
+    long prevFrameTime=0;
+    
+    
+    public KWAnimationManager()
+    {
+        prevFrameTime = System.currentTimeMillis();
+    }
+    
+    public void addAnimation(KWAnimation animation)
+    {
+        animations.add(animation);
+    }
+    
+    public void removeAnimation(KWAnimation animation)
+    {
+        animations.remove(animation);
+    }
+    
+    public boolean update()//note: must be called regularly
+    {
+        long curTime = System.currentTimeMillis();
+        long dt = curTime-prevFrameTime;
+        prevFrameTime = curTime;
+        
+        if(dt>100)
+        {
+            dt=1000/30;
+        }
+        
+        boolean hasAnimsRunning = false;
+        for(KWAnimation anim: animations)
+        {
+            if(anim.isRunning())
+            {
+                hasAnimsRunning = true;
+                anim.update(dt);
+            }
+        }
+        return hasAnimsRunning;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/utils/KWFontsManager.java b/FairphoneHome/src/org/fairphone/oobe/utils/KWFontsManager.java
new file mode 100644
index 0000000..fa31153
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/utils/KWFontsManager.java
@@ -0,0 +1,111 @@
+/*
+ * 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 org.fairphone.oobe.utils;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+/**
+ * Fonts manager class.
+ * 
+ * Implemented as a singleton.
+ * 
+ * Prepares the fonts used within the application.
+ */
+public class KWFontsManager
+{
+    private static final String HANNAH_REGULAR = "fonts/YWFT-Hannah-Regular.ttf";
+
+    private static KWFontsManager fontsManager = null;
+
+    private static Typeface hannahRegular;
+
+    /**
+     * Get the singleton instance of the fonts manager.
+     */
+    public static KWFontsManager get()
+    {
+        if (fontsManager == null)
+        {
+            fontsManager = new KWFontsManager();
+        }
+
+        return fontsManager;
+    }
+
+    /**
+     * Setup the fonts used within the application.
+     */
+    public static void prepareFonts(Context context, ViewGroup root)
+    {
+        hannahRegular = Typeface.createFromAsset(context.getAssets(), HANNAH_REGULAR);
+
+        setFontInTag(root, "fontHannah", hannahRegular);
+    }
+
+    public static void setFontInTag(ViewGroup root, String tag, Typeface font)
+    {
+        ArrayList<View> regularViews = getViewsByTag(root, tag);
+        for (View view : regularViews)
+        {
+            if (view.getClass() == TextView.class)
+            {
+                TextView text = (TextView) view;
+                text.setTypeface(font);
+            }
+            else if (view.getClass() == Button.class)
+            {
+                Button text = (Button) view;
+                text.setTypeface(font);
+            }
+            else if (view.getClass() == ToggleButton.class)
+            {
+                ToggleButton text = (ToggleButton) view;
+                text.setTypeface(font);
+            }
+            else if (view.getClass() == EditText.class)
+            {
+                EditText text = (EditText) view;
+                text.setTypeface(font);
+            }
+        }
+    }
+
+    private static ArrayList<View> getViewsByTag(ViewGroup root, String tag)
+    {
+        ArrayList<View> views = new ArrayList<View>();
+        final int childCount = root.getChildCount();
+        for (int i = 0; i < childCount; i++)
+        {
+            final View child = root.getChildAt(i);
+            if (child instanceof ViewGroup) // recursive search
+                views.addAll(getViewsByTag((ViewGroup) child, tag));
+
+            final Object tagObj = child.getTag();
+            if (tagObj != null && tagObj.equals(tag))
+                views.add(child);
+        }
+        return views;
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/utils/KWMathUtils.java b/FairphoneHome/src/org/fairphone/oobe/utils/KWMathUtils.java
new file mode 100644
index 0000000..3dab1cd
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/utils/KWMathUtils.java
@@ -0,0 +1,120 @@
+/*
+ * 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 org.fairphone.oobe.utils;
+
+/**
+ * FIXME - Needs cleanup and comments!
+ */
+public class KWMathUtils
+{
+    public static double degToRad(double angleDeg)
+    {
+        return angleDeg/180*Math.PI;
+    }
+    
+    public static double radToDeg(double angleRad)
+    {
+        return angleRad/Math.PI*180;
+    }
+
+    public static float speedUp(float ratio)
+    {
+        return ratio * ratio;
+    }
+
+    public static float slowDown(float ratio)
+    {
+        return 1.0f - ((ratio - 1.0f) * (ratio - 1.0f));
+    }
+
+    public static float smoothStep(float ratio)
+    {
+        return ratio * ratio * (3 - 2 * ratio);
+    }
+
+    public static float blend(float start, float end, float ratio)
+    {
+        return start + (end - start) * ratio;
+    }
+    
+    public static float clamp(float start,float end, float value)
+    {
+        if(value<start)
+            return start;
+        if(value>end)
+            return end;
+        return value;
+    }
+    
+    public static float getLongRatio(long startTime, long endTime, long time)
+    {
+        long duration = endTime - startTime;
+        if (duration > 0)
+        {
+            float ratio = (float) (time-startTime) / (float) duration;
+            if(ratio<=0)
+                return 0;
+            if(ratio>=1.0f)
+                return 1.0f;
+            return ratio;
+        }
+        return 1.0f;
+    }
+    
+    public static float getFloatRatio(float min, float max, float value)
+    {
+        float dif = max - min;
+        if (dif > 0)
+        {
+            float ratio = (float) (value-min) / (float) dif;
+            if(ratio<=0)
+                return 0;
+            if(ratio>=1.0f)
+                return 1.0f;
+            return ratio;
+        }
+        return 1.0f;
+    }
+
+    public static float getSpeedFromPositionAndTimeI(float start, float end, long duration)
+    {
+        return (end-start)/((float)duration/1000.0f);
+    }
+    
+    public static float getSpeedFromPositionAndTimeF(float start, float end, float duration)
+    {
+        return (end-start)/duration;
+    }
+    
+    public static double getDistance(float x1, float y1, float x2, float y2)
+    {
+        float xd=x1-x2;
+        float yd=y1-y2;
+        
+        return Math.sqrt(xd*xd+yd*yd);
+    }
+    
+    public static long calcTimeFromVelocityAndLength(float velocity, float length)
+    {
+        return (long) (Math.abs(2 * length / velocity) * 1000);
+    }
+
+    public static float calcLengthFromTimeAndVelocity(long time, float velocity)
+    {
+        float timef = (float) time / 1000.0f;
+        return (timef * velocity / 2.0f);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/oobe/utils/KWSprite.java b/FairphoneHome/src/org/fairphone/oobe/utils/KWSprite.java
new file mode 100644
index 0000000..5e46933
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/oobe/utils/KWSprite.java
@@ -0,0 +1,184 @@
+/*
+ * 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 org.fairphone.oobe.utils;
+
+import java.util.LinkedList;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+
+public class KWSprite
+{
+    public float x = 0, y = 0;
+    public float rotation = 0;
+    public float width = 100, height = 100;
+    public float pivotX = 0.5f, pivotY = 0.5f;
+    public float scaleX = 1, scaleY = 1;
+    public float alpha = 1;
+    public Drawable drawable = null;
+    
+    private KWSprite parent=null;
+    private LinkedList<KWSprite> children = new LinkedList<KWSprite>();
+    boolean matrixUpdated = false;
+    Matrix matrix = new Matrix();
+    float finalAlpha;
+    
+    public KWSprite()
+    {
+        x = 0;
+        y = 0;
+        rotation = 0;
+        width = 100;
+        height = 100;
+        pivotX = 0.0f;
+        pivotY = 0.0f;
+        scaleX = 1;
+        scaleY = 1;
+        alpha = 1;
+        drawable = null;
+        matrixUpdated = false;
+    }
+    
+    public void clearTransform(boolean clearChildrenTransform)
+    {
+        x=0;
+        y=0;
+        rotation=0;
+        pivotX=0;
+        pivotX=y;
+        scaleX = 1;
+        scaleY = 1;
+        alpha=1;
+        if(clearChildrenTransform)
+        {
+            for(KWSprite sprite: children)
+            {
+                sprite.clearTransform(true);
+            }
+        }
+    }
+    
+    public KWSprite(KWSprite src)
+    {
+        copy(src);
+    }
+    
+    public void copy(KWSprite src)
+    {
+        x=src.x;
+        y=src.y;
+        rotation=src.rotation;
+        width=src.width;
+        height=src.height;
+        pivotX=src.pivotX;
+        pivotY=src.pivotY;
+        scaleX=src.scaleX;
+        scaleY=src.scaleY;
+        alpha=src.alpha;
+        drawable=src.drawable;
+        matrixUpdated = false;
+    }
+    
+
+    public void applySizeFromDrawable()
+    {
+        if(drawable!=null)
+        {
+            int widthI = drawable.getIntrinsicWidth();
+            int heightI = drawable.getIntrinsicHeight();
+            if(widthI>=0)
+            {
+                width = widthI;
+            }
+            if(heightI>=0)
+            {
+                height = heightI;
+            }
+        }
+    }
+    
+    
+    public void addChild(KWSprite sprite)
+    {
+        if(sprite.parent!=null)
+        {
+            sprite.parent.removeChild(sprite);
+        }
+        
+        children.add(sprite);
+        sprite.parent = this;
+    }
+    
+    public void removeChild(KWSprite sprite)
+    {
+        if(sprite.parent==this)
+        {
+            sprite.parent = null;
+            children.remove(sprite);
+        }
+    }
+    
+    public void resetMatrix()//only needed to call in parent
+    {
+        matrixUpdated = false;
+        for(KWSprite sprite: children)
+        {
+            sprite.resetMatrix();
+        }
+    }
+    
+    public void updateMatrix()
+    {
+        if(!matrixUpdated)
+        {
+            finalAlpha = alpha;
+            matrixUpdated = true;
+            matrix.reset();
+            matrix.postScale(scaleX, scaleY);
+            matrix.postRotate(rotation);
+            matrix.postTranslate(x, y);
+            if(parent!=null)
+            {
+                parent.updateMatrix();
+                matrix.postConcat(parent.matrix);
+                finalAlpha*=parent.finalAlpha;
+            }
+        }
+    }
+    
+    public void draw(Canvas canvas, Paint paint)
+    {
+        updateMatrix();
+        if (drawable != null)
+        {
+            if(finalAlpha>0)
+            {
+                canvas.save(Canvas.MATRIX_SAVE_FLAG);
+                canvas.concat(matrix);
+                int left = (int) (-width * pivotX);
+                int right = (int) (width * (1 - pivotX));
+                int top = (int) (-height * pivotY);
+                int bottom = (int) (height * (1 - pivotY));
+                drawable.setBounds(left, top, right, bottom);
+                drawable.setAlpha((int) (255 * finalAlpha));
+                drawable.draw(canvas);
+                canvas.restore();
+            }
+        }
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/settings/SettingsActivity.java b/FairphoneHome/src/org/fairphone/settings/SettingsActivity.java
new file mode 100644
index 0000000..4803e70
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/settings/SettingsActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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 org.fairphone.settings;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class SettingsActivity extends Activity {
+	@Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        
+         // Display the fragment as the main content.
+        getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, new SettingsFragment())
+                .commit();
+    }
+	
+	@Override
+    public void onBackPressed()
+    {
+        
+        Intent intent = getIntent();
+        setResult(RESULT_OK, intent);
+        
+        finish();
+    }
+	
+}
diff --git a/FairphoneHome/src/org/fairphone/settings/SettingsFragment.java b/FairphoneHome/src/org/fairphone/settings/SettingsFragment.java
new file mode 100644
index 0000000..c41a360
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/settings/SettingsFragment.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.fairphone.settings;
+
+import org.fairphone.launcher.R;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+
+public class SettingsFragment extends PreferenceFragment {
+	@Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        PreferenceManager preferenceManager = getPreferenceManager();
+        
+        preferenceManager.setSharedPreferencesName("HomeSettings");
+        preferenceManager.setSharedPreferencesMode(Context.MODE_WORLD_WRITEABLE);
+        
+        // Load the preferences from an XML resource
+        addPreferencesFromResource(R.xml.launcher_settings);
+    }
+}
diff --git a/FairphoneHome/src/org/fairphone/widgets/appswitcher/AppDiscoverer.java b/FairphoneHome/src/org/fairphone/widgets/appswitcher/AppDiscoverer.java
new file mode 100644
index 0000000..b2b0b2b
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/widgets/appswitcher/AppDiscoverer.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.fairphone.widgets.appswitcher;
+
+
+public class AppDiscoverer
+{
+	private static final ApplicationRunInfoManager _instance = new ApplicationRunInfoManager();
+	
+	public static ApplicationRunInfoManager getInstance(){
+		return _instance;
+	}
+}
diff --git a/FairphoneHome/src/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager.java b/FairphoneHome/src/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager.java
new file mode 100644
index 0000000..25001f6
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/widgets/appswitcher/ApplicationRunInfoManager.java
@@ -0,0 +1,271 @@
+/*
+ * 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 org.fairphone.widgets.appswitcher;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import android.content.ComponentName;
+import android.util.Log;
+
+/**
+ * This class processes the count for the most used apps and the most recent.
+ * 
+ * @author Tiago Costa
+ *
+ */
+public class ApplicationRunInfoManager {
+
+	public static final int RECENT_APP_MAX_COUNT_LIMIT = 5;
+	public static final int MOST_APP_MAX_COUNT_LIMIT = 6;
+	public static final int MINIMAL_COUNT = 2;
+	private static final String TAG = null;
+
+	private LimitedQueue<ApplicationRunInformation> _mostUsed;
+	private LimitedQueue<ApplicationRunInformation> _recentApps;
+	private Map<String, ApplicationRunInformation> _appRunInfos;
+	
+	private int _mostUsedAppsLimit;
+	private int _recentAppsLimit;
+
+	public ApplicationRunInfoManager() {
+		
+		setUpLimits(MOST_APP_MAX_COUNT_LIMIT, RECENT_APP_MAX_COUNT_LIMIT);
+		
+		_appRunInfos = new HashMap<String, ApplicationRunInformation>();
+	}
+	
+	public void setUpLimits(int maxMostUsed, int maxRecentApps){
+		_mostUsedAppsLimit = maxMostUsed;
+		_recentAppsLimit = maxRecentApps;
+		
+		// refactor the limits
+		setUpNewLimits();
+	}
+
+	private void setUpNewLimits() {
+		_mostUsed    = new LimitedQueue<ApplicationRunInformation>(_mostUsedAppsLimit);
+		_recentApps  = new LimitedQueue<ApplicationRunInformation>(_recentAppsLimit);
+		
+		// update the information
+		if(_appRunInfos != null){
+			updateAppInformation();
+		}
+	}
+	
+	public void loadNewRunInformation(List<ApplicationRunInformation> allApps){
+		// clear the current state
+		resetState();
+		
+		// add application to the bag
+		for(ApplicationRunInformation appInfo : allApps){
+			_appRunInfos.put(ApplicationRunInformation.serializeComponentName(appInfo.getComponentName()), appInfo);
+		}
+		
+		// update the information
+		updateAppInformation();
+	}
+	
+	public void resetState() {
+		_mostUsed.clear();
+		_recentApps.clear();
+		_appRunInfos.clear();
+	}
+
+	public void applicationStarted(ApplicationRunInformation appInfo){
+		// obtain the cached app information
+		ApplicationRunInformation cachedApp = _appRunInfos.get(ApplicationRunInformation.serializeComponentName(appInfo.getComponentName()));
+		// if does not exist, create one
+		if(cachedApp == null){
+			_appRunInfos.put(ApplicationRunInformation.serializeComponentName(appInfo.getComponentName()), appInfo);
+			
+			cachedApp = appInfo;
+			
+			cachedApp.resetCount();
+		}
+		
+		// increment count
+		cachedApp.incrementCount();
+		
+		Log.d( TAG, "Logging application : " + cachedApp.getComponentName() + " : " + cachedApp.getCount() );
+		
+		// set the current time for the last execution
+		cachedApp.setLastExecution(appInfo.getLastExecution());
+		
+		// update the information
+		updateAppInformation();
+	}
+	
+	public void applicationRemoved(ComponentName component){
+		// remove data
+		ApplicationRunInformation appInfo = _appRunInfos.remove(ApplicationRunInformation.serializeComponentName(component));
+		
+		// if does not exist return
+		if(appInfo == null){
+			return;
+		}
+		
+		// if its being used in the lists refactor the lists
+		if(_mostUsed.contains(appInfo) || _recentApps.contains(appInfo)){
+			updateAppInformation();
+		}
+	}
+
+	private void updateAppInformation() {
+		_mostUsed.clear();
+		_recentApps.clear();
+		
+		// most used
+		// calculate the most used
+		for(ApplicationRunInformation current : _appRunInfos.values()){
+			
+			if(current.getCount() >= MINIMAL_COUNT){
+				addByCount(current, _mostUsed, _mostUsedAppsLimit);
+			}
+		}
+		
+		printMostUsedApps();
+		
+		// calculate the most recent
+		for(ApplicationRunInformation current : _appRunInfos.values()){
+			if(!_mostUsed.contains(current)){
+				addByDate(current, _recentApps, _recentAppsLimit);
+			}
+		}
+		
+		printRecentApps();
+	}
+
+	private void printRecentApps() {
+		for(ApplicationRunInformation current : _recentApps){
+			Log.d(TAG, "Fairphone RecentApps - " + current);
+		}
+	}
+
+	private void printMostUsedApps() {
+		for(ApplicationRunInformation current : _mostUsed){
+			Log.d(TAG, "Fairphone MostUsed - " + current);
+		}
+	}
+
+	private static void addByDate(ApplicationRunInformation info, LimitedQueue<ApplicationRunInformation> queue, int limit) {
+		for (int insertIdx = 0; insertIdx < queue.size(); insertIdx++)
+        {
+            if (queue.get(insertIdx).getLastExecution().before(info.getLastExecution()))
+            {
+            	queue.add(insertIdx, info);
+
+                return;
+            }
+        }
+
+		if(queue.size() < limit){
+        	queue.addLast(info);
+        }
+	}
+
+	private static void addByCount(ApplicationRunInformation info, LimitedQueue<ApplicationRunInformation> queue, int limit)
+    {
+        for (int insertIdx = 0; insertIdx < queue.size(); insertIdx++)
+        {
+        	Log.d(TAG, "Fairphone - Contacting ... " + queue.get(insertIdx));
+        	if(info.getCount() > queue.get(insertIdx).getCount() ){
+        		Log.d(TAG, "FairPhone - Qs : " + queue.size() + " : Most Used : Adding " + info.getComponentName() + " to position " + insertIdx);
+        		queue.add(insertIdx, info);
+
+        		return;
+        	}
+        }
+
+        Log.d(TAG, "Fairphone - Qs : " + queue.size() + " : Most Used : Adding " + info.getComponentName() + " to first position ");
+        if(queue.size() < limit){
+        	queue.addLast(info);
+        }
+    }
+
+	private static class LimitedQueue<E> extends LinkedList<E> {
+
+		/**
+		 * 
+		 */
+		private static final long serialVersionUID = 8174761694444365605L;
+		private final int limit;
+
+		public LimitedQueue(int limit) {
+			this.limit = limit;
+		}
+
+		@Override
+		public void add(int idx, E o) {
+			super.add(idx, o);
+			
+			while (size() > limit) {
+				super.removeLast();
+			}
+		}
+		
+		@Override
+		public boolean add(E o) {
+			super.addLast(o);
+			while (size() > limit) {
+				super.removeLast();
+			}
+			return true;
+		}
+	}
+
+	public List<ApplicationRunInformation> getRecentApps() {
+		
+		
+		
+		Log.d(TAG, "Fairphone - Getting recent apps... " + _recentApps.size() );
+		return _recentApps;
+	}
+	
+	public List<ApplicationRunInformation> getMostUsedApps() {
+		Log.d(TAG, "Fairphone - Getting most Used apps... " + _mostUsed.size() );
+		
+		
+		
+		return _mostUsed;
+	}
+
+	public int getMostUsedAppsLimit() {
+		return _mostUsedAppsLimit;
+	}
+
+	public int getRecentAppsLimit() {
+		return _recentAppsLimit;
+	}
+
+	public List<ApplicationRunInformation> getAllAppRunInfo() {
+		return new ArrayList<ApplicationRunInformation>(_appRunInfos.values());
+	}
+	
+	public void setAllRunInfo(List<ApplicationRunInformation> allApps){
+		resetState();
+		
+		for(ApplicationRunInformation app : allApps){
+			_appRunInfos.put(ApplicationRunInformation.serializeComponentName(app.getComponentName()), app);
+		}
+		
+		updateAppInformation();
+	}
+
+}
diff --git a/FairphoneHome/src/org/fairphone/widgets/appswitcher/ApplicationRunInformation.java b/FairphoneHome/src/org/fairphone/widgets/appswitcher/ApplicationRunInformation.java
new file mode 100644
index 0000000..0b403b3
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/widgets/appswitcher/ApplicationRunInformation.java
@@ -0,0 +1,160 @@
+/*
+ * 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 org.fairphone.widgets.appswitcher;
+
+import java.util.Date;
+
+import android.content.ComponentName;
+
+/**
+ * Represents the run data for a specific application in the system.
+ * It contains data for fast access like the component name and the icon.
+ * All the info can still be obtained via the Application info.
+ * 
+ */
+public class ApplicationRunInformation
+{
+
+	private static final String COMPONENT_NAME_SEPARATOR = ";";
+	private ComponentName 	mComponentName;
+	private int 			mRunCount;
+    private Date			mLastExecution;
+    
+    /**
+     * Create a base count zero Application Run information.
+     * 
+     * @param component The ComponentName of the application
+     */
+    public ApplicationRunInformation(ComponentName component){
+    	this(component, 0);
+    }
+    
+    /**
+     * Create a application run information with a specific value for the count
+     * the count value must be zero or above. 
+     * 
+     * @param component The ComponentName of the application
+     * @param count the number of run times (used when starting)
+     */
+    public ApplicationRunInformation(ComponentName component, int count) {
+    	if(component == null){
+    		throw new IllegalArgumentException("Invalid value for ComponentName");
+    	}
+    	
+    	setComponentName(component);
+    	
+    	if(count < 0){
+    		throw new IllegalArgumentException("Run count cannot be negative");
+    	}
+    	
+    	mRunCount = count;
+	}
+
+	public int getCount(){
+    	return mRunCount;
+    }
+    
+    public void incrementCount(){
+    	mRunCount++;
+    }
+    
+    public void decrementCount(){
+    	if(mRunCount > 0){
+    		mRunCount--;
+    	}
+    }
+
+	public ComponentName getComponentName() {
+		return mComponentName;
+	}
+
+	private void setComponentName(ComponentName component) {
+		this.mComponentName = new ComponentName(component.getPackageName(), component.getClassName());
+	}
+
+	public Date getLastExecution() {
+		return mLastExecution;
+	}
+
+	public void setLastExecution(Date lastExecution) {
+		this.mLastExecution = lastExecution;
+	}
+	
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((mComponentName == null) ? 0 : mComponentName.hashCode());
+		result = prime * result
+				+ ((mLastExecution == null) ? 0 : mLastExecution.hashCode());
+		result = prime * result + mRunCount;
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		ApplicationRunInformation other = (ApplicationRunInformation) obj;
+		if (mComponentName == null) {
+			if (other.mComponentName != null)
+				return false;
+		} else if (!mComponentName.equals(other.mComponentName))
+			return false;
+		if (mLastExecution == null) {
+			if (other.mLastExecution != null)
+				return false;
+		} else if (!mLastExecution.equals(other.mLastExecution))
+			return false;
+		if (mRunCount != other.mRunCount)
+			return false;
+		return true;
+	}
+
+	public void resetCount() {
+		mRunCount = 0;
+	}
+	
+	/**
+	 * Serializes a component in order to be used has a map key
+	 * @param mComponentName component to serialize
+	 * @return the serialized component
+	 */
+	public static String serializeComponentName(ComponentName mComponentName) {
+		StringBuffer sb = new StringBuffer();
+    	
+    	sb.append(mComponentName.getPackageName()).append(COMPONENT_NAME_SEPARATOR).append(mComponentName.getClassName());
+    	
+		return sb.toString();
+	}
+	
+	/**
+	 * Transforms a string into a ComponentName
+	 * @param componentNameString serialized component
+	 * @return the ComponentName object
+	 */
+	public static ComponentName deserializeComponentName(String componentNameString) {
+		String[] strings = componentNameString.split(COMPONENT_NAME_SEPARATOR);
+    	
+		return strings.length == 2 ? new ComponentName(strings[0],strings[1]): null;
+	}
+
+}
diff --git a/FairphoneHome/src/org/fairphone/widgets/appswitcher/WidgetProvider.java b/FairphoneHome/src/org/fairphone/widgets/appswitcher/WidgetProvider.java
new file mode 100755
index 0000000..752b8a9
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/widgets/appswitcher/WidgetProvider.java
@@ -0,0 +1,306 @@
+/*
+ * 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 org.fairphone.widgets.appswitcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.fairphone.launcher.Launcher;
+import org.fairphone.launcher.R;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.RemoteViews;
+
+public class WidgetProvider extends AppWidgetProvider
+{
+    private static final String TAG = WidgetProvider.class.getSimpleName();
+    private static final boolean APP_SWITCHER_DEBUG_MODE = false;
+
+    @Override
+    public void onEnabled(Context context)
+    {
+        Log.d(TAG, "Fairphone - WidgetProvicer Context is " + context);
+    }
+
+    @Override
+    public void onDisabled(Context context)
+    {
+        // Called once the last instance of your widget is removed from the
+        // homescreen
+        super.onDisabled(context);
+    }
+
+    @Override
+    public void onDeleted(Context context, int[] appWidgetIds)
+    {
+        // Widget instance is removed from the homescreen
+        Log.d(TAG, "onDeleted - " + appWidgetIds);
+    }
+
+    @Override
+    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)
+    {
+        updateUI(context, appWidgetManager, appWidgetId);
+        // Obtain appropriate widget and update it.
+        // appWidgetManager.updateAppWidget(appWidgetId, new
+        // RemoteViews(context.getPackageName(), R.layout.widget));
+        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
+    }
+
+    private void updateUI(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
+    {
+        int code = 0;
+        // get the widgets
+        RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.fp_app_switcher);
+
+        code = setupButtonClickIntents(context, code, widget);
+
+        // clear the current data
+        widget.removeAllViews(R.id.lastUsedApps);
+        widget.removeAllViews(R.id.mostUsedApps);
+
+        // obtain the current data saved
+        ApplicationRunInfoManager instance = AppDiscoverer.getInstance();
+
+        List<ApplicationRunInformation> mostRecent = new ArrayList<ApplicationRunInformation>(instance.getRecentApps());
+        List<ApplicationRunInformation> mostUsed = new ArrayList<ApplicationRunInformation>(instance.getMostUsedApps());
+
+        Log.d("KW", "mostRecent lenght: " + mostRecent.size());
+        Log.d("KW", "mostUsed lenght: " + mostUsed.size());
+
+        toggleMostAndLastUsedViewsVisibility(widget, mostRecent, mostUsed);
+
+        // update the recent apps
+        code = updateLastUsedAppsList(context, code, widget, mostRecent);
+
+        // Process the most used apps
+        code = updateMostUsedAppsList(context, code, widget, mostUsed);
+
+        // update the widget data
+        appWidgetManager.updateAppWidget(appWidgetId, null);
+        appWidgetManager.updateAppWidget(appWidgetId, widget);
+    }
+
+    private int updateMostUsedAppsList(Context context, int code, RemoteViews widget, List<ApplicationRunInformation> mostUsed)
+    {
+        for (ApplicationRunInformation mostUsedInfo : mostUsed)
+        {
+            RemoteViews view = null;
+            try
+            {
+                view = getMostUsedView(context, mostUsedInfo, code);
+
+                if (view != null)
+                {
+                    widget.addView(R.id.mostUsedApps, view);
+                }
+            } catch (NameNotFoundException e)
+            {
+                // if no information is available log it and continue
+                Log.e(TAG, "Could not find the correct package", e);
+
+                continue;
+            }
+
+            // update the code
+            code++;
+        }
+        return code;
+    }
+
+    private int updateLastUsedAppsList(Context context, int code, RemoteViews widget, List<ApplicationRunInformation> mostRecent)
+    {
+        for (ApplicationRunInformation appRunInfo : mostRecent)
+        {
+            RemoteViews view = null;
+            try
+            {
+                view = getRecentView(context, appRunInfo, code);
+
+                if (view != null)
+                {
+                    widget.addView(R.id.lastUsedApps, view);
+                }
+            } catch (NameNotFoundException e)
+            {
+                // if no information is available log it and continue
+                Log.e(TAG, "Could not find the correct package", e);
+
+                continue;
+            }
+
+            // update the code
+            code++;
+        }
+        return code;
+    }
+
+    private void toggleMostAndLastUsedViewsVisibility(RemoteViews widget, List<ApplicationRunInformation> mostRecent, List<ApplicationRunInformation> mostUsed)
+    {
+        if (mostRecent.size() == 0 && mostUsed.size() == 0)
+        {
+            widget.setViewVisibility(R.id.lastUsedAppsOOBETitle, View.VISIBLE);
+            widget.setViewVisibility(R.id.mostUsedAppsOOBETitle, View.VISIBLE);
+            widget.setViewVisibility(R.id.mostUsedAppsOOBEDescription, View.VISIBLE);
+            widget.setViewVisibility(R.id.buttonReset, View.GONE);
+            widget.setViewVisibility(R.id.buttonResetDisabled, View.VISIBLE);
+            widget.setViewVisibility(R.id.lastUsedAppsTitle, View.GONE);
+            widget.setViewVisibility(R.id.mostUsedAppsTitle, View.GONE);
+
+        }
+        else
+        {
+            widget.setViewVisibility(R.id.lastUsedAppsOOBETitle, View.GONE);
+            widget.setViewVisibility(R.id.mostUsedAppsOOBETitle, View.GONE);
+            widget.setViewVisibility(R.id.mostUsedAppsOOBEDescription, View.GONE);
+            widget.setViewVisibility(R.id.buttonReset, View.VISIBLE);
+            widget.setViewVisibility(R.id.buttonResetDisabled, View.GONE);
+            widget.setViewVisibility(R.id.lastUsedAppsTitle, View.VISIBLE);
+            widget.setViewVisibility(R.id.mostUsedAppsTitle, View.VISIBLE);
+        }
+    }
+
+    private int setupButtonClickIntents(Context context, int code, RemoteViews widget)
+    {
+        // set up the all apps intent
+        Intent launchIntent = new Intent();
+        launchIntent.setAction(Launcher.APP_SWITCHER_ALL_APPS);
+
+        PendingIntent launchPendingIntent = PendingIntent.getBroadcast(context, code++, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+        widget.setOnClickPendingIntent(R.id.buttonLauncher, launchPendingIntent);
+
+        // set up the reset apps intent
+        Intent resetIntent = new Intent();
+        resetIntent.setAction(Launcher.APP_SWITCHER_RESET);
+        PendingIntent resetPendingIntent = PendingIntent.getBroadcast(context, code++, resetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+        widget.setOnClickPendingIntent(R.id.buttonReset, resetPendingIntent);
+        return code;
+    }
+
+    private RemoteViews getMostUsedView(Context context, ApplicationRunInformation info, int code) throws NameNotFoundException
+    {
+        // generate the mostUsed row
+        RemoteViews mostUsedRow = new RemoteViews(context.getPackageName(), R.layout.fp_most_used_item);
+        PackageManager pm = context.getPackageManager();
+
+        // get app icon and label
+        Drawable icon = pm.getActivityIcon(info.getComponentName());
+        Bitmap iconBitmap = ((BitmapDrawable) icon).getBitmap();
+        CharSequence appLabel = pm.getActivityInfo(info.getComponentName(), 0).loadLabel(pm);
+
+        // debug String with app count
+        String fullAppLabel = info.getCount() + "# " + appLabel;
+
+        mostUsedRow.setImageViewBitmap(android.R.id.content, iconBitmap);
+
+        mostUsedRow.setTextViewText(R.id.mostUsedButton, APP_SWITCHER_DEBUG_MODE ? fullAppLabel : appLabel);
+
+        Intent launchIntent = generateLaunchIntent(info, appLabel.toString());
+
+        PendingIntent clickRecentApps = PendingIntent.getBroadcast(context, code, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+        mostUsedRow.setOnClickPendingIntent(R.id.mostUsedButton, clickRecentApps);
+
+        return mostUsedRow;
+    }
+
+    private Intent generateLaunchIntent(ApplicationRunInformation info, String appLabel) throws NameNotFoundException
+    {
+        Intent i = new Intent();
+        i.setAction(Launcher.APP_SWITCHER_LAUNCH_APP);
+
+        Bundle extras = new Bundle();
+        extras.putString(Launcher.APP_NAME, appLabel);
+        extras.putString(Launcher.APP_PACKAGE, info.getComponentName().getPackageName());
+        extras.putString(Launcher.APP_CLASS_NAME, info.getComponentName().getClassName());
+
+        i.putExtras(extras);
+
+        return i;
+    }
+
+    private RemoteViews getRecentView(Context context, ApplicationRunInformation info, int code) throws NameNotFoundException
+    {
+        RemoteViews recentRow = new RemoteViews(context.getPackageName(), R.layout.fp_last_used_item);
+        PackageManager pm = context.getPackageManager();
+
+        // get application icon and label
+        Drawable icon = pm.getActivityIcon(info.getComponentName());
+        Bitmap iconBitmap = ((BitmapDrawable) icon).getBitmap();
+        CharSequence appLabel = pm.getActivityInfo(info.getComponentName(), 0).loadLabel(pm);
+
+        // debug String with app count
+        String fullAppLabel = info.getCount() + "# " + appLabel;
+
+        recentRow.setTextViewText(android.R.id.text1, APP_SWITCHER_DEBUG_MODE ? fullAppLabel : appLabel);
+        recentRow.setImageViewBitmap(android.R.id.background, iconBitmap);
+
+        // create the intent for this app
+        Intent launchIntent = generateLaunchIntent(info, appLabel.toString());
+
+        PendingIntent clickRecentApps = PendingIntent.getBroadcast(context, code, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+        recentRow.setOnClickPendingIntent(R.id.recentButton, clickRecentApps);
+
+        return recentRow;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
+     * android.appwidget.AppWidgetManager, int[])
+     * 
+     * OnUpdate ==============================================================
+     * context The Context in which this receiver is running. appWidgetManager A
+     * AppWidgetManager object you can call updateAppWidget(ComponentName,
+     * RemoteViews) on. appWidgetIds The appWidgetIds for which an update is
+     * needed. Note that this may be all of the AppWidget instances for this
+     * provider, or just a subset of them.
+     */
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
+    {
+        super.onUpdate(context, appWidgetManager, appWidgetIds);
+        // Called in response to the ACTION_APPWIDGET_UPDATE broadcast when this
+        // AppWidget provider
+        // is being asked to provide RemoteViews for a set of AppWidgets.
+        // Override this method to implement your own AppWidget functionality.
+
+        // iterate through every instance of this widget
+        // remember that it can have more than one widget of the same type.
+        for (int i = 0; i < appWidgetIds.length; i++)
+        { // See the dimensions and
+            System.out.println("Updating widget #" + i);
+            updateUI(context, appWidgetManager, appWidgetIds[i]);
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/FairphoneHome/src/org/fairphone/widgets/gapps/GoogleAppsInstallerWidget.java b/FairphoneHome/src/org/fairphone/widgets/gapps/GoogleAppsInstallerWidget.java
new file mode 100644
index 0000000..9b4a321
--- /dev/null
+++ b/FairphoneHome/src/org/fairphone/widgets/gapps/GoogleAppsInstallerWidget.java
@@ -0,0 +1,253 @@
+/*

+ * 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 org.fairphone.widgets.gapps;

+

+import org.fairphone.launcher.R;

+import org.fairphone.launcher.gappsinstaller.GappsInstallerHelper;

+

+import android.app.PendingIntent;

+import android.appwidget.AppWidgetManager;

+import android.appwidget.AppWidgetProvider;

+import android.content.Context;

+import android.content.Intent;

+import android.content.SharedPreferences;

+import android.os.Bundle;

+import android.util.Log;

+import android.view.View;

+import android.widget.RemoteViews;

+

+public class GoogleAppsInstallerWidget extends AppWidgetProvider

+{

+

+    private static final String TAG = GoogleAppsInstallerWidget.class.getSimpleName();

+

+    @Override

+    public void onEnabled(Context context)

+    {

+//        Log.d(TAG, "Fairphone - GoogleAppsInstaller Context is " + context);

+    }

+

+    @Override

+    public void onDisabled(Context context)

+    {

+        // Called once the last instance of your widget is removed from the

+        // homescreen

+        super.onDisabled(context);

+    }

+

+    @Override

+    public void onDeleted(Context context, int[] appWidgetIds)

+    {

+        // Widget instance is removed from the homescreen

+//        Log.d(TAG, "onDeleted - " + appWidgetIds);

+    }

+

+    @Override

+    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)

+    {

+        updateUI(context, appWidgetManager, appWidgetId);

+        // Obtain appropriate widget and update it.

+        // appWidgetManager.updateAppWidget(appWidgetId, new

+        // RemoteViews(context.getPackageName(), R.layout.widget));

+        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);

+    }

+

+    private int setupButtonClickIntents(Context context, int code, RemoteViews widget)

+    {

+        // set up Disclaimer

+        Intent disclaimerIntent = new Intent();

+        disclaimerIntent.setAction(GappsInstallerHelper.GAPPS_ACTION_DISCLAIMER);

+        PendingIntent disclaimerPendingIntent = PendingIntent.getBroadcast(context, code++, disclaimerIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.installButton, disclaimerPendingIntent);

+

+        // set up the start download Ok intent

+        Intent startDownloadOkIntent = new Intent();

+        startDownloadOkIntent.setAction(GappsInstallerHelper.GAPPS_ACTION_DOWNLOAD_CONFIGURATION_FILE);

+        PendingIntent startDownloadOkPendingIntent = PendingIntent.getBroadcast(context, code++, startDownloadOkIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.disclaimerOkButton, startDownloadOkPendingIntent);

+

+        // set up the start download Cancel intent

+        Intent startDownloadCancelIntent = new Intent();

+        startDownloadCancelIntent.setAction(GappsInstallerHelper.GOOGLE_APPS_INSTALL_DOWNLOAD_CANCEL);

+        PendingIntent startDownloadCancelPendingIntent = PendingIntent.getBroadcast(context, code++, startDownloadCancelIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.disclaimerCancelButton, startDownloadCancelPendingIntent);

+        

+        // set up the start download Ok intent

+        Intent failedDownloadOkIntent = new Intent();

+        failedDownloadOkIntent.setAction(GappsInstallerHelper.GAPPS_ACTION_DOWNLOAD_CONFIGURATION_FILE);

+        PendingIntent failedDownloadOkPendingIntent = PendingIntent.getBroadcast(context, code++, failedDownloadOkIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.failedDownloadOkButton, failedDownloadOkPendingIntent);

+

+        Intent permissionsOkIntent = new Intent();

+        permissionsOkIntent.setAction(GappsInstallerHelper.GAPPS_ACTION_GO_PERMISSIONS);

+        PendingIntent permissionsOkPendingIntent = PendingIntent.getBroadcast(context, code++, permissionsOkIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.permissionsOkButton, permissionsOkPendingIntent);

+        

+        // set up the start download Cancel intent

+        Intent failedDownloadCancelIntent = new Intent();

+        failedDownloadCancelIntent.setAction(GappsInstallerHelper.GOOGLE_APPS_INSTALL_DOWNLOAD_CANCEL);

+        PendingIntent failedDownloadCancelPendingIntent = PendingIntent.getBroadcast(context, code++, failedDownloadCancelIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.failedDownloadCancelButton, failedDownloadCancelPendingIntent);

+        

+        // set up the start reboot ok intent

+        Intent rebootOkIntent = new Intent();

+        rebootOkIntent.setAction(GappsInstallerHelper.GOOGLE_APPS_INSTALL_REBOOT);

+        PendingIntent rebootOkPendingIntent = PendingIntent.getBroadcast(context, code++, rebootOkIntent, PendingIntent.FLAG_UPDATE_CURRENT);

+        widget.setOnClickPendingIntent(R.id.rebootOkButton, rebootOkPendingIntent);

+        

+        return code;

+    }

+

+    private void updateUI(Context context, AppWidgetManager appWidgetManager, int appWidgetId)

+    {

+        int code = 0;

+        // get the widgets

+        RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.fp_google_apps_installer_widget);

+

+		code = setupButtonClickIntents(context, code, widget);

+

+        SharedPreferences sharedPrefs = context.getSharedPreferences(GappsInstallerHelper.PREFS_GOOGLE_APPS_INSTALLER_DATA, Context.MODE_PRIVATE);

+        int widgetCurrentState = sharedPrefs.getInt(GappsInstallerHelper.GOOGLE_APPS_INSTALLER_STATE, 0);

+        switch (widgetCurrentState)

+        {

+            case GappsInstallerHelper.GAPPS_STATES_INITIAL:

+                widget.setViewVisibility(R.id.installGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+                break;

+            case GappsInstallerHelper.GAPPS_STATES_DOWNLOAD_CONFIGURATION_FILE:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+                widget.setTextViewText(R.id.progressDialogTitle, context.getResources().getString(R.string.google_apps_download_title));

+                

+                updateProgress(widget, sharedPrefs);

+            	break;

+            case GappsInstallerHelper.GAPPS_STATES_DOWNLOAD_GOOGLE_APPS_FILE:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+                widget.setTextViewText(R.id.progressDialogTitle, context.getResources().getString(R.string.google_apps_download_title));

+                

+                updateProgress(widget, sharedPrefs);

+            	break;

+            case GappsInstallerHelper.GAPPS_STATES_EXTRACT_FILES:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+                widget.setTextViewText(R.id.progressDialogTitle, context.getResources().getString(R.string.google_apps_unzip_title));

+                

+                updateProgress(widget, sharedPrefs);

+            	break;

+            case GappsInstallerHelper.GAPPS_DOWNLOAD_FAILED_STATE:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+            	break;

+            case GappsInstallerHelper.GAPPS_STATES_PERMISSION_CHECK:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+            	widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+            	break;

+            case GappsInstallerHelper.GAPPS_STATE_INSTALLATION:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+            	widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+                widget.setTextViewText(R.id.progressDialogTitle, context.getResources().getString(R.string.google_apps_install_title));

+

+                updateProgress(widget, sharedPrefs);

+	            break;

+            case GappsInstallerHelper.GAPPS_REBOOT_STATE:

+            	widget.setViewVisibility(R.id.installGroup, View.GONE);

+            	widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.VISIBLE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.GONE);

+	            break;

+            case GappsInstallerHelper.GAPPS_INSTALLED_STATE:

+                widget.setViewVisibility(R.id.installGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupFailedDownloadGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupDisclaimerGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupProgressGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupPermissionsGroup, View.GONE);

+                widget.setViewVisibility(R.id.popupRebootGroup, View.GONE);

+                widget.setViewVisibility(R.id.uninstallGroup, View.VISIBLE);

+                break;

+

+            default:

+                break;

+        }

+

+        // update the widget data

+        appWidgetManager.updateAppWidget(appWidgetId, widget);

+    }

+

+	private void updateProgress(RemoteViews widget,

+			SharedPreferences sharedPrefs) {

+		int progress = sharedPrefs.getInt(GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS, 0);

+		int progressMax = sharedPrefs.getInt(GappsInstallerHelper.GOOGLE_APPS_INSTALLER_PROGRESS_MAX, 0);

+		widget.setProgressBar(R.id.progressBar, progressMax != 0 ? progressMax : 100, progress, false);

+	}

+

+    @Override

+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)

+    {

+        super.onUpdate(context, appWidgetManager, appWidgetIds);

+        // Called in response to the ACTION_APPWIDGET_UPDATE broadcast when this

+        // AppWidget provider

+        // is being asked to provide RemoteViews for a set of AppWidgets.

+        // Override this method to implement your own AppWidget functionality.

+

+        // iterate through every instance of this widget

+        // remember that it can have more than one widget of the same type.

+        for (int i = 0; i < appWidgetIds.length; i++)

+        { // See the dimensions and

+            System.out.println("Updating widget #" + i);

+            updateUI(context, appWidgetManager, appWidgetIds[i]);

+        }

+

+    }

+}

diff --git a/FairphoneHome/tests/Android.mk b/FairphoneHome/tests/Android.mk
new file mode 100644
index 0000000..e33169c
--- /dev/null
+++ b/FairphoneHome/tests/Android.mk
@@ -0,0 +1,16 @@
+# Copyright (C) 2011 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 $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/FairphoneHome/tests/stress/Android.mk b/FairphoneHome/tests/stress/Android.mk
new file mode 100644
index 0000000..68289bd
--- /dev/null
+++ b/FairphoneHome/tests/stress/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2011 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)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := LauncherRotationStressTest
+
+LOCAL_CERTIFICATE := shared
+
+LOCAL_INSTRUMENTATION_FOR := Launcher2
+
+include $(BUILD_PACKAGE)
diff --git a/FairphoneHome/tests/stress/AndroidManifest.xml b/FairphoneHome/tests/stress/AndroidManifest.xml
new file mode 100644
index 0000000..74ceddc
--- /dev/null
+++ b/FairphoneHome/tests/stress/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.launcher.stress.launcherrotation">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.launcher"
+        android:label="Rotation stress test using Launcher2">
+    </instrumentation>
+</manifest>
diff --git a/FairphoneHome/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java b/FairphoneHome/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
new file mode 100644
index 0000000..d21fd53
--- /dev/null
+++ b/FairphoneHome/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.launcher2.stress;
+
+
+import com.android.launcher2.Launcher;
+
+import android.content.pm.ActivityInfo;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.RepetitiveTest;
+import android.util.Log;
+
+/**
+ * Run rotation stress test using Launcher2 for 50 iterations.
+ */
+public class LauncherRotationStressTest extends ActivityInstrumentationTestCase2<Launcher> {
+
+    private static final int NUM_ITERATIONS = 50;
+    private static final int WAIT_TIME_MS = 500;
+    private static final String LOG_TAG = "LauncherRotationStressTest";
+
+    public LauncherRotationStressTest() {
+        super(Launcher.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @RepetitiveTest(numIterations=NUM_ITERATIONS)
+    public void testLauncherRotationStress() throws Exception {
+        Launcher launcher = getActivity();
+        getInstrumentation().waitForIdleSync();
+        SystemClock.sleep(WAIT_TIME_MS);
+        launcher.setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        getInstrumentation().waitForIdleSync();
+        SystemClock.sleep(WAIT_TIME_MS);
+        launcher.setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+    }
+}
diff --git a/FairphonePeaceOfMind/.classpath b/FairphonePeaceOfMind/.classpath
new file mode 100644
index 0000000..7bc01d9
--- /dev/null
+++ b/FairphonePeaceOfMind/.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/FairphonePeaceOfMind/.project b/FairphonePeaceOfMind/.project
new file mode 100644
index 0000000..19017f3
--- /dev/null
+++ b/FairphonePeaceOfMind/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>FairPhonePeaceOfMindApp</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/FairphonePeaceOfMind/.settings/org.eclipse.jdt.core.prefs b/FairphonePeaceOfMind/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b080d2d
--- /dev/null
+++ b/FairphonePeaceOfMind/.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/FairphonePeaceOfMind/AndroidManifest.xml b/FairphonePeaceOfMind/AndroidManifest.xml
new file mode 100644
index 0000000..de9d1b8
--- /dev/null
+++ b/FairphonePeaceOfMind/AndroidManifest.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.fairphone.fairphonepeaceofmindapp"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="16" />
+
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/peace_app_icon"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="org.fairphone.peaceofmind.PeaceOfMindActivity"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait" 
+            android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+<!-- 
+        <service
+            android:name="org.fairphone.peaceofmind.service.TimerService"
+            android:permission="android.permission.BIND_REMOTEVIEWS" /> -->
+        <receiver
+            android:name="org.fairphone.peaceofmind.PeaceOfMindBroadCastReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.AIRPLANE_MODE"/>
+                <action android:name="android.intent.action.ACTION_SHUTDOWN" />
+            </intent-filter>
+        </receiver>
+        <receiver
+            android:name="org.fairphone.peaceofmind.PeaceOfMindApplicationBroadcastReceiver">
+        </receiver>
+        
+        <!--  android:process=":remote" -->
+        <!-- Widget -->
+        <receiver
+            android:name="org.fairphone.peaceofmind.widget.WidgetProvider"
+            android:exported="false"
+            android:icon="@drawable/peace_widget_icon"
+            android:label="@string/peace_of_mind_widget" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider" />
+        </receiver>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/bin/AndroidManifest.xml b/FairphonePeaceOfMind/bin/AndroidManifest.xml
new file mode 100644
index 0000000..de9d1b8
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/AndroidManifest.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.fairphone.fairphonepeaceofmindapp"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="16" />
+
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/peace_app_icon"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="org.fairphone.peaceofmind.PeaceOfMindActivity"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait" 
+            android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+<!-- 
+        <service
+            android:name="org.fairphone.peaceofmind.service.TimerService"
+            android:permission="android.permission.BIND_REMOTEVIEWS" /> -->
+        <receiver
+            android:name="org.fairphone.peaceofmind.PeaceOfMindBroadCastReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.AIRPLANE_MODE"/>
+                <action android:name="android.intent.action.ACTION_SHUTDOWN" />
+            </intent-filter>
+        </receiver>
+        <receiver
+            android:name="org.fairphone.peaceofmind.PeaceOfMindApplicationBroadcastReceiver">
+        </receiver>
+        
+        <!--  android:process=":remote" -->
+        <!-- Widget -->
+        <receiver
+            android:name="org.fairphone.peaceofmind.widget.WidgetProvider"
+            android:exported="false"
+            android:icon="@drawable/peace_widget_icon"
+            android:label="@string/peace_of_mind_widget" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider" />
+        </receiver>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/BuildConfig.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/BuildConfig.class
new file mode 100644
index 0000000..1520cf3
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/BuildConfig.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$anim.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$anim.class
new file mode 100644
index 0000000..b896471
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$anim.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$attr.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$attr.class
new file mode 100644
index 0000000..aeadec4
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$attr.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$color.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$color.class
new file mode 100644
index 0000000..5cd816d
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$color.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$dimen.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$dimen.class
new file mode 100644
index 0000000..9fbb457
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$dimen.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$drawable.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$drawable.class
new file mode 100644
index 0000000..6928dd5
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$drawable.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$id.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$id.class
new file mode 100644
index 0000000..1476df6
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$id.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$layout.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$layout.class
new file mode 100644
index 0000000..2208a80
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$layout.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$raw.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$raw.class
new file mode 100644
index 0000000..3b1ff85
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$raw.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$string.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$string.class
new file mode 100644
index 0000000..51d3a03
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$string.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$style.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$style.class
new file mode 100644
index 0000000..fe9e954
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$style.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$xml.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$xml.class
new file mode 100644
index 0000000..d897940
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R$xml.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R.class
new file mode 100644
index 0000000..ed9de7a
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/fairphonepeaceofmindapp/R.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/AirplaneModeDeviceController.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/AirplaneModeDeviceController.class
new file mode 100644
index 0000000..5a3590e
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/AirplaneModeDeviceController.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/AirplaneModeToggler.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/AirplaneModeToggler.class
new file mode 100644
index 0000000..da89d24
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/AirplaneModeToggler.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/IDeviceController.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/IDeviceController.class
new file mode 100644
index 0000000..021b38d
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/IDeviceController.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$1.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$1.class
new file mode 100644
index 0000000..17c52f8
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$1.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$10.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$10.class
new file mode 100644
index 0000000..4b5ecae
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$10.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$2.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$2.class
new file mode 100644
index 0000000..62ab9a7
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$2.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$3.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$3.class
new file mode 100644
index 0000000..d546077
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$3.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$4.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$4.class
new file mode 100644
index 0000000..a02ca0c
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$4.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$5.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$5.class
new file mode 100644
index 0000000..30787c3
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$5.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$6.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$6.class
new file mode 100644
index 0000000..0131141
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$6.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$7.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$7.class
new file mode 100644
index 0000000..a1877c0
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$7.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$8.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$8.class
new file mode 100644
index 0000000..7551f59
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$8.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$9.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$9.class
new file mode 100644
index 0000000..6bc1918
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity$9.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity.class
new file mode 100644
index 0000000..e51286c
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindActivity.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver$Listener.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver$Listener.class
new file mode 100644
index 0000000..4922f1e
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver$Listener.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver.class
new file mode 100644
index 0000000..911faa0
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindBroadCastReceiver.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindBroadCastReceiver.class
new file mode 100644
index 0000000..039b2f8
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindBroadCastReceiver.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindIntents.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindIntents.class
new file mode 100644
index 0000000..6d9cef0
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/PeaceOfMindIntents.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/data/PeaceOfMindRun.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/data/PeaceOfMindRun.class
new file mode 100644
index 0000000..3d0c898
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/data/PeaceOfMindRun.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/data/PeaceOfMindStats.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/data/PeaceOfMindStats.class
new file mode 100644
index 0000000..8dc7c7f
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/data/PeaceOfMindStats.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/service/IPeaceOfMindTimeListener.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/service/IPeaceOfMindTimeListener.class
new file mode 100644
index 0000000..f2e7365
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/service/IPeaceOfMindTimeListener.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/service/IPeaceServiceController.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/service/IPeaceServiceController.class
new file mode 100644
index 0000000..6a47e74
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/service/IPeaceServiceController.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/ui/VerticalScrollListener.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/ui/VerticalScrollListener.class
new file mode 100644
index 0000000..9c07040
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/ui/VerticalScrollListener.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/ui/VerticalSeekBar.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/ui/VerticalSeekBar.class
new file mode 100644
index 0000000..a9d79d3
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/ui/VerticalSeekBar.class
Binary files differ
diff --git a/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/widget/WidgetProvider.class b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/widget/WidgetProvider.class
new file mode 100644
index 0000000..4399369
--- /dev/null
+++ b/FairphonePeaceOfMind/bin/classes/org/fairphone/peaceofmind/widget/WidgetProvider.class
Binary files differ
diff --git a/FairphonePeaceOfMind/gen/org/fairphone/fairphonepeaceofmindapp/BuildConfig.java b/FairphonePeaceOfMind/gen/org/fairphone/fairphonepeaceofmindapp/BuildConfig.java
new file mode 100644
index 0000000..30872b6
--- /dev/null
+++ b/FairphonePeaceOfMind/gen/org/fairphone/fairphonepeaceofmindapp/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package org.fairphone.fairphonepeaceofmindapp;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/gen/org/fairphone/fairphonepeaceofmindapp/R.java b/FairphonePeaceOfMind/gen/org/fairphone/fairphonepeaceofmindapp/R.java
new file mode 100644
index 0000000..dfce5ca
--- /dev/null
+++ b/FairphonePeaceOfMind/gen/org/fairphone/fairphonepeaceofmindapp/R.java
@@ -0,0 +1,168 @@
+/* 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 org.fairphone.fairphonepeaceofmindapp;
+
+public final class R {
+    public static final class anim {
+        public static final int fade_in_fast=0x7f040000;
+        public static final int fade_out_fast=0x7f040001;
+        public static final int target_time_fade_in_fast=0x7f040002;
+    }
+    public static final class attr {
+    }
+    public static final class color {
+        public static final int alpha_black=0x7f07000b;
+        public static final int alpha_white=0x7f07000a;
+        /**  BACKGROUND 
+         */
+        public static final int background=0x7f07000c;
+        public static final int black=0x7f070001;
+        public static final int blue=0x7f070005;
+        public static final int blue_alpha=0x7f070007;
+        public static final int blue_green=0x7f070008;
+        public static final int blue_grey=0x7f070006;
+        public static final int grey=0x7f070002;
+        public static final int grey_text=0x7f070003;
+        public static final int grey_text_to=0x7f070004;
+        /**  TRANSPARENCY 
+         */
+        public static final int transparent=0x7f070009;
+        /**  BASE COLORS 
+         */
+        public static final int white=0x7f070000;
+    }
+    public static final class dimen {
+        /**  Default screen margins, per the Android Design guidelines. 
+         */
+        public static final int activity_horizontal_margin=0x7f080000;
+        public static final int activity_vertical_margin=0x7f080001;
+    }
+    public static final class drawable {
+        public static final int background_grid=0x7f020000;
+        public static final int background_off=0x7f020001;
+        public static final int background_off_repeat=0x7f020002;
+        public static final int background_on=0x7f020003;
+        public static final int background_on_repeat=0x7f020004;
+        public static final int background_overlay=0x7f020005;
+        public static final int button_close=0x7f020006;
+        public static final int button_close_press=0x7f020007;
+        public static final int button_close_up=0x7f020008;
+        public static final int button_help=0x7f020009;
+        public static final int button_help_press=0x7f02000a;
+        public static final int button_help_up=0x7f02000b;
+        public static final int peace_app_icon=0x7f02000c;
+        public static final int peace_play_store_icon=0x7f02000d;
+        public static final int peace_system_bar_icon=0x7f02000e;
+        public static final int peace_widget_icon=0x7f02000f;
+        public static final int progressbar_progress=0x7f020010;
+        public static final int secondary_progressbar_progress=0x7f020011;
+        public static final int seekbar_background_off=0x7f020012;
+        public static final int seekbar_background_on=0x7f020013;
+        public static final int seekbar_progress_secondary=0x7f020014;
+        public static final int seekbar_thumb_off=0x7f020015;
+        public static final int seekbar_thumb_on=0x7f020016;
+        public static final int transparent=0x7f020017;
+        public static final int widget_off=0x7f020018;
+        public static final int widget_progressbar_background_off=0x7f020019;
+        public static final int widget_progressbar_background_on=0x7f02001a;
+        public static final int widget_progressbar_progress=0x7f02001b;
+        public static final int widget_progressbar_secondary_progress=0x7f02001c;
+    }
+    public static final class id {
+        public static final int atText=0x7f0b001a;
+        public static final int background=0x7f0b0000;
+        public static final int backgroundGrid=0x7f0b0003;
+        public static final int backgroundOverlay=0x7f0b0001;
+        public static final int closeButton=0x7f0b0015;
+        public static final int currentAtText=0x7f0b000b;
+        public static final int currentPeaceText=0x7f0b000c;
+        public static final int helpButton=0x7f0b0012;
+        public static final int helpHolder=0x7f0b0013;
+        public static final int helpLayout=0x7f0b0014;
+        public static final int inPeaceTextCurrent=0x7f0b000a;
+        public static final int offGroup=0x7f0b0021;
+        public static final int onGroup=0x7f0b0017;
+        public static final int peaceOfMindText=0x7f0b0018;
+        public static final int peaceOfMindWidgetLayout=0x7f0b0016;
+        public static final int peaceText=0x7f0b001b;
+        public static final int peace_of_mind_widget_layout=0x7f0b0023;
+        public static final int pomVideo=0x7f0b0002;
+        public static final int progressBar=0x7f0b0020;
+        public static final int progressBarBackground=0x7f0b0019;
+        public static final int progressText=0x7f0b000f;
+        public static final int progressView=0x7f0b000e;
+        public static final int secondaryProgressBar=0x7f0b001f;
+        public static final int seekbar_background_off=0x7f0b0010;
+        public static final int seekbar_background_on=0x7f0b0011;
+        public static final int timeText=0x7f0b001d;
+        public static final int timeTextCurrent=0x7f0b0006;
+        public static final int timeTextCurrentGroup=0x7f0b0004;
+        public static final int timeTextTotal=0x7f0b000d;
+        public static final int timerTexts=0x7f0b001c;
+        public static final int toText=0x7f0b0008;
+        public static final int toTimeGroup=0x7f0b0007;
+        public static final int toTimeText=0x7f0b0009;
+        public static final int totalTimeText=0x7f0b001e;
+        public static final int verticalSeekBar=0x7f0b0005;
+        public static final int widgetOffImage=0x7f0b0022;
+    }
+    public static final class layout {
+        public static final int activity_main=0x7f030000;
+        public static final int help_layout=0x7f030001;
+        public static final int widget=0x7f030002;
+        public static final int widget_off=0x7f030003;
+    }
+    public static final class raw {
+        public static final int fp_start_pom_video=0x7f060000;
+    }
+    public static final class string {
+        public static final int app_name=0x7f090000;
+        public static final int at=0x7f090003;
+        public static final int de=0x7f09000f;
+        public static final int enjoy=0x7f090008;
+        public static final int help_string_1=0x7f090005;
+        public static final int help_string_2=0x7f090006;
+        public static final int help_string_3=0x7f090007;
+        public static final int hour_separator=0x7f09000c;
+        public static final int peace=0x7f090004;
+        public static final int peace_of_mind_widget=0x7f090001;
+        public static final int peace_off_notification=0x7f09000e;
+        public static final int peace_on_notification=0x7f09000d;
+        public static final int some=0x7f090009;
+        public static final int to_h=0x7f09000b;
+        public static final int to_m=0x7f09000a;
+        public static final int to_widget=0x7f090011;
+        public static final int um=0x7f090010;
+        public static final int widget_enjoy_some_peace=0x7f090002;
+    }
+    public static final class style {
+        /**  <item name="android:windowBackground">@android:color/transparent</item> 
+ <item name="android:windowIsTranslucent">true</item> 
+         */
+        public static final int AppTheme=0x7f0a0000;
+        public static final int AtText=0x7f0a0005;
+        public static final int PeaceText=0x7f0a0006;
+        public static final int TimeText=0x7f0a0002;
+        public static final int ToText=0x7f0a0003;
+        public static final int ToTimeText=0x7f0a0004;
+        public static final int TotalTimeText=0x7f0a0001;
+        public static final int WidgetOffBoldText=0x7f0a0009;
+        /**  WIDGET OFF 
+         */
+        public static final int WidgetOffLightText=0x7f0a0007;
+        public static final int WidgetOffRegularText=0x7f0a0008;
+        public static final int WidgetOnBoldText=0x7f0a000c;
+        /**  WIDGET ON 
+         */
+        public static final int WidgetOnLightText=0x7f0a000a;
+        public static final int WidgetOnRegularText=0x7f0a000b;
+    }
+    public static final class xml {
+        public static final int widget_provider=0x7f050000;
+    }
+}
diff --git a/FairphonePeaceOfMind/help_layout.xml b/FairphonePeaceOfMind/help_layout.xml
new file mode 100644
index 0000000..4112f0d
--- /dev/null
+++ b/FairphonePeaceOfMind/help_layout.xml
@@ -0,0 +1,58 @@
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <FrameLayout
+        android:id="@+id/helpHolder"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#DD000000"
+        android:visibility="gone" >
+
+        <LinearLayout
+            android:id="@+id/helpLayout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:paddingLeft="46.5dp"
+            android:paddingRight="46.5dp"
+            android:visibility="gone" >
+
+            <Button
+                android:id="@+id/closeButton"
+                android:layout_width="56dp"
+                android:layout_height="56dp"
+                android:layout_marginTop="65dp"
+                android:background="@drawable/button_close" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="25dp"
+                android:fontFamily="sans-serif-light"
+                android:lineSpacingExtra="-2dp"
+                android:text="@string/help_string_1"
+                android:textColor="@color/grey_text"
+                android:textSize="21sp" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="45dp"
+                android:lineSpacingExtra="0dp"
+                android:text="@string/help_string_2"
+                android:textColor="@color/blue"
+                android:textSize="14.5sp"
+                android:textStyle="bold" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="15dp"
+                android:lineSpacingExtra="0dp"
+                android:text="@string/help_string_3"
+                android:textColor="@color/blue"
+                android:textSize="14.5sp" />
+        </LinearLayout>
+    </FrameLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/libs/android-support-v4.jar b/FairphonePeaceOfMind/libs/android-support-v4.jar
new file mode 100644
index 0000000..428bdbc
--- /dev/null
+++ b/FairphonePeaceOfMind/libs/android-support-v4.jar
Binary files differ
diff --git a/FairphonePeaceOfMind/proguard-project.txt b/FairphonePeaceOfMind/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/FairphonePeaceOfMind/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/FairphonePeaceOfMind/project.properties b/FairphonePeaceOfMind/project.properties
new file mode 100644
index 0000000..a3ee5ab
--- /dev/null
+++ b/FairphonePeaceOfMind/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/FairphonePeaceOfMind/res/anim/fade_in_fast.xml b/FairphonePeaceOfMind/res/anim/fade_in_fast.xml
new file mode 100644
index 0000000..68b14c8
--- /dev/null
+++ b/FairphonePeaceOfMind/res/anim/fade_in_fast.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/decelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="350" />
diff --git a/FairphonePeaceOfMind/res/anim/fade_out_fast.xml b/FairphonePeaceOfMind/res/anim/fade_out_fast.xml
new file mode 100644
index 0000000..def0869
--- /dev/null
+++ b/FairphonePeaceOfMind/res/anim/fade_out_fast.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/decelerate_interpolator"
+
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+
+    android:duration="350" />
diff --git a/FairphonePeaceOfMind/res/anim/target_time_fade_in_fast.xml b/FairphonePeaceOfMind/res/anim/target_time_fade_in_fast.xml
new file mode 100644
index 0000000..c6814d8
--- /dev/null
+++ b/FairphonePeaceOfMind/res/anim/target_time_fade_in_fast.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/decelerate_interpolator"
+
+    android:fromAlpha="0.0"
+    android:toAlpha="1.0"
+
+    android:duration="250" />
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/background_grid.png b/FairphonePeaceOfMind/res/drawable-hdpi/background_grid.png
new file mode 100644
index 0000000..285fa64
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/background_grid.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/background_off.png b/FairphonePeaceOfMind/res/drawable-hdpi/background_off.png
new file mode 100644
index 0000000..f233bad
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/background_off.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/background_on.png b/FairphonePeaceOfMind/res/drawable-hdpi/background_on.png
new file mode 100644
index 0000000..f8f4e67
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/background_on.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/background_overlay.png b/FairphonePeaceOfMind/res/drawable-hdpi/background_overlay.png
new file mode 100644
index 0000000..1a76943
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/background_overlay.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/button_close_press.png b/FairphonePeaceOfMind/res/drawable-hdpi/button_close_press.png
new file mode 100644
index 0000000..4abc856
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/button_close_press.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/button_close_up.png b/FairphonePeaceOfMind/res/drawable-hdpi/button_close_up.png
new file mode 100644
index 0000000..5aecfff
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/button_close_up.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/button_help_press.png b/FairphonePeaceOfMind/res/drawable-hdpi/button_help_press.png
new file mode 100644
index 0000000..127145b
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/button_help_press.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/button_help_up.png b/FairphonePeaceOfMind/res/drawable-hdpi/button_help_up.png
new file mode 100644
index 0000000..d7256ea
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/button_help_up.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/peace_app_icon.png b/FairphonePeaceOfMind/res/drawable-hdpi/peace_app_icon.png
new file mode 100644
index 0000000..1e76f82
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/peace_app_icon.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/peace_play_store_icon.png b/FairphonePeaceOfMind/res/drawable-hdpi/peace_play_store_icon.png
new file mode 100644
index 0000000..9883ad4
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/peace_play_store_icon.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/peace_system_bar_icon.png b/FairphonePeaceOfMind/res/drawable-hdpi/peace_system_bar_icon.png
new file mode 100644
index 0000000..6134416
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/peace_system_bar_icon.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/peace_widget_icon.png b/FairphonePeaceOfMind/res/drawable-hdpi/peace_widget_icon.png
new file mode 100644
index 0000000..1bdb8b6
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/peace_widget_icon.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_background_off.9.png b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_background_off.9.png
new file mode 100644
index 0000000..a115551
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_background_off.9.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_background_on.9.png b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_background_on.9.png
new file mode 100644
index 0000000..bfd954f
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_background_on.9.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_progress_secondary.9.png b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_progress_secondary.9.png
new file mode 100644
index 0000000..3da4993
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_progress_secondary.9.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_thumb_off.png b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_thumb_off.png
new file mode 100644
index 0000000..ff38b5a
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_thumb_off.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_thumb_on.png b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_thumb_on.png
new file mode 100644
index 0000000..676ecdc
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/seekbar_thumb_on.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/transparent.png b/FairphonePeaceOfMind/res/drawable-hdpi/transparent.png
new file mode 100644
index 0000000..9a324e8
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/transparent.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/widget_off.png b/FairphonePeaceOfMind/res/drawable-hdpi/widget_off.png
new file mode 100644
index 0000000..f07a211
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/widget_off.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_background_off.png b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_background_off.png
new file mode 100644
index 0000000..3405b00
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_background_off.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_background_on.png b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_background_on.png
new file mode 100644
index 0000000..b5b8683
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_background_on.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_progress.9.png b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_progress.9.png
new file mode 100644
index 0000000..6f5f781
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_progress.9.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_secondary_progress.9.png b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_secondary_progress.9.png
new file mode 100644
index 0000000..18deef4
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable-hdpi/widget_progressbar_secondary_progress.9.png
Binary files differ
diff --git a/FairphonePeaceOfMind/res/drawable/background_off_repeat.xml b/FairphonePeaceOfMind/res/drawable/background_off_repeat.xml
new file mode 100644
index 0000000..27aaca4
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable/background_off_repeat.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/background_off"
+    android:tileMode="repeat" />
diff --git a/FairphonePeaceOfMind/res/drawable/background_on_repeat.xml b/FairphonePeaceOfMind/res/drawable/background_on_repeat.xml
new file mode 100644
index 0000000..654f38b
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable/background_on_repeat.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/background_on"
+    android:tileMode="repeat" />
diff --git a/FairphonePeaceOfMind/res/drawable/button_close.xml b/FairphonePeaceOfMind/res/drawable/button_close.xml
new file mode 100644
index 0000000..d6ad47a
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable/button_close.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/button_close_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/button_close_up"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/drawable/button_help.xml b/FairphonePeaceOfMind/res/drawable/button_help.xml
new file mode 100644
index 0000000..4e4ba27
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable/button_help.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/button_help_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/button_help_up"/>
+
+</selector>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/drawable/progressbar_progress.xml b/FairphonePeaceOfMind/res/drawable/progressbar_progress.xml
new file mode 100644
index 0000000..bed9511
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable/progressbar_progress.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="#00000000" />
+        </shape>
+    </item>
+    <item android:id="@android:id/secondaryProgress">
+        <clip android:drawable="@drawable/widget_progressbar_secondary_progress" />
+    </item>
+    <item android:id="@android:id/progress">
+        <clip android:drawable="@drawable/widget_progressbar_secondary_progress" />
+    </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/drawable/secondary_progressbar_progress.xml b/FairphonePeaceOfMind/res/drawable/secondary_progressbar_progress.xml
new file mode 100644
index 0000000..189c833
--- /dev/null
+++ b/FairphonePeaceOfMind/res/drawable/secondary_progressbar_progress.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="#00000000" />
+        </shape>
+    </item>
+    <item android:id="@android:id/secondaryProgress">
+        <clip android:drawable="@drawable/widget_progressbar_progress" />
+    </item>
+    <item android:id="@android:id/progress">
+        <clip android:drawable="@drawable/widget_progressbar_progress" />
+    </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout-de/widget_off.xml b/FairphonePeaceOfMind/res/layout-de/widget_off.xml
new file mode 100644
index 0000000..536062c
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout-de/widget_off.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <LinearLayout
+        android:id="@+id/offGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/widgetOffImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/widget_off" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/enjoy" />
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/some" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/de" />
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/peace" />
+        </LinearLayout>
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout-es/widget_off.xml b/FairphonePeaceOfMind/res/layout-es/widget_off.xml
new file mode 100644
index 0000000..e0a8f48
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout-es/widget_off.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <LinearLayout
+        android:id="@+id/offGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/widgetOffImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/widget_off" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/enjoy" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/to_m" />
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/um" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/some" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/to_m" />
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/peace" />
+        </LinearLayout>
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout-fr/help_layout.xml b/FairphonePeaceOfMind/res/layout-fr/help_layout.xml
new file mode 100644
index 0000000..6320a4b
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout-fr/help_layout.xml
@@ -0,0 +1,58 @@
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <FrameLayout
+        android:id="@+id/helpHolder"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#DD000000"
+        android:visibility="gone" >
+
+        <LinearLayout
+            android:id="@+id/helpLayout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:paddingLeft="46.5dp"
+            android:paddingRight="46.5dp"
+            android:visibility="gone" >
+
+            <Button
+                android:id="@+id/closeButton"
+                android:layout_width="56dp"
+                android:layout_height="56dp"
+                android:layout_marginTop="65dp"
+                android:background="@drawable/button_close" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="25dp"
+                android:fontFamily="sans-serif-light"
+                android:lineSpacingExtra="-2dp"
+                android:text="@string/help_string_1"
+                android:textColor="@color/grey_text"
+                android:textSize="17.5sp" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="45dp"
+                android:lineSpacingExtra="0dp"
+                android:text="@string/help_string_2"
+                android:textColor="@color/blue"
+                android:textSize="14.5sp"
+                android:textStyle="bold" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="15dp"
+                android:lineSpacingExtra="0dp"
+                android:text="@string/help_string_3"
+                android:textColor="@color/blue"
+                android:textSize="14.5sp" />
+        </LinearLayout>
+    </FrameLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout-fr/widget_off.xml b/FairphonePeaceOfMind/res/layout-fr/widget_off.xml
new file mode 100644
index 0000000..3fe588b
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout-fr/widget_off.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <LinearLayout
+        android:id="@+id/offGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/widgetOffImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/widget_off" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/enjoy" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/to_widget" />
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/some" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/de" />
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/peace" />
+        </LinearLayout>
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout-nl/widget_off.xml b/FairphonePeaceOfMind/res/layout-nl/widget_off.xml
new file mode 100644
index 0000000..536062c
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout-nl/widget_off.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <LinearLayout
+        android:id="@+id/offGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/widgetOffImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/widget_off" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/enjoy" />
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/some" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/de" />
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/peace" />
+        </LinearLayout>
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout-pt/widget_off.xml b/FairphonePeaceOfMind/res/layout-pt/widget_off.xml
new file mode 100644
index 0000000..e0a8f48
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout-pt/widget_off.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <LinearLayout
+        android:id="@+id/offGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/widgetOffImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/widget_off" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/enjoy" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/to_m" />
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/um" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffRegularText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/some" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/to_m" />
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/peace" />
+        </LinearLayout>
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout/activity_main.xml b/FairphonePeaceOfMind/res/layout/activity_main.xml
new file mode 100644
index 0000000..b032f55
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout/activity_main.xml
@@ -0,0 +1,181 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/background"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <View
+        android:id="@+id/backgroundOverlay"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/background_off_repeat" />
+
+    <VideoView
+        android:id="@+id/pomVideo"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <View
+        android:id="@+id/backgroundGrid"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/background_grid" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="440dp"
+            android:layout_marginBottom="50dp"
+            android:layout_marginTop="50dp" >
+
+            <LinearLayout
+                android:id="@+id/timeTextCurrentGroup"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignBottom="@+id/verticalSeekBar"
+                android:layout_toLeftOf="@+id/verticalSeekBar"
+                android:gravity="center_vertical|right"
+                android:orientation="vertical" >
+
+                <TextView
+                    android:id="@+id/timeTextCurrent"
+                    style="@style/TimeText"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:paddingRight="5dp"/>
+
+                <LinearLayout
+                    android:id="@+id/toTimeGroup"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="-7dp"
+                    android:orientation="horizontal" >
+
+                    <TextView
+                        android:id="@+id/toText"
+                        style="@style/ToText"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:alpha="0.5"
+                        android:text="@string/to_m" />
+
+                    <TextView
+                        android:id="@+id/toTimeText"
+                        style="@style/ToTimeText"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:alpha="0.5"
+                        android:paddingRight="5dp"/>
+                </LinearLayout>
+            </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/inPeaceTextCurrent"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignBottom="@+id/verticalSeekBar"
+                android:layout_marginBottom="28dp"
+                android:layout_marginLeft="5dp"
+                android:layout_toRightOf="@+id/verticalSeekBar"
+                android:alpha="0.5"
+                android:gravity="center_vertical"
+                android:paddingTop="3dp" >
+
+                <TextView
+                    android:id="@+id/currentAtText"
+                    style="@style/AtText"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/at" />
+
+                <TextView
+                    android:id="@+id/currentPeaceText"
+                    style="@style/PeaceText"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/peace" />
+            </LinearLayout>
+
+            <TextView
+                android:id="@+id/timeTextTotal"
+                style="@style/TotalTimeText"
+                android:layout_width="wrap_content"
+                android:layout_height="65dp"
+                android:layout_alignBottom="@+id/verticalSeekBar"
+                android:layout_marginRight="5dp"
+                android:layout_toLeftOf="@+id/verticalSeekBar"
+                android:alpha="0.5"
+                android:visibility="invisible" />
+
+            <RelativeLayout
+                android:layout_width="57dp"
+                android:layout_height="408dp"
+                android:layout_alignBottom="@+id/verticalSeekBar"
+                android:layout_alignLeft="@+id/verticalSeekBar"
+                android:layout_marginBottom="13.5dp"
+                android:layout_marginLeft="13.5dp"
+                android:gravity="bottom" >
+
+                <View
+                    android:id="@+id/progressView"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp"
+                    android:background="@drawable/seekbar_progress_secondary" />
+
+                <TextView
+                    android:id="@+id/progressText"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignTop="@+id/progressView"
+                    android:layout_centerInParent="true"
+                    android:layout_marginTop="10dp"
+                    android:paddingLeft="2dp"
+                    android:textColor="#1D71B8"
+                    android:textSize="14.sp"
+                    android:textStyle="bold" />
+            </RelativeLayout>
+
+            <View
+                android:id="@+id/seekbar_background_off"
+                android:layout_width="74dp"
+                android:layout_height="432dp"
+                android:layout_centerInParent="true"
+                android:background="@drawable/seekbar_background_off" />
+
+            <View
+                android:id="@+id/seekbar_background_on"
+                android:layout_width="74dp"
+                android:layout_height="432dp"
+                android:layout_centerInParent="true"
+                android:background="@drawable/seekbar_background_on"
+                android:visibility="invisible" />
+
+            <org.fairphone.peaceofmind.ui.VerticalSeekBar
+                android:id="@+id/verticalSeekBar"
+                android:layout_width="81dp"
+                android:layout_height="440dp"
+                android:layout_centerHorizontal="true"
+                android:max="100"
+                android:padding="0dp"
+                android:progressDrawable="@drawable/transparent"
+                android:rotation="180"
+                android:thumb="@drawable/seekbar_thumb_off"
+                android:thumbOffset="0dp" />
+        </RelativeLayout>
+
+        <Button
+            android:id="@+id/helpButton"
+            android:layout_width="56dp"
+            android:layout_height="56dp"
+            android:layout_marginBottom="15dp"
+            android:background="@drawable/button_help" />
+    </LinearLayout>
+
+    <include layout="@layout/help_layout" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout/help_layout.xml b/FairphonePeaceOfMind/res/layout/help_layout.xml
new file mode 100644
index 0000000..e40810f
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout/help_layout.xml
@@ -0,0 +1,58 @@
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <FrameLayout
+        android:id="@+id/helpHolder"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#DD000000"
+        android:visibility="gone" >
+
+        <LinearLayout
+            android:id="@+id/helpLayout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:paddingLeft="46.5dp"
+            android:paddingRight="46.5dp"
+            android:visibility="gone" >
+
+            <Button
+                android:id="@+id/closeButton"
+                android:layout_width="56dp"
+                android:layout_height="56dp"
+                android:layout_marginTop="65dp"
+                android:background="@drawable/button_close" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="25dp"
+                android:fontFamily="sans-serif-light"
+                android:lineSpacingExtra="-2dp"
+                android:text="@string/help_string_1"
+                android:textColor="@color/grey_text"
+                android:textSize="20sp" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="45dp"
+                android:lineSpacingExtra="0dp"
+                android:text="@string/help_string_2"
+                android:textColor="@color/blue"
+                android:textSize="14.5sp"
+                android:textStyle="bold" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="15dp"
+                android:lineSpacingExtra="0dp"
+                android:text="@string/help_string_3"
+                android:textColor="@color/blue"
+                android:textSize="14.5sp" />
+        </LinearLayout>
+    </FrameLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout/widget.xml b/FairphonePeaceOfMind/res/layout/widget.xml
new file mode 100644
index 0000000..d62449d
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout/widget.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/peaceOfMindWidgetLayout"
+    android:layout_width="match_parent"
+    android:layout_height="280dp" >
+
+    <include layout="@layout/widget_off" />
+
+    <RelativeLayout
+        android:id="@+id/onGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:visibility="gone" >
+
+        <RelativeLayout
+            android:id="@+id/peaceOfMindText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignBottom="@+id/progressBarBackground"
+            android:layout_marginLeft="3dp"
+            android:layout_toRightOf="@+id/progressBarBackground" >
+
+            <TextView
+                android:id="@+id/atText"
+                style="@style/WidgetOnLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingBottom="18dp"
+                android:text="@string/at" />
+
+            <TextView
+                android:id="@+id/peaceText"
+                style="@style/WidgetOnBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@+id/atText"
+                android:paddingBottom="18dp"
+                android:text="@string/peace" />
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:id="@+id/timerTexts"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignBottom="@+id/progressBarBackground"
+            android:layout_toLeftOf="@+id/progressBarBackground" >
+
+            <TextView
+                android:id="@+id/timeText"
+                style="@style/WidgetOnBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:paddingRight="3dp"
+                android:textAllCaps="false" />
+
+            <TextView
+                android:id="@+id/toText"
+                style="@style/WidgetOnLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@+id/timeText"
+                android:layout_marginTop="-6dp"
+                android:layout_toLeftOf="@+id/totalTimeText"
+                android:paddingRight="0.9dp"
+                android:text="@string/to_m"
+                android:textColor="@color/grey_text_to" />
+
+            <TextView
+                android:id="@+id/totalTimeText"
+                style="@style/WidgetOnBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_below="@+id/timeText"
+                android:layout_marginTop="-6dp"
+                android:paddingRight="3dp"
+                android:textAllCaps="false"
+                android:textColor="@color/grey_text_to" />
+        </RelativeLayout>
+
+        <ProgressBar
+            android:id="@+id/secondaryProgressBar"
+            android:layout_width="178.4dp"
+            android:layout_height="31dp"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="79dp"
+            android:indeterminateOnly="false"
+            android:max="100"
+            android:paddingRight="4dp"
+            android:paddingTop="2dp"
+            android:progress="0"
+            android:progressDrawable="@drawable/secondary_progressbar_progress"
+            android:rotation="270" />
+
+        <ProgressBar
+            android:id="@+id/progressBar"
+            android:layout_width="178.4dp"
+            android:layout_height="31dp"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="79dp"
+            android:indeterminateOnly="false"
+            android:max="100"
+            android:paddingRight="4dp"
+            android:paddingTop="2dp"
+            android:progress="0"
+            android:progressDrawable="@drawable/progressbar_progress"
+            android:rotation="270" />
+
+        <ImageView
+            android:id="@+id/progressBarBackground"
+            android:layout_width="wrap_content"
+            android:layout_height="188.6dp"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/widget_progressbar_background_off" />
+    </RelativeLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/layout/widget_off.xml b/FairphonePeaceOfMind/res/layout/widget_off.xml
new file mode 100644
index 0000000..6ddc68d
--- /dev/null
+++ b/FairphonePeaceOfMind/res/layout/widget_off.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <LinearLayout
+        android:id="@+id/offGroup"
+        android:layout_width="300dp"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/widgetOffImage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/widget_off" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:orientation="horizontal" >
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/enjoy" />
+
+            <TextView
+                style="@style/WidgetOffLightText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/some" />
+
+            <TextView
+                style="@style/WidgetOffBoldText"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/peace" />
+        </LinearLayout>
+    </LinearLayout>
+
+</merge>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/raw/fp_start_pom_video.mp4 b/FairphonePeaceOfMind/res/raw/fp_start_pom_video.mp4
new file mode 100644
index 0000000..e0f94ec
--- /dev/null
+++ b/FairphonePeaceOfMind/res/raw/fp_start_pom_video.mp4
Binary files differ
diff --git a/FairphonePeaceOfMind/res/values-de/strings.xml b/FairphonePeaceOfMind/res/values-de/strings.xml
new file mode 100644
index 0000000..d75649a
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values-de/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="widget_enjoy_some_peace">GENIESSEN SIE DIE RUHE</string>
+    <string name="at">IN</string>
+    <string name="peace">Ruhe</string>
+    
+    <string name="help_string_1">Unsere Abhängigkeit von Handys wächst täglich, da unsere Leben immer stärker miteinander verbunden sind\n\nMöchten Sie die Verbindung wieder trennen, wenn auch nur für einen Moment?</string>
+    <string name="help_string_2">Ihr Handy geht in den Ruhemodus und trennt sich von der Welt: keine E-Mails, keine Status-Updates, keine SMS und keine Anrufe</string>
+    <string name="help_string_3">Wählen Sie, wie lange Sie getrennt sein möchten (bis zu 3 Stunden)\n\nWährenddessen können Sie immer noch Games spielen oder Apps offline benutzen</string>
+    
+    <string name="enjoy">Geniessen</string>
+    <string name="some">Sie</string>
+    <string name="de">Die</string>
+    <string name="to_m">Bis</string>    
+    <string name="to_h">Bis</string>
+    <string name="hour_separator">h</string>
+    
+    <string name="peace_on_notification">In ruhe</string>
+    <string name="peace_off_notification">Peace of Mind ist aus</string>
+        
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values-es/strings.xml b/FairphonePeaceOfMind/res/values-es/strings.xml
new file mode 100644
index 0000000..c621d40
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values-es/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="widget_enjoy_some_peace">Disfruta de un poco de paz</string>
+    <string name="at">En</string>
+    <string name="peace">Paz</string>
+    
+    <string name="help_string_1">A medida que nuestras vidas están más conectadas, aumenta nuestra dependencia de los móviles\n\nTe gustaría sentirte desconectado, aunque fuera sólo por un momento?</string>
+    <string name="help_string_2">Tu teléfono se quedará en silencio y se desconectará del mundo: sin e-mail, sin redes sociales, sin mensajes y sin llamadas</string>
+    <string name="help_string_3">Decide cuánto tiempo te gustaría desconectarte. Hasta 3 horas!\n\nMientras, puedes seguir jugando, leyendo o usando aplicaciones conexión</string>
+    
+    <string name="enjoy">Disfruta</string>
+    <string name="some">poco</string>
+    <string name="um">un</string>
+    <string name="to_m">de</string>    
+    <string name="to_h">de</string>
+    <string name="hour_separator">h</string>
+    
+    <string name="peace_on_notification">En paz</string>
+    <string name="peace_off_notification">Peace of Mind está desconectado</string>
+    
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values-fr/strings.xml b/FairphonePeaceOfMind/res/values-fr/strings.xml
new file mode 100644
index 0000000..428789f
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values-fr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="widget_enjoy_some_peace">Missing translation</string>
+    <string name="at">De</string>
+    <string name="peace">tranquillité</string>
+    
+    <string name="help_string_1">Nous devenons plus conscients de nos téléphones alors que nos vies deviennent de plus en plus connectées\n\nAimeriez-vous pouvoir vous déconnecter, ne serait-ce que pour quelques heures?</string>
+    <string name="help_string_2">Votre téléphone passe en mode silencieux et se déconnecte du reste du monde: plus de courriels, de mises-à-jour de statut, de textos ou d\'appels téléphoniques</string>
+    <string name="help_string_3">Choisissez votre temps de déconnexion (jusqu\'à 3 heures)\n\nPendant ce temps, vous pouvez quand même vous divertir avec les jeux ou utiliser les applications hors ligne</string>
+    
+    <string name="enjoy">Profitez</string>
+    <string name="some">moment</string>
+    <string name="to_widget">d\'un</string>
+    <string name="de">de</string>
+    <string name="to_m">de</string>    
+    <string name="to_h">des</string>
+    <string name="hour_separator">h</string>
+    
+    <string name="peace_on_notification">En tranquillité</string>
+    <string name="peace_off_notification">L’application Peace of Mind est desactivée</string>
+    
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values-nl/strings.xml b/FairphonePeaceOfMind/res/values-nl/strings.xml
new file mode 100644
index 0000000..7ae0cff
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values-nl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="widget_enjoy_some_peace">GENIET VAN DE RUST</string>
+    <string name="at"></string>
+    <string name="peace">Rust</string>
+    
+    <string name="help_string_1">Onze levens worden in toenemende mate met elkaar verbonden en we worden ons steeds bewuster van onze telefoon\n\nWil je offline, al is het voor even?</string>
+    <string name="help_string_2">Je telefoon zal op stil gaan en de wereld voor even achter zich laten: geen e-mail, geen status updates, geen SMS en geen belletjes</string>
+    <string name="help_string_3">Bepaal hoe lang jij ‘uit’ wil staan (tot wel 3 uur)\n\nTussendoor spellen spelen is mogelijk en het offline gebruik van applicaties ook </string>
+    
+    <string name="enjoy">Geniet</string>
+    <string name="some">Van</string>
+    <string name="de">de</string>
+    <string name="to_m">Tot</string>    
+    <string name="to_h">Tot</string>
+    <string name="hour_separator">u</string>
+    
+    <string name="peace_on_notification">In rust</string>
+    <string name="peace_off_notification">Peace of Mind staat uit</string>
+    
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values-pt/strings.xml b/FairphonePeaceOfMind/res/values-pt/strings.xml
new file mode 100644
index 0000000..70c02a6
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="widget_enjoy_some_peace">Disfrute de um pouco de paz</string>
+    <string name="at">Em</string>
+    <string name="peace">Paz</string>
+    
+    <string name="help_string_1">Dependemos cada vez mais dos telefones à medida que as nossas vidas se tornam mais ligadas\n\nGostaria de se sentir desligado outra vez, só por um momento?</string>
+    <string name="help_string_2">O seu telemóvel vai ficar silencioso e desligar-se do mundo: sem e-mail, sem redes sociais, sem mensagens e sem chamadas</string>
+    <string name="help_string_3">Escolha quanto tempo quer estar desligado, até 3 horas\n\nNo entanto, ainda pode jogar ou usar aplicações off-line</string>
+    
+    <string name="enjoy">Disfrute</string>
+    <string name="some">pouco</string>
+    <string name="um">um</string>
+    <string name="to_m">De</string>    
+    <string name="to_h">De</string>
+    <string name="hour_separator">h</string>
+    
+    <string name="peace_on_notification">Em paz</string>
+    <string name="peace_off_notification">Peace of Mind está desligado</string>
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values/colors.xml b/FairphonePeaceOfMind/res/values/colors.xml
new file mode 100644
index 0000000..be75c4b
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values/colors.xml
@@ -0,0 +1,22 @@
+<resources>
+
+    <!-- BASE COLORS -->
+    <color name="white">#FFFFFF</color>
+    <color name="black">#000000</color>
+    <color name="grey">#808080</color>
+    <color name="grey_text">#dadada</color>
+    <color name="grey_text_to">#878787</color>
+    <color name="blue">#5dfffe</color>
+    <color name="blue_grey">#92a6a6</color>
+    <color name="blue_alpha">#AA5dfffe</color>
+    <color name="blue_green">#9fe0e0</color>
+
+    <!-- TRANSPARENCY -->
+    <color name="transparent">#00ffffff</color>
+    <color name="alpha_white">#55ffffff</color>
+    <color name="alpha_black">#66000000</color>
+
+    <!-- BACKGROUND -->
+    <color name="background">#fcfcfc</color>
+
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values/dimens.xml b/FairphonePeaceOfMind/res/values/dimens.xml
new file mode 100644
index 0000000..55c1e59
--- /dev/null
+++ b/FairphonePeaceOfMind/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>
diff --git a/FairphonePeaceOfMind/res/values/strings.xml b/FairphonePeaceOfMind/res/values/strings.xml
new file mode 100644
index 0000000..7ea0b40
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">Peace of Mind</string>
+    <string name="peace_of_mind_widget">Peace of Mind</string>
+    
+    <string name="widget_enjoy_some_peace">Enjoy some Peace</string>
+    <string name="at">At</string>
+    <string name="peace">Peace</string>
+    
+    <string name="help_string_1">We become more conscious of our phones as our lives become increasingly connected\n\nWould you like to disconnect, if only for a moment?</string>
+    <string name="help_string_2">Your phone will go silent and disconnect from the world: no e-mail, no status updates, no SMS and no phone calls</string>
+    <string name="help_string_3">Choose how long you wish to disconnect (up to 3 hours)\n\nMeanwhile, you can still play games or use off-line apps</string>
+    
+    <string name="enjoy">Enjoy</string>
+    <string name="some">Some</string>
+    <string name="to_m">To</string>    
+    <string name="to_h">To</string>
+    <string name="hour_separator">h</string>
+    
+    <string name="peace_on_notification">At peace</string>
+    <string name="peace_off_notification">Peace of Mind is off</string>
+    
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/values/styles.xml b/FairphonePeaceOfMind/res/values/styles.xml
new file mode 100644
index 0000000..cfcbed9
--- /dev/null
+++ b/FairphonePeaceOfMind/res/values/styles.xml
@@ -0,0 +1,145 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="AppTheme" parent="@android:style/Theme.Holo.NoActionBar">
+        <!-- <item name="android:windowBackground">@android:color/transparent</item> -->
+        <!-- <item name="android:windowIsTranslucent">true</item> -->
+    </style>
+
+    <style name="TotalTimeText">
+        <item name="android:textSize">33sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:textColor">@color/blue_green</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="TimeText">
+        <item name="android:textSize">20sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="ToText">
+        <item name="android:textSize">18.5sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="ToTimeText">
+        <item name="android:textSize">18.5sp</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="AtText">
+        <item name="android:textSize">16sp</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="PeaceText">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <!-- WIDGET OFF -->
+
+    <style name="WidgetOffLightText">
+        <item name="android:textSize">17.3sp</item>
+        <item name="android:textColor">@color/grey_text</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+    </style>
+
+    <style name="WidgetOffRegularText">
+        <item name="android:textSize">17.3sp</item>
+        <item name="android:textColor">@color/grey_text</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="WidgetOffBoldText">
+        <item name="android:textSize">17.3sp</item>
+        <item name="android:textColor">@color/grey_text</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+
+    <!-- WIDGET ON -->
+
+    <style name="WidgetOnLightText">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+    </style>
+
+    <style name="WidgetOnRegularText">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+    </style>
+
+    <style name="WidgetOnBoldText">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">@color/blue</item>
+        <item name="android:shadowColor">@color/alpha_black</item>
+        <item name="android:shadowDx">2</item>
+        <item name="android:shadowDy">2</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:shadowRadius">2</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/res/xml/widget_provider.xml b/FairphonePeaceOfMind/res/xml/widget_provider.xml
new file mode 100644
index 0000000..3b86dfc
--- /dev/null
+++ b/FairphonePeaceOfMind/res/xml/widget_provider.xml
@@ -0,0 +1,10 @@
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoAdvanceViewId="@+id/peace_of_mind_widget_layout"
+    android:initialLayout="@layout/widget"
+    android:label="AppWidget"
+    android:minHeight="215dp"
+    android:minWidth="300dp"
+    android:previewImage="@drawable/peace_widget_icon"
+    android:resizeMode="vertical"
+    android:updatePeriodMillis="0"
+    android:widgetCategory="home_screen|keyguard" />
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/AirplaneModeDeviceController.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/AirplaneModeDeviceController.java
new file mode 100644
index 0000000..926c7ef
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/AirplaneModeDeviceController.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.fairphone.peaceofmind;
+
+import android.content.Context;
+
+public class AirplaneModeDeviceController implements IDeviceController
+{
+
+    private Context mContext;
+
+    AirplaneModeDeviceController(Context context)
+    {
+
+        if (context == null)
+        {
+            throw new IllegalArgumentException("Context cannot be null");
+        }
+
+        mContext = context;
+    }
+
+    @Override
+    public void startPeaceOfMind()
+    {
+
+        if (!AirplaneModeToggler.isAirplaneModeOn(mContext))
+        {
+             AirplaneModeToggler.setAirplaneModeOn(mContext);
+        }
+    }
+
+    @Override
+    public void endPeaceOfMind()
+    {
+
+        if (AirplaneModeToggler.isAirplaneModeOn(mContext))
+        {
+             AirplaneModeToggler.setAirplaneModeOff(mContext);
+        }
+    }
+
+    @Override
+    public void screenOffDevice()
+    {
+
+    }
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/AirplaneModeToggler.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/AirplaneModeToggler.java
new file mode 100644
index 0000000..6e9cc85
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/AirplaneModeToggler.java
@@ -0,0 +1,74 @@
+/*

+ * 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 org.fairphone.peaceofmind;

+

+import android.content.Context;

+import android.content.Intent;

+import android.os.Build;

+import android.provider.Settings;

+

+public class AirplaneModeToggler {

+	

+	public static final String PEACE_OF_MIND_TOGGLE = "PEACE_OF_MIND_TOGGLE";

+

+	public static boolean isAirplaneModeOn(Context context) {

+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

+            return Settings.System.getInt(context.getContentResolver(), 

+                    Settings.System.AIRPLANE_MODE_ON, 0) != 0;          

+        } else {

+            return Settings.Global.getInt(context.getContentResolver(), 

+                    Settings.Global.AIRPLANE_MODE_ON, 0) != 0;

+        }       

+    }

+	

+	public static void setAirplaneModeOn(Context context) {

+		setAirplaneModeSettings(context, 1);

+		sendAirplaneModeIntent(context, true);

+	}

+	

+	public static void setAirplaneModeOff(Context context) {

+		setAirplaneModeSettings(context, 0);

+		sendAirplaneModeIntent(context, false);

+	}

+	

+	public static void toggleAirplaneMode(Context context) {

+        boolean isEnabled = isAirplaneModeOn(context);

+        // Toggle airplane mode.

+        setAirplaneModeSettings(context, isEnabled?0:1);

+        // Post an intent to reload.

+        sendAirplaneModeIntent(context, !isEnabled);

+    }

+    

+    private static void setAirplaneModeSettings(Context context, int value) {

+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

+            Settings.System.putInt(

+                      context.getContentResolver(),

+                      Settings.System.AIRPLANE_MODE_ON, value);

+        } else {

+            Settings.Global.putInt(

+                      context.getContentResolver(),

+                      Settings.Global.AIRPLANE_MODE_ON, value);

+        }       

+    }

+    

+    private static void sendAirplaneModeIntent(Context context,

+			boolean isEnabled) {

+		Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);

+        intent.putExtra("state", isEnabled);

+        intent.putExtra(PEACE_OF_MIND_TOGGLE, true);

+        context.sendBroadcast(intent);

+	}

+}

diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/IDeviceController.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/IDeviceController.java
new file mode 100644
index 0000000..9a145c6
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/IDeviceController.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.fairphone.peaceofmind;
+
+public interface IDeviceController {
+
+	void startPeaceOfMind();
+
+	void endPeaceOfMind();
+
+	void screenOffDevice();
+
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindActivity.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindActivity.java
new file mode 100644
index 0000000..78fb607
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindActivity.java
@@ -0,0 +1,774 @@
+/*
+ * 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 org.fairphone.peaceofmind;
+
+import org.fairphone.fairphonepeaceofmindapp.R;
+import org.fairphone.peaceofmind.data.PeaceOfMindStats;
+import org.fairphone.peaceofmind.ui.VerticalScrollListener;
+import org.fairphone.peaceofmind.ui.VerticalSeekBar;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.RelativeLayout.LayoutParams;
+import android.widget.TextView;
+import android.widget.VideoView;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class PeaceOfMindActivity extends Activity implements VerticalScrollListener, PeaceOfMindApplicationBroadcastReceiver.Listener, OnPreparedListener, OnCompletionListener
+{
+    public static String START_PEACE_OF_MIND = "START_PEACE_OF_MIND";
+    public static String END_PEACE_OF_MIND = "END_PEACE_OF_MIND";
+    public static String UPDATE_PEACE_OF_MIND = "UPDATE_PEACE_OF_MIND";
+    public static final String TIMER_TICK = "TIMER_TICK";
+    public static int count = 0;
+
+    private static final float INITIAL_PERCENTAGE = 0.1f;
+    public static final int MINUTE = 60 * 1000;
+    public static final int HOUR = 60 * MINUTE;
+    protected static final String TAG = PeaceOfMindActivity.class.getSimpleName();
+    public static final String BROADCAST_TARGET_PEACE_OF_MIND = "BROADCAST_TARGET_PEACE_OF_MIND";
+    private TextView mTotalTimeText;
+
+    private LinearLayout mCurrentTimeGroup;
+    private TextView mCurrentTimeText;
+    private LinearLayout mCurrentToTimeGroup;
+    private TextView mCurrentToTimeText;
+    private TextView mCurrentToText;
+
+    private TextView mCurrentTimeAtText;
+    private TextView mCurrentTimePEACEText;
+    private LinearLayout mCurrentTimeInPeaceText;
+    private VerticalSeekBar mVerticalSeekBar;
+    private View mProgressView;
+    private Button mHelpButton;
+    private View mSeekbarBackgroundOff;
+    private View mSeekbarBackgroundOn;
+
+    private FrameLayout mHelpHolder;
+    private LinearLayout mHelpLayout;
+    private Button mCloseButton;
+
+    private VideoView mVideo;
+
+    private PeaceOfMindApplicationBroadcastReceiver mBroadCastReceiver;
+    private SharedPreferences mSharedPreferences;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        setupLayout();
+
+        registerForPeaceOfMindBroadCasts();
+
+        setupBroadCastReceiverAlarm();
+    }
+
+    private void loadAvailableData()
+    {
+        PeaceOfMindStats currentStats = PeaceOfMindStats.getStatsFromSharedPreferences(mSharedPreferences);
+
+        mVerticalSeekBar.setThumb(getResources().getDrawable(currentStats.mIsOnPeaceOfMind ? R.drawable.seekbar_thumb_on : R.drawable.seekbar_thumb_off));
+        mVerticalSeekBar.setThumbOffset(0);
+        if (currentStats.mIsOnPeaceOfMind)
+        {
+            float targetTimePercent = (float) currentStats.mCurrentRun.mTargetTime / (float) PeaceOfMindStats.MAX_TIME;
+
+            mVerticalSeekBar.setInvertedProgress((int) (targetTimePercent * mVerticalSeekBar.getHeight()));
+
+            updateTextForNewTime(currentStats.mCurrentRun.mPastTime, currentStats.mCurrentRun.mTargetTime);
+            updateTimeTextLabel(targetTimePercent * 100);
+            updateScreenTexts();
+        }
+        else
+        {
+            mTotalTimeText.setText(generateStringTimeFromMillis(0, true));
+            mCurrentTimeText.setText(generateStringTimeFromMillis(0, true));
+        }
+
+        updateBackground(currentStats.mIsOnPeaceOfMind);
+        mVideo.setBackgroundResource(currentStats.mIsOnPeaceOfMind ? R.drawable.background_on_repeat : R.drawable.background_off_repeat);
+    }
+
+    private void updateScreenTexts()
+    {
+        PeaceOfMindStats currentStats = PeaceOfMindStats.getStatsFromSharedPreferences(mSharedPreferences);
+
+        int blue = getResources().getColor(R.color.blue);
+        int grey = getResources().getColor(R.color.blue_grey);
+
+        if (currentStats.mIsOnPeaceOfMind)
+        {
+            // current time is blue
+            mCurrentTimeText.setTextColor(blue);
+            mCurrentTimeAtText.setTextColor(blue);
+            mCurrentTimePEACEText.setTextColor(blue);
+
+            mCurrentTimeText.setAlpha(1.0f);
+            mCurrentTimeAtText.setAlpha(1.0f);
+            mCurrentTimePEACEText.setAlpha(1.0f);
+
+            mCurrentToTimeGroup.setVisibility(View.VISIBLE);
+            
+            mSeekbarBackgroundOff.setVisibility(View.GONE);
+            mSeekbarBackgroundOn.setVisibility(View.VISIBLE);
+        }
+        else
+        {
+            // show the current time and text at grey
+            mCurrentTimeText.setTextColor(grey);
+            mCurrentTimeAtText.setTextColor(grey);
+            mCurrentTimePEACEText.setTextColor(grey);
+
+            mCurrentTimeText.setAlpha(0.5f);
+            mCurrentTimeAtText.setAlpha(0.5f);
+            mCurrentTimePEACEText.setAlpha(0.5f);
+
+            mCurrentToTimeGroup.setVisibility(View.INVISIBLE);
+            
+            mSeekbarBackgroundOff.setVisibility(View.VISIBLE);
+            mSeekbarBackgroundOn.setVisibility(View.GONE);
+        }
+
+        if (mTotalTimeText.getVisibility() == View.VISIBLE)
+        {
+        	//hide the current time group when the target time approaches 
+        	//TODO: Fix the ugly magical numbers
+        	float position = mCurrentTimeGroup.getY() - mTotalTimeText.getY();
+            float alpha = (position < 500) ? (10.0f * (position-50) / 100.0f) : 1.0f;
+            mCurrentTimeGroup.setAlpha(alpha);
+            mCurrentTimeInPeaceText.setAlpha(alpha);
+        }
+        else
+        {
+        	if(mCurrentTimeGroup.getAlpha() != 1.0f ){
+        		if(!currentStats.mIsOnPeaceOfMind){
+	        		Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.target_time_fade_in_fast);
+	        		mCurrentTimeGroup.startAnimation(fadeIn);
+	        		mCurrentTimeInPeaceText.startAnimation(fadeIn);
+        		}
+	            mCurrentTimeGroup.setAlpha(1.0f);
+	            mCurrentTimeInPeaceText.setAlpha(1.0f);
+        	}
+        }
+    }
+
+    private void updateBackground(boolean on)
+    {
+    	View backgroundOverlay = findViewById(R.id.backgroundOverlay);
+        
+        int backgroundDrawableId = on ? R.drawable.background_on_repeat : R.drawable.background_off_repeat;
+        
+        // setup the background
+        backgroundOverlay.setBackgroundResource(backgroundDrawableId);
+    }
+
+    @Override
+    protected void onResume()
+    {
+        super.onResume();
+
+        mVideo.setVisibility(View.INVISIBLE);
+        mVideo.stopPlayback();
+        
+        // load data from the shared preferences
+        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+        updateScreenTexts();
+    }
+
+    @Override
+    protected void onPause()
+    {
+        super.onPause();
+
+        if (isFinishing())
+        {
+            unRegisterForPeaceOfMindBroadCasts();
+        }
+    }
+
+    @Override
+    protected void onDestroy()
+    {
+        super.onDestroy();
+    }
+
+    private void setupLayout()
+    {
+        mTotalTimeText = (TextView) findViewById(R.id.timeTextTotal);
+
+        mCurrentTimeGroup = (LinearLayout) findViewById(R.id.timeTextCurrentGroup);
+        mCurrentTimeText = (TextView) findViewById(R.id.timeTextCurrent);
+        mCurrentToTimeGroup = (LinearLayout) findViewById(R.id.toTimeGroup);
+        mCurrentToTimeText = (TextView) findViewById(R.id.toTimeText);
+        mCurrentToText = (TextView) findViewById(R.id.toText);
+
+        mCurrentTimeInPeaceText = (LinearLayout) findViewById(R.id.inPeaceTextCurrent);
+
+        mCurrentTimeAtText = (TextView) findViewById(R.id.currentAtText);
+        mCurrentTimePEACEText = (TextView) findViewById(R.id.currentPeaceText);
+
+        mVerticalSeekBar = (VerticalSeekBar) findViewById(R.id.verticalSeekBar);
+
+        mProgressView = (View) findViewById(R.id.progressView);
+        mHelpButton = (Button) findViewById(R.id.helpButton);
+        mSeekbarBackgroundOff = findViewById(R.id.seekbar_background_off);
+        mSeekbarBackgroundOn = findViewById(R.id.seekbar_background_on);
+
+        if (mVerticalSeekBar != null)
+        {
+            mVerticalSeekBar.setPeaceListener(this);
+        }
+
+        mHelpHolder = (FrameLayout) findViewById(R.id.helpHolder);
+        mHelpLayout = (LinearLayout) findViewById(R.id.helpLayout);
+        mCloseButton = (Button) findViewById(R.id.closeButton);
+
+        mHelpButton.setOnClickListener(new OnClickListener()
+        {
+            @Override
+            public void onClick(View v)
+            {
+                showHelp();
+            }
+        });
+
+        mCloseButton.setOnClickListener(new OnClickListener()
+        {
+            @Override
+            public void onClick(View v)
+            {
+                hideHelp();
+            }
+        });
+
+        mVideo = (VideoView) findViewById(R.id.pomVideo);
+
+        mVideo.setVisibility(View.INVISIBLE);
+
+        Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.fp_start_pom_video);
+
+        mVideo.setMediaController(null);
+        mVideo.requestFocus();
+        mVideo.setVideoURI(uri);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus)
+    {
+        super.onWindowFocusChanged(hasFocus);
+        loadAvailableData();
+    }
+
+    public void showHelp()
+    {
+        // disable the seekbar and help button when the help is showed
+        mVerticalSeekBar.setEnabled(false);
+        mHelpButton.setEnabled(false);
+
+        mHelpHolder.setVisibility(View.VISIBLE);
+        ObjectAnimator showIn = ObjectAnimator.ofFloat(mHelpHolder, "alpha", 0, 1);
+        showIn.setDuration(400);
+        showIn.start();
+
+        showIn.addListener(new AnimatorListener()
+        {
+            @Override
+            public void onAnimationStart(Animator animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animator animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation)
+            {
+                mHelpLayout.setVisibility(View.VISIBLE);
+                Interpolator decelerator = new DecelerateInterpolator();
+                ObjectAnimator translateIn = ObjectAnimator.ofFloat(mHelpLayout, "translationY", 900f, 0f);
+                translateIn.setInterpolator(decelerator);
+                translateIn.setDuration(400);
+                translateIn.start();
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation)
+            {
+            }
+        });
+
+    }
+
+    public void hideHelp()
+    {
+        ObjectAnimator showIn = ObjectAnimator.ofFloat(mHelpHolder, "alpha", 1, 0);
+        showIn.setDuration(400);
+        showIn.start();
+        showIn.addListener(new AnimatorListener()
+        {
+            @Override
+            public void onAnimationStart(Animator animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animator animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation)
+            {
+                mHelpButton.setEnabled(true);
+                mVerticalSeekBar.setEnabled(true);
+                mHelpHolder.setVisibility(View.GONE);
+                mHelpLayout.setVisibility(View.GONE);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation)
+            {
+            }
+        });
+
+    }
+    
+    @Override
+    public void onBackPressed() {
+        if (mHelpLayout.getVisibility() == View.VISIBLE) {
+            hideHelp();
+        } else {
+            // allows standard use of back button for page 1
+            super.onBackPressed();
+        }
+    }
+
+    private void registerForPeaceOfMindBroadCasts()
+    {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_STARTED);
+        filter.addAction(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_UPDATED);
+        filter.addAction(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_ENDED);
+        filter.addAction(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TICK);
+
+        mBroadCastReceiver = new PeaceOfMindApplicationBroadcastReceiver(this);
+        registerReceiver(mBroadCastReceiver, filter);
+    }
+
+    private void unRegisterForPeaceOfMindBroadCasts()
+    {
+        unregisterReceiver(mBroadCastReceiver);
+    }
+
+    private void setupBroadCastReceiverAlarm()
+    {
+        Log.d(TAG, "Setting the alarm tick");
+        Intent alarmIntent = new Intent(this, PeaceOfMindBroadCastReceiver.class);
+        alarmIntent.setAction(PeaceOfMindActivity.TIMER_TICK);
+
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+        AlarmManager alarmManager = (AlarmManager) this.getSystemService(this.ALARM_SERVICE);
+        alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), MINUTE, pendingIntent);
+    }
+
+    @Override
+    public void updateBarScroll(float progress)
+    {
+        // TODO: Put the 612 seekbar dimension in resources in dp if possible
+        int pos = (int) (612 - (612 / 100 * progress) + (progress / 2) - 53);
+
+        updateTimeTextLabel(progress);
+
+        if(mTotalTimeText.getVisibility() == View.INVISIBLE){
+        	mTotalTimeText.setVisibility(View.VISIBLE);
+        	Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.target_time_fade_in_fast);
+        	mTotalTimeText.startAnimation(fadeIn);
+        }
+        mTotalTimeText.setY(pos);
+
+        updateScreenTexts();
+    }
+
+    @Override
+    public synchronized void scrollEnded(float percentage)
+    {
+        if(mTotalTimeText.getVisibility() == View.VISIBLE){
+        	Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out_fast);
+	    	mTotalTimeText.startAnimation(fadeOut);
+	    	fadeOut.setAnimationListener(new AnimationListener()
+	        {
+	            @Override
+	            public void onAnimationStart(Animation animation)
+	            {
+	            }
+
+	            @Override
+	            public void onAnimationRepeat(Animation animation)
+	            {
+	            }
+
+	            @Override
+	            public void onAnimationEnd(Animation animation)
+	            {
+	    	    	mTotalTimeText.setVisibility(View.INVISIBLE);
+	    	    	updateScreenTexts();
+	            }
+	        });
+        }
+
+        long targetTime = roundToInterval((long) (percentage * PeaceOfMindStats.MAX_TIME));
+
+        Intent intent = new Intent(getApplicationContext(), PeaceOfMindBroadCastReceiver.class);
+        intent.setAction(PeaceOfMindActivity.UPDATE_PEACE_OF_MIND);
+
+        intent.putExtra(PeaceOfMindActivity.BROADCAST_TARGET_PEACE_OF_MIND, targetTime);
+
+        sendBroadcast(intent);
+    }
+
+    private long roundToInterval(long time)
+    {
+
+        int hours = (int) (time / HOUR);
+        int minutes = (int) ((time - hours * HOUR) / MINUTE);
+
+        int index = minutes % 10;
+
+        long newTime = 0;
+
+        switch (index)
+        {
+            case 1:
+            case 6:
+                newTime -= MINUTE;
+                break;
+            case 2:
+            case 7:
+                newTime -= 2 * MINUTE;
+                break;
+            case 3:
+            case 8:
+                newTime += 2 * MINUTE;
+                break;
+            case 4:
+            case 9:
+                newTime += MINUTE;
+                break;
+        }
+
+        Log.d(TAG, "Index: " + index + " - " + newTime);
+
+        return time + newTime;
+    }
+
+    private void updateTextForNewTime(long timePast, long targetTime)
+    {
+        long maxTime = PeaceOfMindStats.MAX_TIME;
+
+        float timePercentage = 0;
+
+        long timeUntilTarget = targetTime - timePast;
+        mCurrentTimeText.setText(generateStringTimeFromMillis(timeUntilTarget, timeUntilTarget <= 0));
+
+        int finalY = getCurrentProgressY(timePast, targetTime, maxTime, timePercentage);
+
+        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, finalY);
+
+        mProgressView.setLayoutParams(params);
+
+        float pos = mVerticalSeekBar.getHeight() - finalY - 12;
+        mCurrentTimeGroup.setY(pos);
+        mCurrentTimeInPeaceText.setY(pos);
+
+    }
+
+    private int getCurrentProgressY(long timePast, long targetTime, long maxTime, float timePercentage)
+    {
+        if (targetTime > 0)
+        {
+            timePercentage = (((float) timePast / (float) (maxTime)));
+        }
+
+        System.out.println("Updating time to " + timePercentage + " - " + timePast + " target time " + targetTime);
+
+        int finalY = (int) (0.8f * mVerticalSeekBar.getHeight() * timePercentage + (mVerticalSeekBar.getHeight() * INITIAL_PERCENTAGE));
+        return finalY;
+    }
+
+    private String generateStringTimeFromMillis(long timePast, boolean reset)
+    {
+    	int hours = 0;
+    	int minutes = 0;
+    	if(!reset){
+	        hours = (int) (timePast / HOUR);
+	        int timeInMinutes = (int) (timePast - hours * HOUR);
+	        
+	        if(hours == 0){
+	        	minutes = timeInMinutes - MINUTE > 0 ? timeInMinutes / MINUTE : 1;
+	        }else{
+	        	minutes = timeInMinutes / MINUTE;
+	        }
+    	}
+
+        String timeStr = String.format("%d%s%02d", hours, getResources().getString(R.string.hour_separator), minutes);
+        if(hours == 0){
+        	mCurrentToText.setText(getResources().getString(R.string.to_m));
+        }else{
+        	mCurrentToText.setText(getResources().getString(R.string.to_h));
+        }
+
+        return timeStr;
+    }
+
+    private void updateTimeTextLabel(float progress)
+    {
+        long targetTime = roundToInterval((long) (PeaceOfMindStats.MAX_TIME * progress / 100.0f));
+
+        mTotalTimeText.setText(generateStringTimeFromMillis(targetTime, targetTime == 0));
+        mCurrentToTimeText.setText(generateStringTimeFromMillis(targetTime, targetTime == 0));
+    }
+
+    @Override
+    public void peaceOfMindTick(long pastTime, long targetTime)
+    {
+        updateTextForNewTime(pastTime, targetTime);
+        updateScreenTexts();
+    }
+
+    static Semaphore mSemaphore = new Semaphore(1);
+    
+    @Override
+    public synchronized void peaceOfMindStarted(long targetTime)
+    {
+    	try {
+			mSemaphore.tryAcquire(1, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+    	
+        Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out_fast);
+        mSeekbarBackgroundOff.startAnimation(fadeOut);
+
+        Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in_fast);
+
+        mSeekbarBackgroundOn.startAnimation(fadeIn);
+
+        fadeIn.setAnimationListener(new AnimationListener()
+        {
+            @Override
+            public void onAnimationStart(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation)
+            {
+            	mSeekbarBackgroundOff.setVisibility(View.GONE);
+                mSeekbarBackgroundOn.setVisibility(View.VISIBLE);
+                
+                mSemaphore.release();
+            }
+        });
+
+        mVerticalSeekBar.setThumb(getResources().getDrawable(R.drawable.seekbar_thumb_on));
+        mVerticalSeekBar.setThumbOffset(0);
+
+        // fix thumb position
+        float targetTimePercent = (float) targetTime / (float) PeaceOfMindStats.MAX_TIME;
+
+        updateTextForNewTime(0, targetTime);
+        mVerticalSeekBar.setInvertedProgress((int) (targetTimePercent * mVerticalSeekBar.getHeight()));
+
+        startPeaceOfMindVideo();
+    }
+
+    private void startPeaceOfMindVideo()
+    {
+		mVideo.setBackgroundResource(R.drawable.background_off_repeat);
+        mVideo.setVisibility(View.VISIBLE);
+
+        mVideo.setOnPreparedListener(this);
+        mVideo.setOnCompletionListener(this);
+        mVideo.setDrawingCacheEnabled(true);
+    }
+
+    private void stopPeaceOfMindVideo()
+    {   
+		mVideo.removeCallbacks(null);
+		if(mVideo.getVisibility() != View.VISIBLE){
+			mVideo.setVisibility(View.VISIBLE);
+		}
+		
+		Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out_fast);
+		mVideo.startAnimation(fadeOut);
+
+		updateBackground(false);
+        fadeOut.setAnimationListener(new AnimationListener()
+        {
+            @Override
+            public void onAnimationStart(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation)
+            {
+            	mVideo.setVisibility(View.INVISIBLE);
+                mVideo.stopPlayback();
+            }
+        });
+    }
+
+    public void onPrepared(MediaPlayer mp)
+    {
+    	//Used to avoid the initial black flicker
+    	//remove the foreground 30 miliseconds after the video starts
+    	mVideo.postDelayed(new Runnable() {
+            public void run()
+            {
+                if (mVideo.isPlaying()){
+                	mVideo.setBackgroundResource(0);
+                    return;
+                }
+
+            }
+        }, 30);
+    	
+    	//Used to avoid the final black flicker
+    	//remove the foreground 20 miliseconds before the video ends
+    	mVideo.postDelayed(new Runnable() {
+            public void run()
+            {
+                if (mVideo.isPlaying()){
+                	mVideo.setBackgroundResource(R.drawable.background_on_repeat);		
+                    return;
+                }
+
+            }
+        }, mVideo.getDuration() - 20);
+    	mVideo.start();
+    }
+    
+
+	@Override
+	public void onCompletion(MediaPlayer mp) {
+		updateBackground(true);
+		mVideo.removeCallbacks(null);
+		mVideo.setBackgroundResource(R.drawable.background_on_repeat);
+		mVideo.stopPlayback();
+	}
+
+    @Override
+    public synchronized void peaceOfMindEnded()
+    {
+    	try {
+			mSemaphore.tryAcquire(1, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+    	
+        Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in_fast);
+
+        mSeekbarBackgroundOff.startAnimation(fadeIn);
+
+        Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out_fast);
+        mSeekbarBackgroundOn.startAnimation(fadeOut);
+
+        fadeIn.setAnimationListener(new AnimationListener()
+        {
+            @Override
+            public void onAnimationStart(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationRepeat(Animation animation)
+            {
+            }
+
+            @Override
+            public void onAnimationEnd(Animation animation)
+            {
+                mSeekbarBackgroundOff.setVisibility(View.VISIBLE);
+                mSeekbarBackgroundOn.setVisibility(View.GONE);
+
+            	updateScreenTexts();
+                stopPeaceOfMindVideo();
+                
+                mSemaphore.release();
+            }
+        });
+        
+    	updateScreenTexts();
+        mVerticalSeekBar.setThumb(getResources().getDrawable(R.drawable.seekbar_thumb_off));
+        mVerticalSeekBar.setThumbOffset(0);
+        mVerticalSeekBar.setInvertedProgress(0);
+        updateTextForNewTime(0, 0);
+        updateTimeTextLabel(0);
+
+        mTotalTimeText.setVisibility(View.INVISIBLE);
+    }
+
+    @Override
+    public void peaceOfMindUpdated(long pastTime, long newTargetTime)
+    {
+        updateTextForNewTime(pastTime, newTargetTime);
+    }
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver.java
new file mode 100644
index 0000000..953b064
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindApplicationBroadcastReceiver.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.fairphone.peaceofmind;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class PeaceOfMindApplicationBroadcastReceiver extends BroadcastReceiver {
+
+	public static String PEACE_OF_MIND_PAST_TIME = "PEACE_OF_MIND_PAST_TIME";
+	public static String PEACE_OF_MIND_TARGET_TIME = "PEACE_OF_MIND_TARGET_TIME";
+
+	public static String PEACE_OF_MIND_STARTED = "PEACE_OF_MIND_STARTED";
+	public static String PEACE_OF_MIND_UPDATED = "PEACE_OF_MIND_UPDATED";
+	public static String PEACE_OF_MIND_ENDED = "PEACE_OF_MIND_ENDED";
+	public static String PEACE_OF_MIND_TICK = "PEACE_OF_MIND_TICK";
+
+	public interface Listener {
+		void peaceOfMindTick(long pastTime, long targetTime);
+
+		void peaceOfMindStarted(long targetTime);
+
+		void peaceOfMindEnded();
+
+		void peaceOfMindUpdated(long currentTime, long newTargetTime);
+	}
+
+	private Listener mListener;
+
+	public PeaceOfMindApplicationBroadcastReceiver(Listener listener) {
+		mListener = listener;
+	}
+
+	@Override
+	public void onReceive(Context context, Intent intent) {
+
+		String action = intent.getAction();
+
+		if (PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TICK.equals(action)) {
+			mListener.peaceOfMindTick(intent.getExtras().getLong(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_PAST_TIME),
+									  intent.getExtras().getLong(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TARGET_TIME));
+		} else if (PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_STARTED.equals(action)) {
+			mListener.peaceOfMindStarted(intent.getExtras().getLong(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TARGET_TIME));
+		} else if (PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_UPDATED.equals(action)) {
+			mListener.peaceOfMindUpdated(intent.getExtras().getLong(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_PAST_TIME), 
+					intent.getExtras().getLong(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TARGET_TIME));
+		} else if (PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_ENDED.equals(action)) {
+			mListener.peaceOfMindEnded();
+		}
+	}
+
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindBroadCastReceiver.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindBroadCastReceiver.java
new file mode 100644
index 0000000..f8788d6
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindBroadCastReceiver.java
@@ -0,0 +1,267 @@
+/*
+ * 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 org.fairphone.peaceofmind;
+
+import org.fairphone.fairphonepeaceofmindapp.R;
+import org.fairphone.peaceofmind.data.PeaceOfMindRun;
+import org.fairphone.peaceofmind.data.PeaceOfMindStats;
+import org.fairphone.peaceofmind.widget.WidgetProvider;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
+import android.appwidget.AppWidgetManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v4.app.NotificationCompat;
+
+public class PeaceOfMindBroadCastReceiver extends BroadcastReceiver {
+
+	private static final String TAG = PeaceOfMindBroadCastReceiver.class.getSimpleName();
+
+	private static final int PEACE_OF_MIND_ON_NOTIFICATION = 0;
+	private static final int PEACE_OF_MIND_INTERRUPTED_NOTIFICATION = 1;
+
+	private PeaceOfMindStats mCurrentStats;
+	private SharedPreferences mSharedPreferences;
+
+	private Context mContext;
+	
+	private IDeviceController mDeviceController;
+
+	@Override
+	public void onReceive(Context context, Intent intent) {
+		mContext = context;
+		setupDeviceController();
+		
+		String action = intent.getAction();
+		if (action != null) {
+			// obtains the piece of mind data from shared preferences
+			mSharedPreferences = PreferenceManager
+					.getDefaultSharedPreferences(context);
+
+			mCurrentStats = PeaceOfMindStats
+					.getStatsFromSharedPreferences(mSharedPreferences);
+
+			if (action.equals(PeaceOfMindActivity.UPDATE_PEACE_OF_MIND)) {
+				updateTargetTime(intent);
+			} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
+				//only react to this if the app is running
+				if(mCurrentStats.mIsOnPeaceOfMind){
+					Bundle extras = intent.getExtras();
+					//if the intent was sent by the system end Peace of mind
+					if(!extras.containsKey(AirplaneModeToggler.PEACE_OF_MIND_TOGGLE)){
+						endPeaceOfMind(true);
+					}
+				}
+			}  else if (Intent.ACTION_SHUTDOWN.equals(action) && mCurrentStats.mIsOnPeaceOfMind) {
+				endPeaceOfMind(true);
+			} else {
+				performTimeTick();
+			}
+		} else {
+			return;
+		}
+		// update the widgets
+		updateWidget(context);
+
+	}
+	
+	private void setupDeviceController() {
+		mDeviceController = new AirplaneModeDeviceController(mContext);
+	}
+	
+	private void updateWidget(Context context) {
+        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+        int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, WidgetProvider.class));
+        if (appWidgetIds.length > 0)
+        {
+            new WidgetProvider().onUpdate(context, appWidgetManager, appWidgetIds);
+        }
+	}
+
+	private void performTimeTick() {
+		 long currentTime = System.currentTimeMillis();
+		
+		 long passedTime = 0;
+		
+		 if (mCurrentStats.mLastTimePinged != 0) {
+			 if(mCurrentStats.mLastTimePinged >= currentTime){
+				 endPeaceOfMind(false);
+				 return;
+			 }else{
+				 passedTime += currentTime - mCurrentStats.mLastTimePinged;
+			 }
+		 }
+		
+		 mCurrentStats.mLastTimePinged = currentTime;
+		 if (mCurrentStats.mIsOnPeaceOfMind) {
+			 
+			 mCurrentStats.mCurrentRun.mPastTime += passedTime;
+			 
+			 if(mCurrentStats.mCurrentRun.mPastTime >= mCurrentStats.mCurrentRun.mTargetTime){
+				 endPeaceOfMind(false);
+				 return;
+			 }
+			 
+			 
+			 
+		 } 
+		
+		 PeaceOfMindStats.saveToSharedPreferences(mCurrentStats, mSharedPreferences);
+		 
+		 // send broadcast to application receiver
+		 if (mCurrentStats.mIsOnPeaceOfMind) {
+			Intent tickIntent = new Intent(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TICK);
+			tickIntent.putExtra(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TARGET_TIME, mCurrentStats.mCurrentRun.mTargetTime);
+			tickIntent.putExtra(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_PAST_TIME, mCurrentStats.mCurrentRun.mPastTime);
+			
+			mContext.sendBroadcast(tickIntent);
+		 }
+	}
+
+	private void startPeaceOfMind(long targetTime) {
+		long currentTime = System.currentTimeMillis();
+		
+		mCurrentStats.mIsOnPeaceOfMind = true;
+		mCurrentStats.mLastTimePinged = currentTime;
+		
+		mCurrentStats.mCurrentRun = new PeaceOfMindRun();
+		mCurrentStats.mCurrentRun.mTimeStarted = currentTime;
+		mCurrentStats.mCurrentRun.mPastTime = 0;
+		mCurrentStats.mCurrentRun.mTargetTime = targetTime;
+		
+		PeaceOfMindStats.saveToSharedPreferences(mCurrentStats, mSharedPreferences);
+		
+		mDeviceController.startPeaceOfMind();
+		
+		// send broadcast to application receiver
+		Intent intent = new Intent(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_STARTED);
+		intent.putExtra(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TARGET_TIME, targetTime);
+		
+		mContext.sendBroadcast(intent);
+	}
+
+	private void updateTargetTime(Intent intent) {
+
+		long newTargetTime = intent.getExtras().getLong(
+				PeaceOfMindActivity.BROADCAST_TARGET_PEACE_OF_MIND);
+
+		if(newTargetTime == 0){
+			if(mCurrentStats.mIsOnPeaceOfMind){
+				endPeaceOfMind(false);
+			}
+		}else if (mCurrentStats.mIsOnPeaceOfMind) {
+			if (mCurrentStats.mCurrentRun.mPastTime < newTargetTime) {
+				mCurrentStats.mCurrentRun.mTargetTime = newTargetTime;
+				
+				PeaceOfMindStats.saveToSharedPreferences(mCurrentStats, mSharedPreferences);
+
+				Intent updateIntent = new Intent(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_UPDATED);
+				updateIntent.putExtra(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_TARGET_TIME, mCurrentStats.mCurrentRun.mTargetTime);
+				updateIntent.putExtra(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_PAST_TIME, mCurrentStats.mCurrentRun.mPastTime);
+				
+				mContext.sendBroadcast(updateIntent);
+			} else {
+				endPeaceOfMind(false);
+			}
+		}else {
+			startPeaceOfMind(newTargetTime);
+			setPeaceOfMindIconInNotificationBar(true, false); 
+		}
+	}
+
+	/**
+	 * Sets the Peace of mind icon on the notification bar
+	 * @param putIcon if true the icon is put otherwise it is removed
+	 * @param wasInterrupted when true, an extra notification is sent to inform the user that Peace of mind was ended
+	 */
+	private void setPeaceOfMindIconInNotificationBar(boolean putIcon, boolean wasInterrupted) {
+
+		NotificationManager manager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 
+		
+		if(putIcon){
+			
+			//just in case the user didn't clear it
+			manager.cancel(PEACE_OF_MIND_INTERRUPTED_NOTIFICATION);
+			
+			NotificationCompat.Builder builder =  
+		            new NotificationCompat.Builder(mContext)
+		            .setSmallIcon(R.drawable.peace_system_bar_icon)  
+		            .setContentTitle(mContext.getResources().getString(R.string.app_name))  
+		            .setContentText(mContext.getResources().getString(R.string.peace_on_notification));  
+	 
+		    Intent resultIntent = new Intent(mContext, PeaceOfMindActivity.class);
+	        TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
+	        // Adds the back stack for the Intent (but not the Intent itself)
+	        stackBuilder.addParentStack(PeaceOfMindActivity.class);
+	        // Adds the Intent that starts the Activity to the top of the stack
+	        stackBuilder.addNextIntent(resultIntent);
+	        PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
+	        
+		    builder.setContentIntent(resultPendingIntent);  
+	
+		    Notification notificationWhileRunnig = builder.build();
+		    notificationWhileRunnig.flags |= Notification.FLAG_NO_CLEAR;
+		    // Add notification   
+		    manager.notify(PEACE_OF_MIND_ON_NOTIFICATION, notificationWhileRunnig);
+		    
+		}else{
+			manager.cancel(PEACE_OF_MIND_ON_NOTIFICATION);
+			
+			//send a notification saying that the peace was ended 
+			if(wasInterrupted){
+				NotificationCompat.Builder builder =  
+			            new NotificationCompat.Builder(mContext)
+			            .setSmallIcon(R.drawable.peace_system_bar_icon)
+			            .setAutoCancel(true)
+			            .setContentTitle(mContext.getResources().getString(R.string.app_name))  
+			            .setContentText(mContext.getResources().getString(R.string.peace_off_notification))
+			            .setTicker(mContext.getResources().getString(R.string.peace_off_notification));
+
+				manager.notify(PEACE_OF_MIND_INTERRUPTED_NOTIFICATION, builder.build());
+			}
+		}
+	}
+
+	private void endPeaceOfMind(boolean wasInterrupted) {
+
+		mCurrentStats.mIsOnPeaceOfMind = false;
+		mCurrentStats.mLastTimePinged = 0;
+		
+		if(mCurrentStats.mCurrentRun != null){
+			mCurrentStats.mCurrentRun.mTimeStarted = 0;
+			mCurrentStats.mCurrentRun.mPastTime = 0;
+			mCurrentStats.mCurrentRun.mTargetTime = 0;
+			mCurrentStats.mCurrentRun = null;
+		}
+		
+		PeaceOfMindStats.saveToSharedPreferences(mCurrentStats, mSharedPreferences);
+
+		mDeviceController.endPeaceOfMind();
+		
+		Intent endIntent = new Intent(PeaceOfMindApplicationBroadcastReceiver.PEACE_OF_MIND_ENDED);
+		mContext.sendBroadcast(endIntent);
+		
+		setPeaceOfMindIconInNotificationBar(false, wasInterrupted);
+	}
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindIntents.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindIntents.java
new file mode 100644
index 0000000..67e68fd
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/PeaceOfMindIntents.java
@@ -0,0 +1,22 @@
+/*
+ * 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 org.fairphone.peaceofmind;
+
+public class PeaceOfMindIntents {
+	public static String PIECE_OF_MIND_APP  = "org.fairphone.peaceofmind.launchapp";
+	public static String STOP_PIECE_OF_MIND = "org.fairphone.peaceofmind.stoppeaceofmind";
+	
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/data/PeaceOfMindRun.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/data/PeaceOfMindRun.java
new file mode 100644
index 0000000..9282a3c
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/data/PeaceOfMindRun.java
@@ -0,0 +1,22 @@
+/*
+ * 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 org.fairphone.peaceofmind.data;
+
+public class PeaceOfMindRun {
+	public long mTimeStarted;
+	public long mTargetTime;
+	public long mPastTime;
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/data/PeaceOfMindStats.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/data/PeaceOfMindStats.java
new file mode 100644
index 0000000..7eb595e
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/data/PeaceOfMindStats.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.fairphone.peaceofmind.data;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+public class PeaceOfMindStats {
+	public static final long MAX_TIME = 3 * 60 * 60 * 1000;
+	
+	
+	private static final String PM_STATS_LAST_TIME_PINGED = "PM_STATS_LAST_TIME_PINGED";
+	private static final String PM_STATS_IS_IN_PEACE_OF_MIND = "PM_STATS_IS_IN_PEACE_OF_MIND";
+	private static final String PM_STATS_RUN_PAST_TIME = "PM_STATS_RUN_PAST_TIME";
+	private static final String PM_STATS_RUN_TARGET_TIME = "PM_STATS_RUN_TARGET_TIME";
+	private static final String PM_STATS_RUN_START_TIME = "PM_STATS_RUN_START_TIME";
+	
+	public boolean mIsOnPeaceOfMind;
+	public long mLastTimePinged;
+	
+	public PeaceOfMindRun mCurrentRun;
+	
+	public static PeaceOfMindStats getStatsFromSharedPreferences(SharedPreferences preferences){
+		PeaceOfMindStats stats = new PeaceOfMindStats();
+		
+		stats.mIsOnPeaceOfMind = preferences.getBoolean(PM_STATS_IS_IN_PEACE_OF_MIND, false);
+		stats.mLastTimePinged = preferences.getLong(PM_STATS_LAST_TIME_PINGED, 0);
+		
+		if(stats.mIsOnPeaceOfMind){
+			stats.mCurrentRun = new PeaceOfMindRun();
+			stats.mCurrentRun.mPastTime = preferences.getLong(PM_STATS_RUN_PAST_TIME, 0);
+			stats.mCurrentRun.mTargetTime = preferences.getLong(PM_STATS_RUN_TARGET_TIME, 0);
+			stats.mCurrentRun.mTimeStarted = preferences.getLong(PM_STATS_RUN_START_TIME, 0);
+		}
+		
+		return stats;
+	}
+
+	public static void saveToSharedPreferences(PeaceOfMindStats stats, SharedPreferences preferences) {
+		Editor editor = preferences.edit();
+		
+		editor.putBoolean(PM_STATS_IS_IN_PEACE_OF_MIND, stats.mIsOnPeaceOfMind);
+		editor.putLong(PM_STATS_LAST_TIME_PINGED, stats.mLastTimePinged);
+		
+		if(stats.mIsOnPeaceOfMind){
+			editor.putLong(PM_STATS_RUN_PAST_TIME, stats.mCurrentRun.mPastTime);
+			editor.putLong(PM_STATS_RUN_TARGET_TIME, stats.mCurrentRun.mTargetTime);
+			editor.putLong(PM_STATS_RUN_START_TIME, stats.mCurrentRun.mTimeStarted);
+		}
+		
+		editor.commit();
+	}
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/service/IPeaceOfMindTimeListener.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/service/IPeaceOfMindTimeListener.java
new file mode 100644
index 0000000..f792d6b
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/service/IPeaceOfMindTimeListener.java
@@ -0,0 +1,20 @@
+/*
+ * 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 org.fairphone.peaceofmind.service;
+
+public interface IPeaceOfMindTimeListener {
+	void updateTime(long millis);
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/service/IPeaceServiceController.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/service/IPeaceServiceController.java
new file mode 100644
index 0000000..ca0693a
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/service/IPeaceServiceController.java
@@ -0,0 +1,23 @@
+/*
+ * 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 org.fairphone.peaceofmind.service;
+
+public interface IPeaceServiceController {
+	
+	void startPeaceOfMind();
+	
+	void startWarOfMind();
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/ui/VerticalScrollListener.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/ui/VerticalScrollListener.java
new file mode 100644
index 0000000..dbb8eb7
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/ui/VerticalScrollListener.java
@@ -0,0 +1,23 @@
+/*
+ * 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 org.fairphone.peaceofmind.ui;
+
+public interface VerticalScrollListener {
+
+	void scrollEnded(float progress);
+
+	void updateBarScroll(float progress);
+}
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/ui/VerticalSeekBar.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/ui/VerticalSeekBar.java
new file mode 100644
index 0000000..9b6f75a
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/ui/VerticalSeekBar.java
@@ -0,0 +1,111 @@
+/*
+ * 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 org.fairphone.peaceofmind.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.SeekBar;
+
+public class VerticalSeekBar extends SeekBar {
+
+	private VerticalScrollListener _listener;
+
+	public VerticalSeekBar(Context context) {
+		super(context);
+	}
+
+	public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
+		super(context, attrs, defStyle);
+	}
+
+	public VerticalSeekBar(Context context, AttributeSet attrs) {
+		super(context, attrs);
+	}
+
+	public void setPeaceListener(VerticalScrollListener listener) {
+		_listener = listener;
+	}
+
+	public void onSizeChanged(int w, int h, int oldw, int oldh) {
+		super.onSizeChanged(h, w, oldh, oldw);
+	}
+
+	@Override
+	protected synchronized void onMeasure(int widthMeasureSpec,
+			int heightMeasureSpec) {
+		super.onMeasure(heightMeasureSpec, widthMeasureSpec);
+		setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
+	}
+
+	protected void onDraw(Canvas c) {
+		c.rotate(90);
+		c.translate(0, -getWidth());
+
+		super.onDraw(c);
+	}
+
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+		if (!isEnabled()) {
+			return false;
+		}
+
+		switch (event.getAction()) {
+		case MotionEvent.ACTION_DOWN:
+			updateScroll(event);
+			break;
+		case MotionEvent.ACTION_MOVE:
+			updateScroll(event);
+			break;
+		case MotionEvent.ACTION_UP:
+			updateScroll(event);
+			performScrollEnded();
+			break;
+
+		case MotionEvent.ACTION_CANCEL:
+			break;
+		}
+		return true;
+	}
+	
+	public void setInvertedProgress(int y){
+		int i = 0;
+		i = getMax() - (int) (getMax() * y / getHeight());
+		setProgress(100 - i);
+		onSizeChanged(getWidth(), getHeight(), 0, 0);
+	}
+
+	private void updateScroll(MotionEvent event) {
+		int i = 0;
+		i = getMax() - (int) (getMax() * event.getY() / getHeight());
+		setProgress(100 - i);
+		onSizeChanged(getWidth(), getHeight(), 0, 0);
+		
+		if (_listener != null) {
+			_listener.updateBarScroll(getProgress());
+		}
+	}
+
+	private void performScrollEnded() {
+		float progress = getProgress() / 100.0f;
+
+		if (_listener != null) {
+			_listener.scrollEnded(progress);
+		}
+	}
+}
\ No newline at end of file
diff --git a/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/widget/WidgetProvider.java b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/widget/WidgetProvider.java
new file mode 100644
index 0000000..17abf46
--- /dev/null
+++ b/FairphonePeaceOfMind/src/org/fairphone/peaceofmind/widget/WidgetProvider.java
@@ -0,0 +1,229 @@
+/*
+ * 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 org.fairphone.peaceofmind.widget;
+
+import org.fairphone.fairphonepeaceofmindapp.R;
+import org.fairphone.peaceofmind.data.PeaceOfMindStats;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+public class WidgetProvider extends AppWidgetProvider
+{
+    private static final int MINUTE = 60 * 1000;
+    private static final int HOUR = 60 * MINUTE;
+
+    private static final String TAG = WidgetProvider.class.getSimpleName();
+    private PeaceOfMindStats mCurrentStats;
+
+    @Override
+    public void onEnabled(Context context)
+    {
+        Log.d(TAG, "Fairphone - WidgetProvider Context is " + context);
+    }
+
+    @Override
+    public void onDisabled(Context context)
+    {
+        // Called once the last instance of your widget is removed from the
+        // homescreen
+        super.onDisabled(context);
+    }
+
+    @Override
+    public void onDeleted(Context context, int[] appWidgetIds)
+    {
+        // Widget instance is removed from the homescreen
+        Log.d(TAG, "onDeleted - " + appWidgetIds);
+    }
+
+    @Override
+    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)
+    {
+        updateUI(context, appWidgetManager, appWidgetId);
+
+        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
+    }
+
+    private void loadCurrentStats(Context context)
+    {
+        mCurrentStats = PeaceOfMindStats.getStatsFromSharedPreferences(PreferenceManager.getDefaultSharedPreferences(context));
+    }
+
+    private void updateUI(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
+    {
+        loadCurrentStats(context);
+
+        // get the widgets
+        RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget);
+
+        if (mCurrentStats.mIsOnPeaceOfMind)
+        {
+            updateWidgetForPeaceOfMind(context, widget);
+        }
+        else
+        {
+            updateWidgetForOffPeaceOfMind(context, widget);
+        }
+
+        // set the the app link
+        Intent intent = new Intent(context, org.fairphone.peaceofmind.PeaceOfMindActivity.class);
+        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
+
+        widget.setOnClickPendingIntent(R.id.peaceOfMindWidgetLayout, pendingIntent);
+
+        appWidgetManager.updateAppWidget(appWidgetId, widget);
+
+    }
+
+    private void updateWidgetForOffPeaceOfMind(Context context, RemoteViews widget)
+    {
+        // disable off peace of mind text
+        widget.setViewVisibility(R.id.onGroup, View.GONE);
+        widget.setViewVisibility(R.id.offGroup, View.VISIBLE);
+
+        Drawable background = context.getResources().getDrawable(R.drawable.widget_progressbar_background_off);
+        widget.setImageViewBitmap(R.id.progressBarBackground, ((BitmapDrawable) background).getBitmap());
+
+        int maxTime = (int) PeaceOfMindStats.MAX_TIME / 1000;
+
+        // set progress bar
+        widget.setProgressBar(R.id.progressBar, maxTime, 0, false);
+
+        widget.setViewPadding(R.id.timerTexts, 0, 0, 0, 0);
+        widget.setViewPadding(R.id.peaceOfMindText, 0, 0, 0, 0);
+
+        widget.setProgressBar(R.id.secondaryProgressBar, maxTime, 0, false);
+    }
+
+    private void setTimeText(Context context, long time, int hoursId, RemoteViews widgets)
+    {
+        int hours = (int) (time / HOUR);
+        int timeInMinutes = (int) (time - hours * HOUR);
+        int minutes = 0;
+        
+        if(hours == 0){
+        	minutes = timeInMinutes - MINUTE > 0 ? timeInMinutes / MINUTE : 1;
+        }else{
+        	minutes = timeInMinutes / MINUTE;
+        }
+
+        String timeStr = String.format("%d%s%02d", hours, context.getResources().getString(R.string.hour_separator), minutes);
+        if(hoursId == R.id.timeText){
+	        if(hours == 0){
+	        	widgets.setTextViewText(R.id.toText, context.getResources().getString(R.string.to_m));
+	        }else{
+	        	widgets.setTextViewText(R.id.toText, context.getResources().getString(R.string.to_h));
+	        }
+        }
+        widgets.setTextViewText(hoursId, timeStr);
+        
+    }
+
+    private void updateWidgetForPeaceOfMind(Context context, RemoteViews widget)
+    {
+        // disable off peace of mind text
+        widget.setViewVisibility(R.id.onGroup, View.VISIBLE);
+        widget.setViewVisibility(R.id.offGroup, View.GONE);
+
+        Drawable background = context.getResources().getDrawable(R.drawable.widget_progressbar_background_on);
+        widget.setImageViewBitmap(R.id.progressBarBackground, ((BitmapDrawable) background).getBitmap());
+
+        // set the time
+        long timeUntilTarget = mCurrentStats.mCurrentRun.mTargetTime - mCurrentStats.mCurrentRun.mPastTime;
+        setTimeText(context, timeUntilTarget, R.id.timeText, widget);
+        setTimeText(context, mCurrentStats.mCurrentRun.mTargetTime, R.id.totalTimeText, widget);
+
+        // set progress bar
+        int maxTime = (int) PeaceOfMindStats.MAX_TIME / 1000;
+        int progress = (int) mCurrentStats.mCurrentRun.mPastTime / 1000;
+        widget.setProgressBar(R.id.progressBar, maxTime, progress, false);
+
+        //225 is the progress bar size in pixels
+        //TODO: Put the magical number in resources using dp if possible 
+        int progressText = (int) (225 * (mCurrentStats.mCurrentRun.mPastTime / 1000)) / maxTime;
+
+        int ajustedProgress = getajustedTextProgress(progress, progressText);
+        if (ajustedProgress > 0 && ajustedProgress < 215)
+        {
+            widget.setViewPadding(R.id.timerTexts, 0, 0, 0, ajustedProgress);
+            widget.setViewPadding(R.id.peaceOfMindText, 0, 0, 0, ajustedProgress);
+        }
+
+        int secondaryProgress = (int) mCurrentStats.mCurrentRun.mTargetTime / 1000;
+        widget.setProgressBar(R.id.secondaryProgressBar, maxTime, secondaryProgress, false);
+    }
+
+    //this is used to make the text go up aligned with progress bar position
+    //TODO:Change the magical numbers to dp if possible
+	private int getajustedTextProgress(int progress, int progressText) {
+		long maxTimeSeconds = PeaceOfMindStats.MAX_TIME/1000;
+		int ajustedProgress = 0;
+		if(progress <= (maxTimeSeconds/4)){
+			ajustedProgress = progressText - 40;
+		}
+		else if(progress <= (maxTimeSeconds/2)){
+			ajustedProgress = progressText - 35;
+		}else if(progress <= (maxTimeSeconds/1.5)){
+			ajustedProgress = progressText - 25;
+		}else{
+			ajustedProgress = progressText - 15;
+		}
+		return ajustedProgress;
+	}
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
+     * android.appwidget.AppWidgetManager, int[])
+     * 
+     * OnUpdate ==============================================================
+     * context The Context in which this receiver is running. appWidgetManager A
+     * AppWidgetManager object you can call updateAppWidget(ComponentName,
+     * RemoteViews) on. appWidgetIds The appWidgetIds for which an update is
+     * needed. Note that this may be all of the AppWidget instances for this
+     * provider, or just a subset of them.
+     */
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
+    {
+        super.onUpdate(context, appWidgetManager, appWidgetIds);
+        // Called in response to the ACTION_APPWIDGET_UPDATE broadcast when this
+        // AppWidget provider
+        // is being asked to provide RemoteViews for a set of AppWidgets.
+        // Override this method to implement your own AppWidget functionality.
+
+        // iterate through every instance of this widget
+        // remember that it can have more than one widget of the same type.
+        for (int i = 0; i < appWidgetIds.length; i++)
+        { 
+            updateUI(context, appWidgetManager, appWidgetIds[i]);
+        }
+
+    }
+}
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();
+        }
+    }
+    
+    
+    
+}