Import the app.

Change-Id: I79d3421ecac1a5258ed4bfe7703479c225d2fc1e
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..3f9691c
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/.gitignore b/.gitignore
index 14e4dd1..1ec69fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,2 @@
-*.swp
-*~
-TAGS
-tags
-cscope.out
+bin/
+gen/
\ No newline at end of file
diff --git a/.project b/.project
new file mode 100644
index 0000000..584b9d9
--- /dev/null
+++ b/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>ADK 2012</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/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..f1a7d20
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.google.android.apps.adk2"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="10"
+        android:targetSdkVersion="15" />
+
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <uses-feature
+        android:name="android.hardware.usb.accessory"
+        android:required="true" />
+
+    <application
+        android:hardwareAccelerated="true"
+        android:icon="@drawable/ic_launcher_adk"
+        android:label="@string/app_short_name"
+        android:theme="@style/Theme.ADK2" >
+        <uses-library android:name="com.android.future.usb.accessory" />
+
+        <activity
+            android:name=".activity.ConnectActivity"
+            android:label="@string/app_short_name"
+            android:screenOrientation="portrait" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".activity.BTDeviceListActivity"
+            android:label="@string/bluetooth"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.HomeActivity"
+            android:label="@string/app_short_name"
+            android:screenOrientation="portrait" >
+        </activity>
+        <activity
+            android:name=".activity.AlarmActivity"
+            android:label="@string/alarm"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.ClockActivity"
+            android:label="@string/clock"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.VolumeActivity"
+            android:label="@string/volume"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.ColorActivity"
+            android:label="@string/color"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.ColorRGBActivity"
+            android:label="@string/color"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.ColorCameraActivity"
+            android:label="@string/color"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.ColorSensorActivity"
+            android:label="@string/color_sensor"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.ColorCombinationsActivity"
+            android:label="@string/color_combinations"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.BrightnessActivity"
+            android:label="@string/brightness"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.DisplayActivity"
+            android:label="@string/display"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.PresetsActivity"
+            android:label="@string/presets"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".activity.LicenseActivity"
+            android:label="@string/licenses"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name="USBAccessoryActivity"
+            android:label="@string/app_long_name"
+            android:launchMode="singleInstance"
+            android:taskAffinity="" >
+            <intent-filter>
+                <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
+                android:resource="@xml/usb_accessory_filter" />
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/lint.xml b/lint.xml
new file mode 100644
index 0000000..b0d4a8d
--- /dev/null
+++ b/lint.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+    <issue id="Deprecated" severity="informational" />
+</lint>
\ No newline at end of file
diff --git a/proguard-project.txt b/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/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/project.properties b/project.properties
new file mode 100644
index 0000000..e0a848d
--- /dev/null
+++ b/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:15
diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..99b9c53
--- /dev/null
+++ b/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_adk.png b/res/drawable-hdpi/ic_launcher_adk.png
new file mode 100644
index 0000000..dcff319
--- /dev/null
+++ b/res/drawable-hdpi/ic_launcher_adk.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_control_holo_dark.png b/res/drawable-hdpi/scrubber_control_holo_dark.png
new file mode 100644
index 0000000..5947ee1
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_control_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_horizontal_blue_holo_dark.9.png b/res/drawable-hdpi/scrubber_horizontal_blue_holo_dark.9.png
new file mode 100644
index 0000000..1dcd3b0
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_horizontal_blue_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_horizontal_green_holo_dark.9.png b/res/drawable-hdpi/scrubber_horizontal_green_holo_dark.9.png
new file mode 100644
index 0000000..6221a0f
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_horizontal_green_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_horizontal_holo_dark.9.png b/res/drawable-hdpi/scrubber_horizontal_holo_dark.9.png
new file mode 100644
index 0000000..6a162ed
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_horizontal_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_horizontal_red_holo_dark.9.png b/res/drawable-hdpi/scrubber_horizontal_red_holo_dark.9.png
new file mode 100644
index 0000000..b785ebd
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_horizontal_red_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_vertical_blue_holo_dark.9.png b/res/drawable-hdpi/scrubber_vertical_blue_holo_dark.9.png
new file mode 100644
index 0000000..5a22af5
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_vertical_blue_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_vertical_green_holo_dark.9.png b/res/drawable-hdpi/scrubber_vertical_green_holo_dark.9.png
new file mode 100644
index 0000000..1ebd9f6
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_vertical_green_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_vertical_red_holo_dark.9.png b/res/drawable-hdpi/scrubber_vertical_red_holo_dark.9.png
new file mode 100644
index 0000000..74800a4
--- /dev/null
+++ b/res/drawable-hdpi/scrubber_vertical_red_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..bb4cf8e
--- /dev/null
+++ b/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..831e794
--- /dev/null
+++ b/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_adk.png b/res/drawable-mdpi/ic_launcher_adk.png
new file mode 100644
index 0000000..3e7e712
--- /dev/null
+++ b/res/drawable-mdpi/ic_launcher_adk.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_control_holo_dark.png b/res/drawable-mdpi/scrubber_control_holo_dark.png
new file mode 100644
index 0000000..90ece2a
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_control_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_horizontal_blue_holo_dark.9.png b/res/drawable-mdpi/scrubber_horizontal_blue_holo_dark.9.png
new file mode 100644
index 0000000..3a7665b
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_horizontal_blue_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_horizontal_green_holo_dark.9.png b/res/drawable-mdpi/scrubber_horizontal_green_holo_dark.9.png
new file mode 100644
index 0000000..dac988a
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_horizontal_green_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_horizontal_holo_dark.9.png b/res/drawable-mdpi/scrubber_horizontal_holo_dark.9.png
new file mode 100644
index 0000000..ce62fbe
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_horizontal_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_horizontal_red_holo_dark.9.png b/res/drawable-mdpi/scrubber_horizontal_red_holo_dark.9.png
new file mode 100644
index 0000000..bd349fd
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_horizontal_red_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_vertical_blue_holo_dark.9.png b/res/drawable-mdpi/scrubber_vertical_blue_holo_dark.9.png
new file mode 100644
index 0000000..fd9ca52
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_vertical_blue_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_vertical_green_holo_dark.9.png b/res/drawable-mdpi/scrubber_vertical_green_holo_dark.9.png
new file mode 100644
index 0000000..f5cc83e
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_vertical_green_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_vertical_red_holo_dark.9.png b/res/drawable-mdpi/scrubber_vertical_red_holo_dark.9.png
new file mode 100644
index 0000000..26eaa3d
--- /dev/null
+++ b/res/drawable-mdpi/scrubber_vertical_red_holo_dark.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ab_rainbow_bg.9.png b/res/drawable-xhdpi/ab_rainbow_bg.9.png
new file mode 100644
index 0000000..7db3425
--- /dev/null
+++ b/res/drawable-xhdpi/ab_rainbow_bg.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/adk_outline.png b/res/drawable-xhdpi/adk_outline.png
new file mode 100644
index 0000000..a270793
--- /dev/null
+++ b/res/drawable-xhdpi/adk_outline.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_alarm.png b/res/drawable-xhdpi/ic_alarm.png
new file mode 100644
index 0000000..bebd61e
--- /dev/null
+++ b/res/drawable-xhdpi/ic_alarm.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brightness.png b/res/drawable-xhdpi/ic_brightness.png
new file mode 100644
index 0000000..d46da9f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brightness.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_clock.png b/res/drawable-xhdpi/ic_clock.png
new file mode 100644
index 0000000..524f073
--- /dev/null
+++ b/res/drawable-xhdpi/ic_clock.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_color.png b/res/drawable-xhdpi/ic_color.png
new file mode 100644
index 0000000..4de662c
--- /dev/null
+++ b/res/drawable-xhdpi/ic_color.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_display.png b/res/drawable-xhdpi/ic_display.png
new file mode 100644
index 0000000..867bfb3
--- /dev/null
+++ b/res/drawable-xhdpi/ic_display.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..42b2269
--- /dev/null
+++ b/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_adk.png b/res/drawable-xhdpi/ic_launcher_adk.png
new file mode 100644
index 0000000..c762de0
--- /dev/null
+++ b/res/drawable-xhdpi/ic_launcher_adk.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_lock.png b/res/drawable-xhdpi/ic_lock.png
new file mode 100644
index 0000000..bba0c72
--- /dev/null
+++ b/res/drawable-xhdpi/ic_lock.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_presets.png b/res/drawable-xhdpi/ic_presets.png
new file mode 100644
index 0000000..d8d6be8
--- /dev/null
+++ b/res/drawable-xhdpi/ic_presets.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_unlock.png b/res/drawable-xhdpi/ic_unlock.png
new file mode 100644
index 0000000..f8860a2
--- /dev/null
+++ b/res/drawable-xhdpi/ic_unlock.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_volume.png b/res/drawable-xhdpi/ic_volume.png
new file mode 100644
index 0000000..8e8784d
--- /dev/null
+++ b/res/drawable-xhdpi/ic_volume.png
Binary files differ
diff --git a/res/drawable/home_button_bg.xml b/res/drawable/home_button_bg.xml
new file mode 100644
index 0000000..2428828
--- /dev/null
+++ b/res/drawable/home_button_bg.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@color/home_button_pressed" />
+    <item android:drawable="@color/home_button_normal" />
+</selector>
\ No newline at end of file
diff --git a/res/layout/alert_dialog.xml b/res/layout/alert_dialog.xml
new file mode 100644
index 0000000..f8c0aed
--- /dev/null
+++ b/res/layout/alert_dialog.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView 
+        android:id="@+id/username_view"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginLeft="20dip"
+        android:layout_marginRight="20dip"
+        android:text="@string/set_bt_name_title"
+        android:gravity="left"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <EditText
+        android:id="@+id/btname_edit"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_marginLeft="20dip"
+        android:layout_marginRight="20dip"
+        android:scrollHorizontally="true"
+        android:autoText="false"
+        android:capitalize="none"
+        android:gravity="fill_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/color_camera.xml b/res/layout/color_camera.xml
new file mode 100644
index 0000000..87a9157
--- /dev/null
+++ b/res/layout/color_camera.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout 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"
+    >
+
+    <RelativeLayout
+        android:id="@+id/camera_frame"
+        android:layout_width="match_parent"
+        android:layout_height="300dip"
+        >
+        
+        <SurfaceView
+            android:id="@+id/camera_surface"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_centerInParent="true"
+            />
+        
+        <View tools:ignore="PxUsage"
+            android:layout_width="40px"
+            android:layout_height="40px"
+            android:layout_centerInParent="true"
+            android:background="#ff000000"
+            />
+
+        <View tools:ignore="PxUsage"
+            android:id="@+id/sample_preview"
+            android:layout_width="160px"
+            android:layout_height="160px"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:visible="false"
+            />
+        
+    </RelativeLayout>
+
+    <Button
+        android:id="@+id/color_sample_button"
+        android:layout_width="50dip"
+        android:layout_height="50dip"
+        android:layout_below="@+id/camera_frame"
+        android:layout_centerHorizontal="true"
+        />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/color_combinations.xml b/res/layout/color_combinations.xml
new file mode 100644
index 0000000..a29713f
--- /dev/null
+++ b/res/layout/color_combinations.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="25dip" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="64dp" >
+
+        <View
+            android:id="@+id/color_combo1"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@color/combination_color" />
+
+        <View
+            android:id="@+id/color_combo2"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@color/combination_color" />
+
+        <View
+            android:id="@+id/color_combo3"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@color/combination_color" />
+
+        <View
+            android:id="@+id/color_combo4"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@color/combination_color" />
+
+        <View
+            android:id="@+id/color_combo5"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@color/combination_color" />
+    </LinearLayout>
+
+    <RadioGroup
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/color_combination_group"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="25dip" >
+
+        <RadioButton
+            android:id="@+id/radio_monochromatic"
+            style="@android:style/TextAppearance.DeviceDefault.Large"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/monochromatic" />
+
+        <RadioButton
+            android:id="@+id/radio_analogous"
+            style="@android:style/TextAppearance.DeviceDefault.Large"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/analogous" />
+
+        <RadioButton
+            android:id="@+id/radio_triad"
+            style="@android:style/TextAppearance.DeviceDefault.Large"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/triad" />
+    </RadioGroup>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/color_rgb.xml b/res/layout/color_rgb.xml
new file mode 100644
index 0000000..6236391
--- /dev/null
+++ b/res/layout/color_rgb.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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:orientation="vertical"
+    android:padding="25dip"
+    tools:ignore="NestedWeights" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="25dip"
+        android:orientation="horizontal" >
+
+        <View
+            android:id="@+id/original_color"
+            android:layout_width="0dip"
+            android:layout_height="50dip"
+            android:layout_weight="1"
+            android:background="#ff0000" />
+
+        <View
+            android:id="@+id/new_color"
+            android:layout_width="0dip"
+            android:layout_height="50dip"
+            android:layout_weight="1"
+            android:background="#ffff00" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="25dip"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:id="@+id/color_hex"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1.5"
+            android:gravity="center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView
+            android:id="@+id/color_r"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView
+            android:id="@+id/color_g"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView
+            android:id="@+id/color_b"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+    </LinearLayout>
+
+    <com.google.android.apps.adk2.views.Slider
+        android:id="@+id/seek_bar_r"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="25dip" />
+
+    <com.google.android.apps.adk2.views.Slider
+        android:id="@+id/seek_bar_g"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="25dip" />
+
+    <com.google.android.apps.adk2.views.Slider
+        android:id="@+id/seek_bar_b"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="25dip" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/color_sensor.xml b/res/layout/color_sensor.xml
new file mode 100644
index 0000000..dcff0ae
--- /dev/null
+++ b/res/layout/color_sensor.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <View
+        android:layout_width="0dip"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:gravity="center" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="10dip"
+        android:gravity="center"
+        android:text="@string/capture_prompt"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <com.google.android.apps.adk2.views.ColorSensorView
+        android:id="@+id/color_sensor_view"
+        android:layout_width="200dip"
+        android:layout_height="200dip"
+        android:layout_gravity="center"
+        android:layout_margin="25dip"
+        android:gravity="center" />
+
+    <Button
+        android:id="@+id/color_sample_button"
+        android:layout_width="match_parent"
+        android:layout_height="80dip"
+        android:layout_margin="25dip"
+        android:gravity="center"
+        android:text="@string/capture" />
+
+    <View
+        android:layout_width="0dip"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:gravity="center" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/connect.xml b/res/layout/connect.xml
new file mode 100644
index 0000000..2aefb0f
--- /dev/null
+++ b/res/layout/connect.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="5dp" >
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/connect_please"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <ImageView
+        android:id="@+id/imageView1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:contentDescription="@string/adk_description"
+        android:src="@drawable/adk_outline" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+     <TextView
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_gravity="center_horizontal"
+         android:text="@string/plug_in_or_use_bluetooth"
+         android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <Button
+        android:id="@+id/connect_bluetooth_button"
+        android:layout_width="match_parent"
+        android:layout_height="80dip"
+        android:layout_margin="25dip"
+        android:gravity="center"
+        android:text="@string/bluetooth" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/device_list.xml b/res/layout/device_list.xml
new file mode 100644
index 0000000..866d36e
--- /dev/null
+++ b/res/layout/device_list.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/title_paired_devices"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/title_paired_devices"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:visibility="gone" />
+
+    <ListView
+        android:id="@+id/paired_devices"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/device_name.xml b/res/layout/device_name.xml
new file mode 100644
index 0000000..8fa358c
--- /dev/null
+++ b/res/layout/device_name.xml
@@ -0,0 +1,21 @@
+<?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:textSize="18sp"
+    android:padding="5dp"
+/>
\ No newline at end of file
diff --git a/res/layout/display.xml b/res/layout/display.xml
new file mode 100644
index 0000000..d30ad23
--- /dev/null
+++ b/res/layout/display.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/display_group"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="25dip" >
+
+    <!--
+  AdkShowAnimation,
+  AdkShowAccel,
+  AdkShowMag,
+  AdkShowTemp,
+  AdkShowHygro,
+  AdkShowBaro,
+  AdkShowProx,
+  AdkShowColor,
+    -->
+
+    <RadioButton
+        android:id="@+id/radio_animation"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/leds_animation" />
+
+    <RadioButton
+        android:id="@+id/radio_accell"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/accel" />
+
+    <RadioButton
+        android:id="@+id/radio_mag"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/mag" />
+
+    <RadioButton
+        android:id="@+id/radio_temperature"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/temperature" />
+
+    <RadioButton
+        android:id="@+id/radio_hygro"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/hygro" />
+
+    <RadioButton
+        android:id="@+id/radio_baro"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/baro" />
+
+    <RadioButton
+        android:id="@+id/radio_prox"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/prox" />
+
+    <RadioButton
+        android:id="@+id/radio_color"
+        style="@android:style/TextAppearance.DeviceDefault.Large"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/color" />
+    
+</RadioGroup>
\ No newline at end of file
diff --git a/res/layout/home.xml b/res/layout/home.xml
new file mode 100644
index 0000000..b0c5133
--- /dev/null
+++ b/res/layout/home.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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:orientation="vertical"
+    >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        >
+
+        <include
+            tools:ignore="NestedWeights"
+            layout="@layout/home_button"
+            android:id="@+id/clock_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+
+        <View tools:ignore="PxUsage"
+            android:layout_width="1px"
+            android:layout_height="match_parent"
+            android:background="@color/home_activity_divider"
+            />
+            
+        <include layout="@layout/home_button"
+            android:id="@+id/alarm_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+
+    </LinearLayout>
+
+    <View tools:ignore="PxUsage"
+        android:layout_width="match_parent"
+        android:layout_height="1px"
+        android:background="@color/home_activity_divider"
+        />
+ 
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        >
+
+        <include
+               tools:ignore="NestedWeights"
+            layout="@layout/home_button"
+            android:id="@+id/volume_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+
+        <View
+            tools:ignore="PxUsage"
+            android:layout_width="1px"
+            android:layout_height="match_parent"
+            android:background="@color/home_activity_divider"
+            />
+            
+        <include
+            layout="@layout/home_button"
+            android:id="@+id/color_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+        
+    </LinearLayout>
+
+    <View
+        tools:ignore="PxUsage"
+        android:layout_width="match_parent"
+        android:layout_height="1px"
+        android:background="@color/home_activity_divider"
+        />
+ 
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        >
+
+        <include
+            tools:ignore="NestedWeights"
+            layout="@layout/home_button"
+            android:id="@+id/brightness_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+
+        <View tools:ignore="PxUsage"
+            android:layout_width="1px"
+            android:layout_height="match_parent"
+            android:background="@color/home_activity_divider"
+            />
+            
+        <include
+            layout="@layout/home_button"
+            android:id="@+id/display_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+        
+    </LinearLayout>
+
+    <View
+        tools:ignore="PxUsage"
+        android:layout_width="match_parent"
+        android:layout_height="1px"
+        android:background="@color/home_activity_divider"
+        />
+ 
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        >
+
+        <include
+            tools:ignore="NestedWeights"
+            layout="@layout/home_button"
+            android:id="@+id/presets_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+
+        <View
+            tools:ignore="PxUsage"
+            android:layout_width="1px"
+            android:layout_height="match_parent"
+            android:background="@color/home_activity_divider"
+            />
+            
+        <include
+            layout="@layout/home_button"
+            android:id="@+id/lock_button"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            />
+        
+    </LinearLayout>
+
+    <View
+        tools:ignore="PxUsage"
+        android:layout_width="match_parent"
+        android:layout_height="1px"
+        android:background="@color/home_activity_divider"
+        />
+    
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/home_button.xml b/res/layout/home_button.xml
new file mode 100644
index 0000000..1854d55
--- /dev/null
+++ b/res/layout/home_button.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout 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:orientation="vertical"
+    android:background="@drawable/home_button_bg"
+    android:clickable="true"
+    >
+    
+    <ImageView tools:ignore="ContentDescription"
+        android:id="@+id/icon"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginBottom="14dip"
+        android:scaleType="center"
+        />
+
+    <TextView
+        android:id="@+id/label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="14dip"
+        android:textColor="@color/home_button_label"
+        />
+
+</RelativeLayout>
diff --git a/res/layout/licenses.xml b/res/layout/licenses.xml
new file mode 100644
index 0000000..7bd39d6
--- /dev/null
+++ b/res/layout/licenses.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/license_scroll"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/license_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+    </TextView>
+
+</ScrollView>
\ No newline at end of file
diff --git a/res/layout/preset_name_dialog.xml b/res/layout/preset_name_dialog.xml
new file mode 100644
index 0000000..339bb73
--- /dev/null
+++ b/res/layout/preset_name_dialog.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/preset_name_root_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="10dp" >
+
+    <TextView
+        android:id="@+id/preset_name_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/name"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <EditText
+        android:id="@+id/preset_name_edit"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:inputType="text" >
+
+        <requestFocus />
+    </EditText>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+
+        <Button
+            android:id="@+id/preset_edit_cancel"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@android:string/cancel" />
+
+        <Button
+            android:id="@+id/preset_edit_rename"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/rename" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/presets.xml b/res/layout/presets.xml
new file mode 100644
index 0000000..0a7d73a
--- /dev/null
+++ b/res/layout/presets.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="false"
+        android:choiceMode="multipleChoiceModal" />
+
+    <TextView
+        android:id="@android:id/empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/no_presets" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/seekbar_preference.xml b/res/layout/seekbar_preference.xml
new file mode 100644
index 0000000..2fc3a29
--- /dev/null
+++ b/res/layout/seekbar_preference.xml
@@ -0,0 +1,27 @@
+<?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="wrap_content"
+    android:paddingTop="10dip"
+    android:paddingLeft="8dip"
+    android:paddingBottom="14dip"
+    android:paddingRight="?android:attr/scrollbarSize"
+    >
+
+    <TextView android:id="@+android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        />
+
+    <SeekBar android:id="@+id/seekbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="12dip"
+        android:layout_below="@android:id/title"
+        android:layout_alignLeft="@android:id/title"
+        />
+</RelativeLayout>
diff --git a/res/layout/time_dialog.xml b/res/layout/time_dialog.xml
new file mode 100644
index 0000000..3ef9dd2
--- /dev/null
+++ b/res/layout/time_dialog.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    >
+    
+    <TimePicker android:id="@+id/time_picker"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/home_menu.xml b/res/menu/home_menu.xml
new file mode 100644
index 0000000..ca6d261
--- /dev/null
+++ b/res/menu/home_menu.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/disconnect_menu"
+        android:showAsAction="never"
+        android:title="@string/disconnect">
+    </item>
+    <item android:id="@+id/change_bt_name" android:title="@string/change_bt_name"></item><item
+        android:id="@+id/license_menu"
+        android:showAsAction="always"
+        android:title="@string/licenses">
+    </item>
+    
+
+</menu>
\ No newline at end of file
diff --git a/res/menu/list_select_menu.xml b/res/menu/list_select_menu.xml
new file mode 100644
index 0000000..8017a78
--- /dev/null
+++ b/res/menu/list_select_menu.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/delete_preset"
+        android:icon="@android:drawable/ic_menu_delete"
+        android:showAsAction="ifRoom"
+        android:title="@string/delete"/>
+
+    <item
+        android:id="@+id/edit_preset"
+        android:icon="@android:drawable/ic_menu_edit"
+        android:showAsAction="always"
+        android:title="@string/edit"/>
+
+</menu>
\ No newline at end of file
diff --git a/res/menu/presets_menu.xml b/res/menu/presets_menu.xml
new file mode 100644
index 0000000..56082b2
--- /dev/null
+++ b/res/menu/presets_menu.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/new_preset"
+        android:showAsAction="always"
+        android:title="@string/new_preset">
+    </item>
+
+</menu>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100644
index 0000000..88cb3d3
--- /dev/null
+++ b/res/values/arrays.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string-array name="alarm_sounds">
+        <item>Silent</item>
+        <item>Cesium</item>
+        <item>Fermium</item>
+        <item>Hassium</item>
+        <item>Neptunium</item>
+        <item>Nobelium</item>
+        <item>Plutonium</item>
+    </string-array>
+
+</resources>
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
new file mode 100644
index 0000000..3d5dbaf
--- /dev/null
+++ b/res/values/attrs.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources>
+    <declare-styleable name = "ActivityPreference">
+        <attr name="classname" format = "string"/>
+    </declare-styleable>
+
+    <declare-styleable name = "SeekBarPreference">
+        <attr name="max" format = "integer"/>
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..cb03548
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="window_background">#000000</color>
+
+    <color name="home_button_normal">#000000</color>
+    <color name="home_button_pressed">#257391</color>
+
+    <color name="home_activity_divider">#666666</color>
+    <color name="home_button_label">#eeeeee</color>
+
+    <color name="combination_color">#eeeeee</color>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..6e94c2b
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_short_name">ADK 2012</string>
+    <string name="app_long_name">ADK DemoKit 2012</string>
+    <string name="clock">Clock</string>
+    <string name="capture">Capture</string>
+    <string name="adk_description">A picture of the 2012 ADK.</string>
+    <string name="capture_prompt">When ready press the capture button below.</string>
+    <string name="alarm">Alarm</string>
+    <string name="volume">Volume</string>
+    <string name="color">Color</string>
+    <string name="color_sensor">Color sensor</string>
+    <string name="color_combinations">Color combinations</string>
+    <string name="brightness">Brightness</string>
+    <string name="bluetooth">Use Bluetooth</string>
+    <string name="display">Display</string>
+    <string name="presets">Presets</string>
+    <string name="locked">Locked</string>
+    <string name="unlocked">Unlocked</string>
+    <string name="time">Time</string>
+    <string name="accel">Acceleration</string>
+    <string name="temperature">Temperature</string>
+    <string name="hygro">Hygro</string>
+    <string name="leds_animation">LEDs animation</string>
+    <string name="baro">Pressure</string>
+    <string name="mag">Magnetic</string>
+    <string name="prox">Proximity</string>
+    <string name="no_presets">No presets</string>
+    <string name="new_preset">New preset</string>
+    <string name="name">Name</string>
+    <string name="delete">Delete</string>
+    <string name="edit">Edit</string>
+    <string name="rename">Rename</string>
+    <string name="cancel">Cancel</string>
+    <string name="create">Create</string>
+    <string name="disconnect">Disconnect</string>
+    <string name="title_paired_devices">Paired devices</string>
+    <string name="set">Set</string>
+    <string name="licenses">Licenses</string>
+    <string name="monochromatic">Monochromatic</string>
+    <string name="analogous">Analogous</string>
+    <string name="triad">Triad</string>
+    <string name="complementary">Complementary</string>
+    <string name="shade">Shade</string>
+    <string name="connect_please">Your ADK is not connected.</string>
+    <string name="plug_in_or_use_bluetooth">Please plug in the USB cable or use Bluetooth to connect to the ADK.</string>
+    <string name="fake_it">Fake it</string>
+    <string name="none_paired">None paired</string>
+    <string name="select_device">Select device</string>
+    <string name="pref_alarm_on_title">Turn ADK alarm on</string>
+    <string name="pref_alarm_vibrate_title">Vibrate</string>
+    <string name="pref_alarm_time_title">Time</string>
+    <string name="pref_alarm_sound_title">ADK alarm sound</string>
+    <string name="pref_clock_set_time_title">Set time</string>
+    <string name="pref_volume_title">Volume</string>
+    <string name="pref_color_base">Base</string>
+    <string name="pref_color_camera">Capture with phone camera</string>
+    <string name="pref_color_colorimeter">Capture with ADK color sensor</string>
+    <string name="pref_color_combinations">Combinations</string>
+    <string name="sync_width_adk_clock">Sync with ADK clock</string>
+    <string name="tbd">{tbd}</string>
+
+    <plurals name="number_of_presets_deleted">
+        <item quantity="one">Deleted one preset.</item>
+        <item quantity="two">Deleted two presets.</item>
+        <item quantity="other">Deleted %d presets.</item>
+    </plurals>
+    <string name="change_bt_name">Change Bluetooth Name</string>
+    <string name="set_bt_name_title">Set Bluetooth Name</string>
+    <string name="set_bt_name_ok">OK</string>
+    <string name="set_bt_name_cancel">Cancel</string>
+
+</resources>
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..e0f48b1
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="Theme.ADK2" parent="android:style/Theme.Holo">
+        <item name="android:actionBarStyle">@style/Theme.ADK2_ActionBar</item>
+        <item name="android:windowBackground">@color/window_background</item>
+    </style>
+    
+    <style name="Theme.ADK2_ActionBar" parent="@android:style/Widget.Holo.ActionBar">
+        <item name="android:background">@drawable/ab_rainbow_bg</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/res/xml/alarm_preferences.xml b/res/xml/alarm_preferences.xml
new file mode 100644
index 0000000..db0e01a
--- /dev/null
+++ b/res/xml/alarm_preferences.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <CheckBoxPreference
+        android:defaultValue="true"
+        android:key="alarm_on"
+        android:title="@string/pref_alarm_on_title" />
+
+    <com.google.android.apps.adk2.widget.TimeDialogPreference
+        android:dialogLayout="@layout/time_dialog"
+        android:key="alarm_time"
+        android:negativeButtonText="@string/cancel"
+        android:positiveButtonText="@string/set"
+        android:title="@string/pref_alarm_time_title" />
+    />
+    <ListPreference
+        android:key="alarm_sound"
+        android:summary="{tbd}"
+        android:title="@string/pref_alarm_sound_title" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/brightness_preferences.xml b/res/xml/brightness_preferences.xml
new file mode 100644
index 0000000..5e09845
--- /dev/null
+++ b/res/xml/brightness_preferences.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:adk2012="http://schemas.android.com/apk/res/com.google.android.apps.adk2" >
+
+    <com.google.android.apps.adk2.widget.SeekBarPreference
+        adk2012:max="255"
+        android:key="brightness" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/clock_preferences.xml b/res/xml/clock_preferences.xml
new file mode 100644
index 0000000..76b45cb
--- /dev/null
+++ b/res/xml/clock_preferences.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <com.google.android.apps.adk2.widget.TimeDialogPreference
+        android:dialogLayout="@layout/time_dialog"
+        android:key="time"
+        android:negativeButtonText="@string/cancel"
+        android:positiveButtonText="@string/set"
+        android:title="@string/pref_clock_set_time_title" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/color_preferences.xml b/res/xml/color_preferences.xml
new file mode 100644
index 0000000..84be4e3
--- /dev/null
+++ b/res/xml/color_preferences.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:adk2012="http://schemas.android.com/apk/res/com.google.android.apps.adk2" >
+
+    <com.google.android.apps.adk2.widget.ActivityPreference
+        adk2012:classname="com.google.android.apps.adk2.activity.ColorRGBActivity"
+        android:key="color"
+        android:title="@string/pref_color_base" />
+    <com.google.android.apps.adk2.widget.ActivityPreference
+        adk2012:classname="com.google.android.apps.adk2.activity.ColorSensorActivity"
+        android:key="color"
+        android:title="@string/pref_color_colorimeter" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/display_preferences.xml b/res/xml/display_preferences.xml
new file mode 100644
index 0000000..98407a5
--- /dev/null
+++ b/res/xml/display_preferences.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <PreferenceCategory>
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="checkboxPref"
+            android:title="Use PIN" />
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="checkboxPref2"
+            android:title="Don&apos;t use PIN" />
+    </PreferenceCategory>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/usb_accessory_filter.xml b/res/xml/usb_accessory_filter.xml
new file mode 100644
index 0000000..1ecc060
--- /dev/null
+++ b/res/xml/usb_accessory_filter.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <usb-accessory
+        manufacturer="Google, Inc."
+        model="DemoKit"
+        version="2.0" />
+
+</resources>
\ No newline at end of file
diff --git a/res/xml/volume_preferences.xml b/res/xml/volume_preferences.xml
new file mode 100644
index 0000000..73e8616
--- /dev/null
+++ b/res/xml/volume_preferences.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:adk2012="http://schemas.android.com/apk/res/com.google.android.apps.adk2" >
+
+    <com.google.android.apps.adk2.widget.SeekBarPreference
+        adk2012:max="255"
+        android:key="volume"
+        android:title="@string/pref_volume_title" />
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/google/android/apps/adk2/ADK.java b/src/com/google/android/apps/adk2/ADK.java
new file mode 100644
index 0000000..d6a1f41
--- /dev/null
+++ b/src/com/google/android/apps/adk2/ADK.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+public final class ADK {
+	public static final String TAG = "ADK_2012";
+}
diff --git a/src/com/google/android/apps/adk2/BTConnection.java b/src/com/google/android/apps/adk2/BTConnection.java
new file mode 100644
index 0000000..d9568b0
--- /dev/null
+++ b/src/com/google/android/apps/adk2/BTConnection.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.UUID;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+
+public class BTConnection extends Connection {
+
+	private final BluetoothAdapter mAdapter;
+	private BluetoothSocket mSocket;
+
+	private static final UUID MY_UUID_INSECURE = UUID
+			.fromString("1dd35050-a437-11e1-b3dd-0800200c9a66");
+
+	public BTConnection(String address) {
+		mAdapter = BluetoothAdapter.getDefaultAdapter();
+		BluetoothDevice device = mAdapter.getRemoteDevice(address);
+		try {
+			mSocket = device
+					.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);
+			mSocket.connect();
+		} catch (IOException e) {
+		}
+	}
+
+	@Override
+	public InputStream getInputStream() throws IOException {
+		return mSocket.getInputStream();
+	}
+
+	@Override
+	public OutputStream getOutputStream() throws IOException {
+		return mSocket.getOutputStream();
+	}
+
+	@Override
+	public void close() throws IOException {
+		mSocket.close();
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/Connection.java b/src/com/google/android/apps/adk2/Connection.java
new file mode 100644
index 0000000..ab889c1
--- /dev/null
+++ b/src/com/google/android/apps/adk2/Connection.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public abstract class Connection {
+	public abstract InputStream getInputStream() throws IOException;
+
+	public abstract OutputStream getOutputStream() throws IOException;
+
+	public abstract void close() throws IOException;
+}
diff --git a/src/com/google/android/apps/adk2/Preferences.java b/src/com/google/android/apps/adk2/Preferences.java
new file mode 100644
index 0000000..ec88249
--- /dev/null
+++ b/src/com/google/android/apps/adk2/Preferences.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import android.graphics.Color;
+
+public final class Preferences {
+
+	// Preference Keys
+	public static final String PREF_ALARM_ON = "alarm_on";
+	public static final String PREF_ALARM_TIME = "alarm_time";
+	public static final String PREF_ALARM_SOUND = "alarm_sound";
+	public static final String PREF_COLOR = "color";
+	public static final String PREF_DISPLAY = "display";
+	public static final String PREF_BRIGHTNESS = "brightness";
+	public static final String PREF_VOLUME = "volume";
+
+	public static final String PREF_TIME = "time";
+
+	public static final String PREF_COLOR_SENSOR = "color_sensor";
+	public static final String PREF_LOCKED = "locked";
+	
+	public static final String PREF_LICENSE_TEXT = "license_text";
+
+	public static final String[] SETTINGS_PREFERENCES = { PREF_ALARM_ON,
+			PREF_ALARM_TIME, PREF_COLOR, PREF_BRIGHTNESS, PREF_VOLUME };
+
+	// Defaults
+	public static final int PREF_DEFAULT_COLOR = Color.argb(255, 128, 64, 32);
+	public static final int DEFAULT_ALARM_TIME = 390; // 390 = 6:30am
+
+}
diff --git a/src/com/google/android/apps/adk2/Presets.java b/src/com/google/android/apps/adk2/Presets.java
new file mode 100644
index 0000000..4eb03ee
--- /dev/null
+++ b/src/com/google/android/apps/adk2/Presets.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+public class Presets {
+	private ArrayList<Preset> mPresets;
+	private final static String kFileName = "foo.dat";
+
+	public static class Preset implements Serializable {
+		private static final long serialVersionUID = 8075462052014816810L;
+		private String mName;
+		private Boolean mAlarmOn;
+		private int mAlarmTime;
+		private String mAlarmSound;
+		private int mVolume;
+		private int mColor;
+		private int mBrightness;
+		private int mDisplay;
+
+		Preset(String name) {
+			mName = name;
+		}
+
+		public String getName() {
+			return mName;
+		}
+
+		public void setName(String name) {
+			mName = name;
+		}
+
+		public String toString() {
+			return mName;
+		}
+
+		public void applyToPreferences(SharedPreferences thePrefs) {
+			SharedPreferences.Editor editor = thePrefs.edit();
+
+			editor.putBoolean(Preferences.PREF_ALARM_ON, mAlarmOn);
+			editor.putInt(Preferences.PREF_ALARM_TIME, mAlarmTime);
+			editor.putString(Preferences.PREF_ALARM_SOUND, mAlarmSound);
+
+			editor.putInt(Preferences.PREF_VOLUME, mVolume);
+
+			editor.putInt(Preferences.PREF_COLOR, mColor);
+
+			editor.putInt(Preferences.PREF_BRIGHTNESS, mBrightness);
+
+			editor.putInt(Preferences.PREF_DISPLAY, mDisplay);
+
+			editor.commit();
+		}
+
+		void extractFromPreferences(SharedPreferences thePrefs) {
+			mAlarmOn = thePrefs.getBoolean(Preferences.PREF_ALARM_ON, false);
+			mAlarmTime = thePrefs.getInt(Preferences.PREF_ALARM_TIME,
+					Preferences.DEFAULT_ALARM_TIME);
+			mAlarmSound = thePrefs.getString(Preferences.PREF_ALARM_SOUND, "");
+
+			mVolume = thePrefs.getInt(Preferences.PREF_VOLUME, 0);
+
+			mColor = thePrefs.getInt(Preferences.PREF_COLOR, 0);
+
+			mBrightness = thePrefs.getInt(Preferences.PREF_BRIGHTNESS, 0);
+
+			mDisplay = thePrefs.getInt(Preferences.PREF_DISPLAY, 0);
+		}
+
+	}
+
+	public Presets() {
+		mPresets = new ArrayList<Preset>();
+	}
+
+	public void save(Context context) throws IOException {
+		FileOutputStream fos = context.openFileOutput(kFileName,
+				Context.MODE_PRIVATE);
+		ObjectOutputStream os = new ObjectOutputStream(fos);
+		os.writeObject(mPresets);
+		os.close();
+	}
+
+	@SuppressWarnings("unchecked")
+	public void load(Context context) throws IOException,
+			ClassNotFoundException {
+		FileInputStream fis = context.openFileInput(kFileName);
+		ObjectInputStream is = new ObjectInputStream(fis);
+		Object readObject = is.readObject();
+		if (readObject != null) {
+			mPresets = (ArrayList<Preset>) readObject;
+		}
+	}
+
+	public ArrayList<Preset> getPresets() {
+		return mPresets;
+	}
+
+	public Preset makeNewPreset(SharedPreferences thePrefs) {
+		Preset preset = new Preset("Untitled");
+		preset.extractFromPreferences(thePrefs);
+		mPresets.add(preset);
+		return preset;
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/USBAccessoryActivity.java b/src/com/google/android/apps/adk2/USBAccessoryActivity.java
new file mode 100644
index 0000000..9ca10b4
--- /dev/null
+++ b/src/com/google/android/apps/adk2/USBAccessoryActivity.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.google.android.apps.adk2.activity.HomeActivity;
+
+// receive USB_DEVICE_ATTACHED events and launch the main activity
+public final class USBAccessoryActivity extends Activity {
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		Intent i = (new Intent(this, HomeActivity.class));
+		i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+				| Intent.FLAG_ACTIVITY_CLEAR_TOP);
+		startActivity(i);
+
+		finish();
+	}
+}
diff --git a/src/com/google/android/apps/adk2/UsbConnection.java b/src/com/google/android/apps/adk2/UsbConnection.java
new file mode 100644
index 0000000..ecd539a
--- /dev/null
+++ b/src/com/google/android/apps/adk2/UsbConnection.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import com.android.future.usb.UsbAccessory;
+import com.android.future.usb.UsbManager;
+import com.google.android.apps.adk2.activity.ConnectActivity;
+
+public class UsbConnection extends Connection {
+	Activity mActivity;
+	FileInputStream mInputStream;
+	FileOutputStream mOutputStream;
+	ParcelFileDescriptor mFileDescriptor;
+	UsbAccessory mAccessory;
+
+	private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
+
+	private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			String action = intent.getAction();
+			if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
+				UsbAccessory accessory = UsbManager.getAccessory(intent);
+				if (accessory != null && accessory.equals(mAccessory)) {
+					Log.i(ADK.TAG, "closing accessory");
+					Intent connectIntent = new Intent(mActivity,
+							ConnectActivity.class);
+					connectIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+					mActivity.startActivity(connectIntent);
+				}
+			}
+		}
+	};
+
+	public UsbConnection(Activity activity, UsbManager usbManager,
+			UsbAccessory accessory) {
+		mActivity = activity;
+		mFileDescriptor = usbManager.openAccessory(accessory);
+		if (mFileDescriptor != null) {
+			mAccessory = accessory;
+			FileDescriptor fd = mFileDescriptor.getFileDescriptor();
+			mInputStream = new FileInputStream(fd);
+			mOutputStream = new FileOutputStream(fd);
+		}
+		IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
+		filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
+		mActivity.registerReceiver(mUsbReceiver, filter);
+	}
+
+	@Override
+	public InputStream getInputStream() {
+		return mInputStream;
+	}
+
+	@Override
+	public OutputStream getOutputStream() {
+		return mOutputStream;
+	}
+
+	public void close() throws IOException {
+		if (mFileDescriptor != null) {
+			mFileDescriptor.close();
+		}
+		mActivity.unregisterReceiver(mUsbReceiver);
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/Utilities.java b/src/com/google/android/apps/adk2/Utilities.java
new file mode 100644
index 0000000..99e9fd4
--- /dev/null
+++ b/src/com/google/android/apps/adk2/Utilities.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2;
+
+import java.util.Date;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.preference.Preference;
+import android.preference.PreferenceManager;
+
+public class Utilities {
+	public static void centerAround(int x, int y, Drawable d) {
+		int w = d.getIntrinsicWidth();
+		int h = d.getIntrinsicHeight();
+		int left = x - w / 2;
+		int top = y - h / 2;
+		int right = left + w;
+		int bottom = top + h;
+		d.setBounds(left, top, right, bottom);
+	}
+
+	public static int indexOf(int searchArray[], int itemToFind) {
+		for (int i = 0; i < searchArray.length; ++i) {
+			if (itemToFind == searchArray[i]) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	public static int indexOf(String searchArray[], String itemToFind) {
+		for (int i = 0; i < searchArray.length; ++i) {
+			if (itemToFind.equals(searchArray[i])) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	public static int stringToFourCC(String stringCode) {
+		int theCode = 0;
+		int count = Math.max(stringCode.length(), 4);
+		for (int i = 0; i < count; ++i) {
+			char c = stringCode.charAt(i);
+			theCode <<= 8;
+			theCode |= c;
+		}
+		return theCode;
+	}
+
+	public static String fourCCToString(int fourCC) {
+		StringBuilder sb = new StringBuilder();
+		sb.append('\'');
+		sb.append((fourCC & 0xFF000000) >> 24);
+		sb.append((fourCC & 0x00FF0000) >> 16);
+		sb.append((fourCC & 0x0000FF00) >> 8);
+		sb.append((fourCC & 0x000000FF));
+		sb.append('\'');
+		return sb.toString();
+	}
+
+	public static void enablePreference(PreferenceManager preferenceMgr,
+			String prefKey, Boolean isEnabled) {
+		Preference pref = preferenceMgr.findPreference(prefKey);
+		if (pref != null) {
+			preferenceMgr.findPreference(prefKey).setEnabled(isEnabled);
+		}
+	}
+
+	public static String formatTime(Context context, Date dateToFormat) {
+		java.text.DateFormat df = android.text.format.DateFormat
+				.getTimeFormat(context);
+		return df.format(dateToFormat);
+	}
+
+	public static String formatTime(Context context, int timeValue) {
+		Date date = new Date();
+		date.setHours(timeValue / 60);
+		date.setMinutes(timeValue % 60);
+		return formatTime(context, date);
+	}
+
+	public static int dateToTimeValue(int hours, int minutes) {
+		return hours * 60 + minutes;
+	}
+
+	public static int dateToTimeValue(Date date) {
+		return dateToTimeValue(date.getHours(), date.getMinutes());
+	}
+
+	private static final byte[] HEX_CHAR = new byte[] { '0', '1', '2', '3',
+			'4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+	/**
+	 * Helper function that dump an array of bytes in hex form
+	 * 
+	 * @param buffer
+	 *            The bytes array to dump
+	 * @return A string representation of the array of bytes
+	 */
+	public static final String dumpBytes(byte[] buffer, int amountToDump) {
+		if (buffer == null) {
+			return "";
+		}
+
+		StringBuffer sb = new StringBuffer();
+
+		amountToDump = Math.min(amountToDump, buffer.length);
+
+		for (int i = 0; i < amountToDump; i++) {
+			sb.append("0x")
+					.append((char) (HEX_CHAR[(buffer[i] & 0x00F0) >> 4]))
+					.append((char) (HEX_CHAR[buffer[i] & 0x000F])).append(" ");
+		}
+
+		return sb.toString();
+	}
+
+	public static int unsignedByte(byte b) {
+		return b & 0xff;
+	}
+
+	public static int[] byteArrayToIntArray(byte[] byteArray) {
+		int[] intArray = new int[byteArray.length];
+		for (int i = 0; i < intArray.length; ++i) {
+			intArray[i] = byteArray[i] & 0xff;
+		}
+		return intArray;
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/Adk2BaseActivity.java b/src/com/google/android/apps/adk2/activity/Adk2BaseActivity.java
new file mode 100755
index 0000000..310f56b
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/Adk2BaseActivity.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Message;
+import android.view.MenuItem;
+import android.view.View;
+
+public class Adk2BaseActivity extends Activity {
+
+	private boolean mWasPolling = false;
+
+	static void maybeDisplayHomeAsUp(Activity activity) {
+		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+			activity.getActionBar().setDisplayHomeAsUpEnabled(true);
+	}
+
+	static boolean maybeHandleHomeMenuItem(MenuItem item, Activity activity) {
+		switch (item.getItemId()) {
+		case android.R.id.home:
+			activity.finish();
+			return true;
+
+		default:
+			return false;
+		}
+	}
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		Adk2BaseActivity.maybeDisplayHomeAsUp(this);
+
+		HomeActivity h = HomeActivity.get();
+		if (h != null) {
+			mWasPolling = h.startPollingSettings();
+		}
+
+	}
+
+	@Override
+	public void onDestroy() {
+		HomeActivity h = HomeActivity.get();
+		if (h != null && !mWasPolling) {
+			h.stopPollingSettings();
+		}
+		super.onDestroy();
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		return Adk2BaseActivity.maybeHandleHomeMenuItem(item, this);
+	}
+
+	public void onClick(View v) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public boolean handleMessage(Message msg) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		// TODO Auto-generated method stub
+		
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/Adk2PreferenceActivity.java b/src/com/google/android/apps/adk2/activity/Adk2PreferenceActivity.java
new file mode 100755
index 0000000..ff8f57e
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/Adk2PreferenceActivity.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceManager;
+import android.view.MenuItem;
+
+public abstract class Adk2PreferenceActivity extends PreferenceActivity
+		implements OnSharedPreferenceChangeListener {
+
+	protected PreferenceManager mPreferenceManager;
+	protected SharedPreferences mPreferences;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		Adk2BaseActivity.maybeDisplayHomeAsUp(this);
+
+		mPreferenceManager = getPreferenceManager();
+		mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+		mPreferences.registerOnSharedPreferenceChangeListener(this);
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		return Adk2BaseActivity.maybeHandleHomeMenuItem(item, this);
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
\ No newline at end of file
diff --git a/src/com/google/android/apps/adk2/activity/AlarmActivity.java b/src/com/google/android/apps/adk2/activity/AlarmActivity.java
new file mode 100644
index 0000000..04bdf17
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/AlarmActivity.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.util.Log;
+
+import com.google.android.apps.adk2.ADK;
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.Utilities;
+
+public class AlarmActivity extends Adk2PreferenceActivity {
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		addPreferencesFromResource(R.xml.alarm_preferences);
+
+		updatePreferencesDisplay();
+
+		HomeActivity h = HomeActivity.get();
+		if (h == null) {
+			Log.i(ADK.TAG, "Can't find home activity");
+		} else {
+			Log.i(ADK.TAG, "h = " + h.toString());
+		}
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		if (Preferences.PREF_ALARM_ON.equals(key)
+				|| Preferences.PREF_ALARM_TIME.equals(key)
+				|| Preferences.PREF_ALARM_SOUND.equals(key))
+			updatePreferencesDisplay();
+	}
+
+	void updatePreferencesDisplay() {
+		boolean alarmOn = mPreferences.getBoolean(Preferences.PREF_ALARM_ON,
+				true);
+
+		Utilities.enablePreference(mPreferenceManager,
+				Preferences.PREF_ALARM_TIME, alarmOn);
+		Utilities.enablePreference(mPreferenceManager,
+				Preferences.PREF_ALARM_SOUND, alarmOn);
+
+		updateAlarmTime();
+		updateAlarmSoundList();
+	}
+
+	private void updateAlarmTime() {
+		int alarmTime = mPreferences.getInt(Preferences.PREF_ALARM_TIME,
+				Preferences.DEFAULT_ALARM_TIME);
+		String alarmTimeString = Utilities.formatTime(this, alarmTime);
+		Preference alarmTimePref = mPreferenceManager
+				.findPreference(Preferences.PREF_ALARM_TIME);
+		if (alarmTimePref != null) {
+			alarmTimePref.setSummary(alarmTimeString);
+		}
+	}
+
+	private void updateAlarmSoundList() {
+		ListPreference alarmSoundPref = (ListPreference) mPreferenceManager
+				.findPreference(Preferences.PREF_ALARM_SOUND);
+		if (alarmSoundPref != null) {
+			HomeActivity h = HomeActivity.get();
+			String[] alarmSoundsList = h.getAlarmSounds();
+			String defaultAlarmSound = "";
+			if (alarmSoundsList.length > 0) {
+				defaultAlarmSound = alarmSoundsList[0];
+			}
+			String alarmSoundString = mPreferences.getString(
+					Preferences.PREF_ALARM_SOUND, defaultAlarmSound);
+			alarmSoundPref.setEntries(alarmSoundsList);
+			alarmSoundPref.setEntryValues(alarmSoundsList);
+			alarmSoundPref.setSummary(alarmSoundString);
+			alarmSoundPref.setValue(alarmSoundString);
+		}
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/BTDeviceListActivity.java b/src/com/google/android/apps/adk2/activity/BTDeviceListActivity.java
new file mode 100755
index 0000000..d9649af
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/BTDeviceListActivity.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import java.util.Set;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.google.android.apps.adk2.R;
+
+public class BTDeviceListActivity extends Adk2BaseActivity implements
+		OnItemClickListener {
+	private BluetoothAdapter mBtAdapter;
+	private ArrayAdapter<String> mPairedDevicesArrayAdapter;
+
+	public static String EXTRA_DEVICE_ADDRESS = "device_address";
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.device_list);
+
+		mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,
+				R.layout.device_name);
+
+		// Find and set up the ListView for paired devices
+		ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
+		pairedListView.setAdapter(mPairedDevicesArrayAdapter);
+		pairedListView.setOnItemClickListener(this);
+
+		// Get the local Bluetooth adapter
+		mBtAdapter = BluetoothAdapter.getDefaultAdapter();
+
+		// Get a set of currently paired devices
+		Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
+
+		// If there are paired devices, add each one to the ArrayAdapter
+		if (pairedDevices.size() > 0) {
+			findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
+			for (BluetoothDevice device : pairedDevices) {
+				mPairedDevicesArrayAdapter.add(device.getName() + "\n"
+						+ device.getAddress());
+			}
+		} else {
+			String noDevices = getResources().getText(R.string.none_paired)
+					.toString();
+			mPairedDevicesArrayAdapter.add(noDevices);
+		}
+	}
+
+	public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) {
+		mBtAdapter.cancelDiscovery();
+
+		// Get the device MAC address, which is the last 17 chars in the View
+		String info = ((TextView) v).getText().toString();
+
+		if (info.equals(getResources().getText(R.string.none_paired).toString()))
+			return; // do not proceed if we clicked the "there are no devices"
+					// message
+
+		String address = info.substring(info.length() - 17);
+		Intent connectIntent = new Intent(this, HomeActivity.class);
+		connectIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+		connectIntent.putExtra(EXTRA_DEVICE_ADDRESS, address);
+		startActivity(connectIntent);
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/activity/BrightnessActivity.java b/src/com/google/android/apps/adk2/activity/BrightnessActivity.java
new file mode 100644
index 0000000..b19e1fa
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/BrightnessActivity.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.widget.SeekBarPreference;
+
+public class BrightnessActivity extends Adk2PreferenceActivity {
+
+	public static final int MAX_BRIGHTNESS = 255;
+
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		addPreferencesFromResource(R.xml.brightness_preferences);
+		updatePreferencesDisplay();
+	}
+
+	private void updatePreferencesDisplay() {
+		SeekBarPreference brightness = (SeekBarPreference) mPreferenceManager
+				.findPreference(Preferences.PREF_BRIGHTNESS);
+
+		if (brightness != null) {
+			brightness.setValue(mPreferences.getInt(
+					Preferences.PREF_BRIGHTNESS, MAX_BRIGHTNESS));
+			brightness.setEnabled(true);
+		}
+	}
+
+	@Override
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		if (Preferences.PREF_BRIGHTNESS.equals(key))
+			updatePreferencesDisplay();
+
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/activity/ClockActivity.java b/src/com/google/android/apps/adk2/activity/ClockActivity.java
new file mode 100644
index 0000000..fe75277
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/ClockActivity.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import java.util.Date;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.Preference;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.Utilities;
+
+public class ClockActivity extends Adk2PreferenceActivity {
+
+	private Handler mHandler = new Handler();
+
+	private Runnable mUpdateTimeTask;
+
+	final static int kUpdateTime = 500;
+	int mHours = -1;
+	int mMinutes = -1;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		addPreferencesFromResource(R.xml.clock_preferences);
+
+		updatePreferencesDisplay();
+
+		mUpdateTimeTask = new Runnable() {
+			public void run() {
+				updatePreferencesDisplay();
+				mHandler.postDelayed(mUpdateTimeTask, kUpdateTime);
+			}
+		};
+		mHandler.postDelayed(mUpdateTimeTask, kUpdateTime);
+	}
+
+	@Override
+	protected void onPause() {
+		mHandler.removeCallbacks(mUpdateTimeTask);
+		super.onPause();
+	}
+
+	@Override
+	protected void onResume() {
+		mHandler.postDelayed(mUpdateTimeTask, kUpdateTime);
+		super.onResume();
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+	}
+
+	private void updatePreferencesDisplay() {
+		Preference clockTimePref = mPreferenceManager
+				.findPreference(Preferences.PREF_TIME);
+		if (clockTimePref != null) {
+			Date d = new Date();
+			if (d.getHours() != mHours || d.getMinutes() != mMinutes) {
+				mHours = d.getHours();
+				mMinutes = d.getMinutes();
+				clockTimePref.setSummary(Utilities.formatTime(this, d));
+			}
+		}
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/ColorActivity.java b/src/com/google/android/apps/adk2/activity/ColorActivity.java
new file mode 100644
index 0000000..b9dc753
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/ColorActivity.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+
+public class ColorActivity extends Adk2PreferenceActivity {
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		addPreferencesFromResource(R.xml.color_preferences);
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		if (Preferences.PREF_COLOR.equals(key))
+			updatePreferencesDisplay();
+	}
+
+	private void updatePreferencesDisplay() {
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/ColorRGBActivity.java b/src/com/google/android/apps/adk2/activity/ColorRGBActivity.java
new file mode 100644
index 0000000..9516cea
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/ColorRGBActivity.java
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.views.Slider;
+
+public class ColorRGBActivity extends Adk2BaseActivity implements
+		Slider.SliderPositionListener, OnSharedPreferenceChangeListener {
+	private View mOriginalColorView;
+	private View mNewColorView;
+	private TextView mTextHex;
+	private TextView mTextR;
+	private TextView mTextG;
+	private TextView mTextB;
+	private Slider mSeekBarR;
+	private Slider mSeekBarG;
+	private Slider mSeekBarB;
+	private Drawable mGreen;
+	private Drawable mRed;
+	private Drawable mBlue;
+
+	private int mOriginalColor;
+	private int mNewColor;
+
+	private final int kColorRange = 255;
+
+	private Slider setupSeekBar(int seekBarId, Drawable color) {
+		Slider theBar = (Slider) findViewById(seekBarId);
+		theBar.setPositionListener(this);
+		theBar.setSliderBackground(color);
+		return theBar;
+	}
+
+	private TextView setupTextField(int textFieldId) {
+		TextView theText = (TextView) findViewById(textFieldId);
+		return theText;
+	}
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.color_rgb);
+
+		Resources res = getResources();
+		mRed = res.getDrawable(R.drawable.scrubber_horizontal_red_holo_dark);
+		mGreen = res
+				.getDrawable(R.drawable.scrubber_horizontal_green_holo_dark);
+		mBlue = res.getDrawable(R.drawable.scrubber_horizontal_blue_holo_dark);
+
+		mOriginalColorView = findViewById(R.id.original_color);
+		mNewColorView = findViewById(R.id.new_color);
+		mTextHex = setupTextField(R.id.color_hex);
+		mTextR = setupTextField(R.id.color_r);
+		mTextG = setupTextField(R.id.color_g);
+		mTextB = setupTextField(R.id.color_b);
+		mSeekBarR = setupSeekBar(R.id.seek_bar_r, mRed);
+		mSeekBarG = setupSeekBar(R.id.seek_bar_g, mGreen);
+		mSeekBarB = setupSeekBar(R.id.seek_bar_b, mBlue);
+
+		mOriginalColor = PreferenceManager.getDefaultSharedPreferences(this)
+				.getInt(Preferences.PREF_COLOR, Preferences.PREF_DEFAULT_COLOR);
+		mNewColor = mOriginalColor;
+
+		SharedPreferences preferences = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		preferences.registerOnSharedPreferenceChangeListener(this);
+
+		updateDisplay();
+	}
+
+	public void onPositionChange(Slider slider, double value) {
+		switch (slider.getId()) {
+		case R.id.seek_bar_r:
+			mNewColor = (mNewColor & 0xff00ffff)
+					| ((int) (value * kColorRange) << 16);
+			break;
+
+		case R.id.seek_bar_g:
+			mNewColor = (mNewColor & 0xffff00ff)
+					| ((int) (value * kColorRange) << 8);
+			break;
+
+		case R.id.seek_bar_b:
+			mNewColor = (mNewColor & 0xffffff00) | (int) (value * kColorRange);
+			break;
+		}
+
+		persistPreferences();
+		updateDisplay();
+	}
+
+	public void onStartTrackingTouch(SeekBar seekBar) {
+	}
+
+	public void onStopTrackingTouch(SeekBar seekBar) {
+	}
+
+	private void persistPreferences() {
+		SharedPreferences.Editor editor = PreferenceManager
+				.getDefaultSharedPreferences(this).edit();
+		editor.putInt(Preferences.PREF_COLOR, mNewColor);
+		editor.apply();
+	}
+
+	private void updateDisplay() {
+		mOriginalColorView.setBackgroundColor(mOriginalColor | 0xff000000);
+		mNewColorView.setBackgroundColor(mNewColor | 0xff000000);
+
+		int r, g, b;
+		r = (mNewColor >> 16) & 0xff;
+		g = (mNewColor >> 8) & 0xff;
+		b = mNewColor & 0xff;
+
+		mTextHex.setText(String.format("%06X", mNewColor & 0xffffff));
+		mTextR.setText(String.format("%d", r));
+		mTextG.setText(Integer.toString(g));
+		mTextB.setText(Integer.toString(b));
+
+		mSeekBarR.setPosition((double) r / (double) kColorRange);
+		mSeekBarG.setPosition((double) g / (double) kColorRange);
+		mSeekBarB.setPosition((double) b / (double) kColorRange);
+	}
+
+	@Override
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		if (Preferences.PREF_COLOR.equals(key)) {
+			mOriginalColor = sharedPreferences.getInt(Preferences.PREF_COLOR,
+					Preferences.PREF_DEFAULT_COLOR);
+			mNewColor = mOriginalColor;
+			updateDisplay();
+		}
+
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/activity/ColorSensorActivity.java b/src/com/google/android/apps/adk2/activity/ColorSensorActivity.java
new file mode 100755
index 0000000..ddf079f
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/ColorSensorActivity.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.views.ColorSensorView;
+
+public class ColorSensorActivity extends Adk2BaseActivity implements
+		OnSharedPreferenceChangeListener, OnClickListener, Callback {
+
+	private Handler mColorPollingHandler;
+	private ColorSensorView mColorSensorView;
+	private Button mCaptureButton;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		SharedPreferences preferences = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		preferences.registerOnSharedPreferenceChangeListener(this);
+
+		setContentView(R.layout.color_sensor);
+		mColorSensorView = (ColorSensorView) findViewById(R.id.color_sensor_view);
+		mCaptureButton = (Button) findViewById(R.id.color_sample_button);
+		mCaptureButton.setOnClickListener(this);
+
+		mColorPollingHandler = new Handler(this);
+		getColorFromSensor();
+		Message msg = mColorPollingHandler.obtainMessage();
+		mColorPollingHandler.sendMessageDelayed(msg, 500);
+	}
+
+	@Override
+	public void onDestroy() {
+		mColorPollingHandler = null;
+		super.onDestroy();
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		if (Preferences.PREF_COLOR_SENSOR.equals(key))
+			updatePreferencesDisplay(sharedPreferences);
+	}
+
+	private void updatePreferencesDisplay(SharedPreferences sharedPreferences) {
+		mColorSensorView.setSensedColor(sharedPreferences.getInt(
+				Preferences.PREF_COLOR_SENSOR, 0) | 0xff000000);
+		getColorFromSensor();
+
+	}
+
+	private void getColorFromSensor() {
+		HomeActivity h = HomeActivity.get();
+		if (h != null) {
+			h.getSensors();
+		}
+	}
+
+	@Override
+	public void onClick(View v) {
+		SharedPreferences preferences = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		SharedPreferences.Editor editor = preferences.edit();
+		int newColor = preferences.getInt(Preferences.PREF_COLOR_SENSOR,
+				0xFFFFFF);
+		editor.putInt(Preferences.PREF_COLOR, newColor);
+		editor.commit();
+		finish();
+	}
+
+
+	public boolean handleMessage(Message msg) {
+		getColorFromSensor();
+		if (mColorPollingHandler != null) {
+			Message newMsg = mColorPollingHandler.obtainMessage();
+			mColorPollingHandler.sendMessageDelayed(newMsg, 500);
+		}
+		return true;
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/activity/ConnectActivity.java b/src/com/google/android/apps/adk2/activity/ConnectActivity.java
new file mode 100755
index 0000000..acfe7c3
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/ConnectActivity.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.google.android.apps.adk2.R;
+
+public class ConnectActivity extends Activity implements OnClickListener {
+	private Button mBluetoothButton;
+
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.connect);
+		mBluetoothButton = (Button) findViewById(R.id.connect_bluetooth_button);
+		mBluetoothButton.setOnClickListener(this);
+	}
+
+	public void onClick(View v) {
+		if (v.getId() == R.id.connect_bluetooth_button) {
+			startActivity(new Intent(this, BTDeviceListActivity.class));
+		}
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/activity/DisplayActivity.java b/src/com/google/android/apps/adk2/activity/DisplayActivity.java
new file mode 100755
index 0000000..98ba3b6
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/DisplayActivity.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.widget.RadioGroup;
+import android.widget.RadioGroup.OnCheckedChangeListener;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.Utilities;
+
+public class DisplayActivity extends Adk2BaseActivity implements
+		OnCheckedChangeListener {
+
+	RadioGroup mDisplayGroup;
+
+	int mDisplayOption;
+
+	final int kDisplayButtons[] = { R.id.radio_animation, R.id.radio_accell,
+			R.id.radio_mag, R.id.radio_temperature, R.id.radio_hygro,
+			R.id.radio_baro, R.id.radio_prox, R.id.radio_color };
+
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.display);
+
+		mDisplayGroup = (RadioGroup) findViewById(R.id.display_group);
+		mDisplayGroup.setOnCheckedChangeListener(this);
+
+		mDisplayOption = PreferenceManager.getDefaultSharedPreferences(this)
+				.getInt(Preferences.PREF_DISPLAY, 0);
+		updateDisplay();
+	}
+
+	public void onCheckedChanged(RadioGroup group, int checkedId) {
+		mDisplayOption = Utilities.indexOf(kDisplayButtons, checkedId);
+		SharedPreferences.Editor editor = PreferenceManager
+				.getDefaultSharedPreferences(this).edit();
+		editor.putInt(Preferences.PREF_DISPLAY, mDisplayOption);
+		editor.apply();
+	}
+
+	void updateDisplay() {
+		mDisplayGroup.check(kDisplayButtons[mDisplayOption]);
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/activity/HomeActivity.java b/src/com/google/android/apps/adk2/activity/HomeActivity.java
new file mode 100755
index 0000000..dedad20
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/HomeActivity.java
@@ -0,0 +1,968 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.zip.GZIPInputStream;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.future.usb.UsbAccessory;
+import com.android.future.usb.UsbManager;
+import com.google.android.apps.adk2.ADK;
+import com.google.android.apps.adk2.BTConnection;
+import com.google.android.apps.adk2.Connection;
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.UsbConnection;
+import com.google.android.apps.adk2.Utilities;
+
+public class HomeActivity extends Activity implements OnClickListener,
+		Callback, OnSharedPreferenceChangeListener, Runnable {
+
+	private Handler mDeviceHandler;
+	private Handler mSettingsPollingHandler;
+
+	private UsbManager mUSBManager;
+	private SharedPreferences mPreferences;
+
+	private ByteArrayOutputStream mLicenseTextStream;
+
+	private byte[] mSettingsBuffer = null;
+	private byte[] mSettingsPayload = new byte[8];
+	private byte[] mQueryBuffer = new byte[4];
+	private byte[] mEmptyPayload = new byte[0];
+
+	Connection mConnection;
+
+	UsbAccessory mAccessory;
+
+	private boolean mIgnorePrefChanges = false;
+	private boolean mPollSettings = false;
+
+	private long mIgnoreUpdatesUntil = System.currentTimeMillis();
+
+	private String mLicenseText = "";
+	private ArrayList<String> mSoundFiles;
+
+	static final String TUNES_FOLDER = "/Tunes";
+
+	static final byte CMD_GET_PROTO_VERSION = 1; // () -> (u8 protocolVersion)
+	static final byte CMD_GET_SENSORS = 2; // () -> (sensors:
+											// i32,i32,i32,i32,u16,u16,u16,u16,u16,u16,u16,i16,i16,i16,i16,i16,i16)
+	static final byte CMD_FILE_LIST = 3; // FIRST: (char name[]) -> (fileinfo or
+											// single zero byte) OR NONLATER: ()
+											// -> (fileinfo or empty or single
+											// zero byte)
+	static final byte CMD_FILE_DELETE = 4; // (char name[0-255)) -> (char
+											// success)
+	static final byte CMD_FILE_OPEN = 5; // (char name[0-255]) -> (char success)
+	static final byte CMD_FILE_WRITE = 6; // (u8 data[]) -> (char success)
+	static final byte CMD_FILE_CLOSE = 7; // () -> (char success)
+	static final byte CMD_GET_UNIQ_ID = 8; // () -> (u8 uniq[16])
+	static final byte CMD_BT_NAME = 9; // (char name[]) -> () OR () -> (char
+										// name[])
+	static final byte CMD_BT_PIN = 10; // (char PIN[]) -> () OR () -> (char
+										// PIN[])
+	static final byte CMD_TIME = 11; // (timespec) -> (char success)) OR () >
+										// (timespec)
+	static final byte CMD_SETTINGS = 12; // () ->
+											// (alarm:u8,u8,u8,brightness:u8,color:u8,u8,u8:volume:u8)
+											// or
+											// (alarm:u8,u8,u8,brightness:u8,color:u8,u8,u8:volume:u8)
+											// > (char success)
+	static final byte CMD_ALARM_FILE = 13; // () -> (char file[0-255]) OR (char
+											// file[0-255]) > (char success)
+	static final byte CMD_GET_LICENSE = 14; // () -> (u8 licensechunk[]) OR ()
+											// if last sent
+	static final byte CMD_DISPLAY_MODE = 15; // () -> (u8) OR (u8) -> ()
+	static final byte CMD_LOCK = 16; // () -> (u8) OR (u8) -> ()
+
+	private static final boolean gLogPackets = false;
+
+	static final int DIALOG_NO_PRESETS_ID = 0;
+
+	private static HomeActivity sHomeActivity = null;
+
+	private static String curBtName = "<UNKNOWN>";
+
+	public static HomeActivity get() {
+		return sHomeActivity;
+	}
+
+	public boolean startPollingSettings() {
+		boolean wasPolling = mPollSettings;
+		mPollSettings = true;
+		if (!wasPolling) {
+			pollSettings();
+		}
+		return wasPolling;
+	}
+
+	public void stopPollingSettings() {
+		mPollSettings = false;
+	}
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		setContentView(R.layout.home);
+
+		mDeviceHandler = new Handler(this);
+		mSettingsPollingHandler = new Handler(this);
+
+		mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+		mPreferences.registerOnSharedPreferenceChangeListener(this);
+
+		mUSBManager = UsbManager.getInstance(this);
+
+		mSoundFiles = new ArrayList<String>();
+
+		setUpButton(R.id.clock_button, R.drawable.ic_clock, R.string.clock);
+		setUpButton(R.id.alarm_button, R.drawable.ic_alarm, R.string.alarm);
+		setUpButton(R.id.volume_button, R.drawable.ic_volume, R.string.volume);
+		setUpButton(R.id.color_button, R.drawable.ic_color, R.string.color);
+		setUpButton(R.id.brightness_button, R.drawable.ic_brightness,
+				R.string.brightness);
+		setUpButton(R.id.display_button, R.drawable.ic_display,
+				R.string.display);
+		setUpButton(R.id.presets_button, R.drawable.ic_presets,
+				R.string.presets);
+		updateLockDisplay();
+
+		connectToAccessory();
+
+		startLicenseUpload();
+		sHomeActivity = this;
+
+		startPollingSettings();
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu menu) {
+		MenuInflater inflater = getMenuInflater();
+		inflater.inflate(R.menu.home_menu, menu);
+		return true;
+	}
+
+	@Override
+	protected Dialog onCreateDialog(int id) {
+		Dialog dialog = null;
+		if (id == DIALOG_NO_PRESETS_ID) {
+			AlertDialog.Builder builder = new AlertDialog.Builder(this);
+			builder.setMessage("Unsupported feature.");
+			dialog = builder.create();
+		}
+		return dialog;
+	}
+
+	private void changeBtName() {
+
+		// This example shows how to add a custom layout to an AlertDialog
+		LayoutInflater factory = LayoutInflater.from(this);
+		final View textEntryView = factory.inflate(R.layout.alert_dialog, null);
+		final EditText e = (EditText) textEntryView
+				.findViewById(R.id.btname_edit);
+
+		AlertDialog ad = new AlertDialog.Builder(this)
+				.setIconAttribute(android.R.attr.alertDialogIcon)
+				.setTitle("Set ADK Bluetooth Name")
+				.setView(textEntryView)
+				.setPositiveButton(R.string.set_bt_name_ok,
+						new DialogInterface.OnClickListener() {
+							public void onClick(DialogInterface dialog,
+									int whichButton) {
+
+								curBtName = e.getText().toString();
+								if (curBtName.equals(""))
+									curBtName = "ADK 2012";
+
+								byte b[] = null;
+								try {
+									b = curBtName.getBytes("UTF-8");
+								} catch (UnsupportedEncodingException e1) {
+									// well aren't you SOL....
+									e1.printStackTrace();
+								}
+								byte b2[] = new byte[b.length + 1];
+								for (int i = 0; i < b.length; i++)
+									b2[i] = b[i];
+								b2[b.length] = 0;
+
+								sendCommand(CMD_BT_NAME, CMD_BT_NAME, b2);
+							}
+						})
+				.setNegativeButton(R.string.set_bt_name_cancel,
+						new DialogInterface.OnClickListener() {
+							public void onClick(DialogInterface dialog,
+									int whichButton) {
+
+								// user cancels
+							}
+						}).create();
+
+		e.setText(curBtName);
+		ad.show();
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		switch (item.getItemId()) {
+		case R.id.license_menu:
+			showLicenses();
+			return true;
+
+		case R.id.disconnect_menu:
+			disconnect();
+			return true;
+
+		case R.id.change_bt_name:
+			changeBtName();
+			return true;
+
+		default:
+			return false;
+		}
+	}
+
+	private void disconnect() {
+		finish();
+	}
+
+	private void showLicenses() {
+		Intent showLicenseIntent = new Intent(this, LicenseActivity.class);
+		startActivity(showLicenseIntent);
+	}
+
+	private void startLicenseUpload() {
+		Log.i(ADK.TAG, "startLicenseUpload");
+		mLicenseTextStream = new ByteArrayOutputStream();
+		sendCommand(CMD_GET_LICENSE, 33);
+	}
+
+	private void pollSettings() {
+		if (mPollSettings) {
+			sendCommand(CMD_SETTINGS, CMD_SETTINGS);
+			sendCommand(CMD_DISPLAY_MODE, CMD_DISPLAY_MODE);
+			sendCommand(CMD_LOCK, CMD_LOCK);
+			Message msg = mSettingsPollingHandler.obtainMessage(99);
+			if (!mSettingsPollingHandler.sendMessageDelayed(msg, 500)) {
+				Log.e(ADK.TAG, "faled to queue settings message");
+			}
+		}
+	}
+
+	@Override
+	public void onPause() {
+		super.onPause();
+	}
+
+	@Override
+	public void onResume() {
+		super.onResume();
+		pollSettings();
+	}
+
+	@Override
+	public void onDestroy() {
+		sHomeActivity = null;
+		if (mConnection != null) {
+			try {
+				mConnection.close();
+			} catch (IOException e) {
+			} finally {
+				mConnection = null;
+			}
+		}
+		super.onDestroy();
+	}
+
+	public void onClick(View v) {
+		switch (v.getId()) {
+		case R.id.clock_button:
+			startActivity(new Intent(this, ClockActivity.class));
+			break;
+
+		case R.id.alarm_button:
+			startActivity(new Intent(this, AlarmActivity.class));
+			break;
+
+		case R.id.volume_button:
+			startActivity(new Intent(this, VolumeActivity.class));
+			break;
+
+		case R.id.color_button:
+			startActivity(new Intent(this, ColorActivity.class));
+			break;
+
+		case R.id.brightness_button:
+			startActivity(new Intent(this, BrightnessActivity.class));
+			break;
+
+		case R.id.display_button:
+			startActivity(new Intent(this, DisplayActivity.class));
+			break;
+
+		case R.id.presets_button:
+			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+				startActivity(new Intent(this, PresetsActivity.class));
+			else
+				showDialog(DIALOG_NO_PRESETS_ID);
+			break;
+
+		case R.id.lock_button:
+			toggleLock();
+			break;
+		}
+	}
+
+	private void toggleLock() {
+		boolean isLocked = mPreferences.getBoolean(Preferences.PREF_LOCKED,
+				false);
+		boolean newLocked = !isLocked;
+		SharedPreferences.Editor editor = mPreferences.edit();
+		editor.putBoolean(Preferences.PREF_LOCKED, newLocked);
+		editor.commit();
+	}
+
+	private void setUpButton(int buttonID, int iconID, int labelID) {
+		View button = findViewById(buttonID);
+		button.setOnClickListener(this);
+		((ImageView) button.findViewById(R.id.icon)).setImageResource(iconID);
+		((TextView) button.findViewById(R.id.label)).setText(labelID);
+	}
+
+	public void connectToAccessory() {
+		// bail out if we're already connected
+		if (mConnection != null)
+			return;
+
+		if (getIntent().hasExtra(BTDeviceListActivity.EXTRA_DEVICE_ADDRESS)) {
+			String address = getIntent().getStringExtra(
+					BTDeviceListActivity.EXTRA_DEVICE_ADDRESS);
+			Log.i(ADK.TAG, "want to connect to " + address);
+			mConnection = new BTConnection(address);
+			performPostConnectionTasks();
+		} else {
+			// assume only one accessory (currently safe assumption)
+			UsbAccessory[] accessories = mUSBManager.getAccessoryList();
+			UsbAccessory accessory = (accessories == null ? null
+					: accessories[0]);
+			if (accessory != null) {
+				if (mUSBManager.hasPermission(accessory)) {
+					openAccessory(accessory);
+				} else {
+					// synchronized (mUsbReceiver) {
+					// if (!mPermissionRequestPending) {
+					// mUsbManager.requestPermission(accessory,
+					// mPermissionIntent);
+					// mPermissionRequestPending = true;
+					// }
+					// }
+				}
+			} else {
+				// Log.d(TAG, "mAccessory is null");
+			}
+		}
+
+	}
+
+	public void disconnectFromAccessory() {
+		closeAccessory();
+	}
+
+	private void openAccessory(UsbAccessory accessory) {
+		mConnection = new UsbConnection(this, mUSBManager, accessory);
+		performPostConnectionTasks();
+	}
+
+	private void performPostConnectionTasks() {
+		sendCommand(CMD_GET_PROTO_VERSION, CMD_GET_PROTO_VERSION);
+		sendCommand(CMD_SETTINGS, CMD_SETTINGS);
+		sendCommand(CMD_BT_NAME, CMD_BT_NAME);
+		sendCommand(CMD_ALARM_FILE, CMD_ALARM_FILE);
+		listDirectory(TUNES_FOLDER);
+
+		Thread thread = new Thread(null, this, "ADK 2012");
+		thread.start();
+	}
+
+	public void closeAccessory() {
+		try {
+			mConnection.close();
+		} catch (IOException e) {
+		} finally {
+			mConnection = null;
+		}
+	}
+
+	public void run() {
+		int ret = 0;
+		byte[] buffer = new byte[16384];
+		int bufferUsed = 0;
+
+		while (ret >= 0) {
+			try {
+				ret = mConnection.getInputStream().read(buffer, bufferUsed,
+						buffer.length - bufferUsed);
+				bufferUsed += ret;
+				int remainder = process(buffer, bufferUsed);
+				if (remainder > 0) {
+					System.arraycopy(buffer, remainder, buffer, 0, bufferUsed
+							- remainder);
+					bufferUsed = remainder;
+				} else {
+					bufferUsed = 0;
+				}
+			} catch (IOException e) {
+				break;
+			}
+		}
+		Intent connectIntent = new Intent(this, ConnectActivity.class);
+		connectIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+		startActivity(connectIntent);
+	}
+
+	public int process(byte[] buffer, int bufferUsed) {
+		if (gLogPackets) {
+			Log.i(ADK.TAG,
+					"read " + bufferUsed + " bytes: "
+							+ Utilities.dumpBytes(buffer, bufferUsed));
+		}
+		ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer, 0,
+				bufferUsed);
+		ProtocolHandler ph = new ProtocolHandler(mDeviceHandler, inputStream);
+		ph.process();
+		return inputStream.available();
+	}
+
+	public void listDirectory(String path) {
+		mSoundFiles.clear();
+		byte[] payload = new byte[path.length() + 1];
+		for (int i = 0; i < path.length(); ++i) {
+			payload[i] = (byte) path.charAt(i);
+		}
+		payload[path.length()] = 0;
+		sendCommand(CMD_FILE_LIST, CMD_FILE_LIST, payload);
+	}
+
+	public void getSensors() {
+		sendCommand(CMD_GET_SENSORS, CMD_GET_SENSORS);
+	}
+
+	public byte[] sendCommand(int command, int sequence, byte[] payload,
+			byte[] buffer) {
+		int bufferLength = payload.length + 4;
+		if (buffer == null || buffer.length < bufferLength) {
+			Log.i(ADK.TAG, "allocating new command buffer of length "
+					+ bufferLength);
+			buffer = new byte[bufferLength];
+		}
+
+		buffer[0] = (byte) command;
+		buffer[1] = (byte) sequence;
+		buffer[2] = (byte) (payload.length & 0xff);
+		buffer[3] = (byte) ((payload.length & 0xff00) >> 8);
+		if (payload.length > 0) {
+			System.arraycopy(payload, 0, buffer, 4, payload.length);
+		}
+		if (mConnection != null && buffer[1] != -1) {
+			try {
+				if (gLogPackets) {
+					Log.i(ADK.TAG,
+							"sendCommand: "
+									+ Utilities
+											.dumpBytes(buffer, buffer.length));
+				}
+				mConnection.getOutputStream().write(buffer);
+			} catch (IOException e) {
+				Log.e(ADK.TAG, "accessory write failed", e);
+			}
+		}
+		return buffer;
+	}
+
+	public void sendCommand(int command, int sequence, byte[] payload) {
+		sendCommand(command, sequence, payload, null);
+	}
+
+	private void sendCommand(int command, int sequence) {
+		sendCommand(command, sequence, mEmptyPayload, mQueryBuffer);
+	}
+
+	private void handleBtNameCommand(byte[] settingsBytes) {
+
+		if (settingsBytes.length > 1 || settingsBytes[0] == 0) { // it's a name
+																	// reply
+
+			byte[] b = new byte[settingsBytes.length - 1];
+			for (int i = 0; i < settingsBytes.length - 1; i++)
+				b[i] = settingsBytes[i];
+
+			curBtName = new String(b);
+		}
+	}
+
+	private void handleSettingsCommand(byte[] settingsBytes) {
+
+		if (System.currentTimeMillis() < mIgnoreUpdatesUntil) {
+			return;
+		}
+
+		if (settingsBytes.length == 8) {
+			int settings[] = Utilities.byteArrayToIntArray(settingsBytes);
+			mIgnorePrefChanges = true;
+			SharedPreferences.Editor editor = PreferenceManager
+					.getDefaultSharedPreferences(this).edit();
+
+			// (alarm:u8,u8,u8,brightness:u8,color:u8,u8,u8:volume:u8)
+			int alarmTime = Utilities.dateToTimeValue(settings[0], settings[1]);
+			editor.putInt(Preferences.PREF_ALARM_TIME, alarmTime);
+			boolean alarmOn = (settings[2] != 0);
+			editor.putBoolean(Preferences.PREF_ALARM_ON, alarmOn);
+
+			editor.putInt(Preferences.PREF_BRIGHTNESS, settings[3]);
+
+			int color = settings[4] << 16 | settings[5] << 8 | settings[6];
+			editor.putInt(Preferences.PREF_COLOR, color);
+
+			int volume = settings[7];
+			editor.putInt(Preferences.PREF_VOLUME, volume);
+			editor.apply();
+
+			mIgnorePrefChanges = false;
+		}
+	}
+
+	private void handleLicenseTextCommand(byte[] licenseTextBytes) {
+		if (gLogPackets) {
+			Log.i(ADK.TAG, "License text chunk");
+			Log.i(ADK.TAG, Utilities.dumpBytes(licenseTextBytes,
+					licenseTextBytes.length));
+		}
+		if (licenseTextBytes.length > 1 && licenseTextBytes[0] != 0) {
+			mLicenseTextStream.write(licenseTextBytes, 1,
+					licenseTextBytes.length - 1);
+			sendCommand(CMD_GET_LICENSE, 33);
+		} else {
+
+			try {
+				mLicenseTextStream.close();
+				byte[] encodedArray = mLicenseTextStream.toByteArray();
+				GZIPInputStream gis = new GZIPInputStream(
+						new ByteArrayInputStream(encodedArray));
+				byte[] decodedBuffer = new byte[128 * 1024]; // TODO: make this
+																// buffer
+																// smaller
+				while (true) {
+					int length = gis.read(decodedBuffer);
+					if (length < 1) {
+						SharedPreferences.Editor editor = PreferenceManager
+								.getDefaultSharedPreferences(this).edit();
+						editor.putString(Preferences.PREF_LICENSE_TEXT,
+								mLicenseText);
+						editor.commit();
+						mLicenseText = "";
+						break;
+					}
+					mLicenseText = mLicenseText
+							+ new String(decodedBuffer, 0, length, "utf-8");
+				}
+			} catch (IOException e) {
+				Log.i(ADK.TAG, "error = " + e.toString());
+			}
+		}
+	}
+
+	private void handleFileListCommand(byte[] fileListBytes) {
+		if (gLogPackets)
+			Log.i(ADK.TAG,
+					"handleFileListCommand: "
+							+ Utilities.dumpBytes(fileListBytes,
+									fileListBytes.length));
+		if (fileListBytes.length == 1 && fileListBytes[0] == 0) {
+			return;
+		}
+		if (fileListBytes.length > 6) {
+			String fileName = new String(fileListBytes, 5,
+					fileListBytes.length - 6);
+			if (gLogPackets)
+				Log.i(ADK.TAG, "got file name '" + fileName + "'");
+			mSoundFiles.add(fileName);
+		}
+		sendCommand(CMD_FILE_LIST, CMD_FILE_LIST);
+
+	}
+
+	private void handleAlarmFileCommand(byte[] alarmFileNameBytes) {
+		if (alarmFileNameBytes.length > 1) {
+			mIgnorePrefChanges = true;
+			SharedPreferences.Editor editor = PreferenceManager
+					.getDefaultSharedPreferences(this).edit();
+			String alarmFileName = new String(alarmFileNameBytes, 0,
+					alarmFileNameBytes.length - 1);
+			alarmFileName = alarmFileName.replaceFirst("(?i)" + TUNES_FOLDER
+					+ "/", "");
+			editor.putString(Preferences.PREF_ALARM_SOUND, alarmFileName);
+			editor.apply();
+			mIgnorePrefChanges = false;
+		}
+	}
+
+	private void handleGetSensorsCommand(byte[] sensorBytes) {
+		if (gLogPackets)
+			Log.i(ADK.TAG,
+					"handleGetSensorsCommand: "
+							+ Utilities.dumpBytes(sensorBytes,
+									sensorBytes.length));
+		if (sensorBytes.length > 23) {
+			int sensorValues[] = Utilities.byteArrayToIntArray(sensorBytes);
+			int proxNormalized[] = {
+					sensorValues[20] | (sensorValues[21] << 8),
+					sensorValues[22] | (sensorValues[23] << 8),
+					sensorValues[24] | (sensorValues[25] << 8) };
+			proxNormalized[2] *= 3;
+			// find max
+			int proxMax = 0;
+			for (int i = 0; i < 3; i++)
+				if (proxMax < proxNormalized[i])
+					proxMax = proxNormalized[i];
+			proxMax++;
+			// normalize to 8-bits
+			for (int i = 0; i < 3; i++)
+				proxNormalized[i] = (proxNormalized[i] << 8) / proxMax;
+			final int exp[] = { 0, 19, 39, 59, 79, 100, 121, 143, 165, 187,
+					209, 232, 255, 279, 303, 327, 352, 377, 402, 428, 454, 481,
+					508, 536, 564, 592, 621, 650, 680, 710, 741, 772, 804, 836,
+					869, 902, 936, 970, 1005, 1040, 1076, 1113, 1150, 1187,
+					1226, 1264, 1304, 1344, 1385, 1426, 1468, 1511, 1554, 1598,
+					1643, 1688, 1734, 1781, 1829, 1877, 1926, 1976, 2026, 2078,
+					2130, 2183, 2237, 2292, 2348, 2404, 2461, 2520, 2579, 2639,
+					2700, 2762, 2825, 2889, 2954, 3020, 3088, 3156, 3225, 3295,
+					3367, 3439, 3513, 3588, 3664, 3741, 3819, 3899, 3980, 4062,
+					4146, 4231, 4317, 4404, 4493, 4583, 4675, 4768, 4863, 4959,
+					5057, 5156, 5257, 5359, 5463, 5568, 5676, 5785, 5895, 6008,
+					6122, 6238, 6355, 6475, 6597, 6720, 6845, 6973, 7102, 7233,
+					7367, 7502, 7640, 7780, 7922, 8066, 8213, 8362, 8513, 8666,
+					8822, 8981, 9142, 9305, 9471, 9640, 9811, 9986, 10162,
+					10342, 10524, 10710, 10898, 11089, 11283, 11480, 11681,
+					11884, 12091, 12301, 12514, 12731, 12951, 13174, 13401,
+					13632, 13866, 14104, 14345, 14591, 14840, 15093, 15351,
+					15612, 15877, 16147, 16421, 16699, 16981, 17268, 17560,
+					17856, 18156, 18462, 18772, 19087, 19407, 19733, 20063,
+					20398, 20739, 21085, 21437, 21794, 22157, 22525, 22899,
+					23279, 23666, 24058, 24456, 24861, 25272, 25689, 26113,
+					26544, 26982, 27426, 27878, 28336, 28802, 29275, 29756,
+					30244, 30740, 31243, 31755, 32274, 32802, 33338, 33883,
+					34436, 34998, 35568, 36148, 36737, 37335, 37942, 38559,
+					39186, 39823, 40469, 41126, 41793, 42471, 43159, 43859,
+					44569, 45290, 46023, 46767, 47523, 48291, 49071, 49863,
+					50668, 51486, 52316, 53159, 54016, 54886, 55770, 56668,
+					57580, 58506, 59447, 60403, 61373, 62359, 63361, 64378,
+					65412 };
+			for (int i = 0; i < 3; i++)
+				proxNormalized[i] = (exp[proxNormalized[i]] + 128) >> 8;
+
+			SharedPreferences.Editor editor = PreferenceManager
+					.getDefaultSharedPreferences(this).edit();
+			int color = (proxNormalized[0] << 16) | (proxNormalized[1] << 8)
+					| proxNormalized[2];
+			editor.putInt(Preferences.PREF_COLOR_SENSOR, color);
+			editor.commit();
+		}
+	}
+
+	private void handleLockCommand(byte[] lockedBytes) {
+		if (gLogPackets)
+			Log.i(ADK.TAG,
+					"lockBytes: "
+							+ Utilities.dumpBytes(lockedBytes,
+									lockedBytes.length));
+		if (lockedBytes.length > 0 && lockedBytes[0] != 1) {
+			mIgnorePrefChanges = true;
+			SharedPreferences.Editor editor = PreferenceManager
+					.getDefaultSharedPreferences(this).edit();
+			editor.putBoolean(Preferences.PREF_LOCKED, lockedBytes[0] == 2);
+			editor.commit();
+			mIgnorePrefChanges = false;
+		}
+	}
+
+	public boolean handleMessage(Message msg) {
+		if (msg.getTarget() == mDeviceHandler) {
+			return handleDeviceMethod(msg);
+		} else {
+			pollSettings();
+			return true;
+		}
+	}
+
+	private boolean handleDeviceMethod(Message msg) {
+		switch (msg.what) {
+		case CMD_SETTINGS:
+			handleSettingsCommand((byte[]) msg.obj);
+			return true;
+		case CMD_BT_NAME:
+			handleBtNameCommand((byte[]) msg.obj);
+		case CMD_GET_LICENSE:
+			handleLicenseTextCommand((byte[]) msg.obj);
+			return true;
+		case CMD_FILE_LIST:
+			handleFileListCommand((byte[]) msg.obj);
+			return true;
+		case CMD_ALARM_FILE:
+			handleAlarmFileCommand((byte[]) msg.obj);
+			return true;
+		case CMD_GET_SENSORS:
+			handleGetSensorsCommand((byte[]) msg.obj);
+			return true;
+		case CMD_LOCK:
+			handleLockCommand((byte[]) msg.obj);
+			return true;
+		}
+		return false;
+	}
+
+	public Object getAccessory() {
+		return mAccessory;
+	}
+
+	private void updateLockDisplay() {
+		boolean isLocked = mPreferences.getBoolean(Preferences.PREF_LOCKED,
+				false);
+		setUpButton(R.id.lock_button, isLocked ? R.drawable.ic_lock
+				: R.drawable.ic_unlock, isLocked ? R.string.locked
+				: R.string.unlocked);
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+
+		if (Preferences.PREF_LOCKED.equals(key)) {
+			updateLockDisplay();
+		}
+
+		if (mIgnorePrefChanges) {
+			return;
+		}
+
+		if (gLogPackets)
+			Log.d(ADK.TAG, "changed: " + key);
+
+		if (Utilities.indexOf(Preferences.SETTINGS_PREFERENCES, key) != -1) {
+			if (gLogPackets)
+				Log.d(ADK.TAG, "updating settings");
+			updateSettings(sharedPreferences);
+		} else if (Preferences.PREF_TIME.equals(key)) {
+			updateTime(sharedPreferences);
+		} else if (Preferences.PREF_DISPLAY.equals(key)) {
+			updateDisplay(sharedPreferences);
+		} else if (Preferences.PREF_LOCKED.equals(key)) {
+			updateLocked(sharedPreferences);
+		} else if (Preferences.PREF_ALARM_SOUND.equals(key)) {
+			updateAlarmSound(sharedPreferences);
+		}
+	}
+
+	private void updateSettings(SharedPreferences sharedPreferences) {
+		mIgnoreUpdatesUntil = System.currentTimeMillis() + 1000;
+		int color = sharedPreferences.getInt(Preferences.PREF_COLOR,
+				Preferences.PREF_DEFAULT_COLOR);
+		byte[] payload = mSettingsPayload;
+		int alarmTimeValue = sharedPreferences.getInt(
+				Preferences.PREF_ALARM_TIME, Preferences.DEFAULT_ALARM_TIME);
+		payload[0] = (byte) (alarmTimeValue / 60);
+		payload[1] = (byte) (alarmTimeValue % 60);
+		boolean alarmOn = sharedPreferences.getBoolean(
+				Preferences.PREF_ALARM_ON, false);
+		payload[2] = (byte) (alarmOn ? 1 : 0);
+		int brightness = sharedPreferences.getInt(Preferences.PREF_BRIGHTNESS,
+				255);
+		payload[3] = (byte) brightness;
+		payload[4] = (byte) (((color >> 16) & 0xff));
+		payload[5] = (byte) (((color >> 8) & 0xff));
+		payload[6] = (byte) ((color & 0xff));
+		int volume = sharedPreferences.getInt(Preferences.PREF_VOLUME, 128);
+		payload[7] = (byte) volume;
+		mSettingsBuffer = sendCommand(CMD_SETTINGS, CMD_SETTINGS, payload,
+				mSettingsBuffer);
+	}
+
+	private void updateTime(SharedPreferences sharedPreferences) {
+		int timeValue = sharedPreferences.getInt(Preferences.PREF_TIME, 0);
+		byte[] payload = new byte[7];
+		payload[0] = 0;
+		payload[1] = 0;
+		payload[2] = 0;
+		payload[3] = 0;
+		payload[4] = (byte) (timeValue / 60);
+		payload[5] = (byte) (timeValue % 60);
+		payload[6] = 0;
+		sendCommand(CMD_TIME, CMD_TIME, payload);
+	}
+
+	private void updateDisplay(SharedPreferences sharedPreferences) {
+		int displayValue = sharedPreferences
+				.getInt(Preferences.PREF_DISPLAY, 0);
+		byte[] payload = new byte[1];
+		payload[0] = (byte) displayValue;
+		sendCommand(CMD_DISPLAY_MODE, CMD_DISPLAY_MODE, payload);
+	}
+
+	private void updateLocked(SharedPreferences sharedPreferences) {
+		boolean isLocked = sharedPreferences.getBoolean(
+				Preferences.PREF_LOCKED, false);
+		Log.i(ADK.TAG, "updating locked " + isLocked);
+		byte[] payload = new byte[1];
+		payload[0] = (byte) (isLocked ? 2 : 0);
+		sendCommand(CMD_LOCK, CMD_LOCK, payload);
+	}
+
+	private void updateAlarmSound(SharedPreferences sharedPreferences) {
+		String alarmSound = TUNES_FOLDER + "/"
+				+ sharedPreferences.getString(Preferences.PREF_ALARM_SOUND, "");
+		final int alarmSoundLength = alarmSound.length();
+		if (alarmSoundLength > 0) {
+			byte[] payload = new byte[alarmSoundLength + 1];
+			alarmSound.getBytes(0, alarmSoundLength, payload, 0);
+			payload[alarmSoundLength] = (byte) 0;
+			sendCommand(CMD_ALARM_FILE, CMD_ALARM_FILE, payload);
+		}
+	}
+
+	private static class ProtocolHandler {
+		InputStream mInputStream;
+		Handler mHandler;
+
+		public ProtocolHandler(Handler handler, InputStream inputStream) {
+			mHandler = handler;
+			mInputStream = inputStream;
+		}
+
+		int readByte() throws IOException {
+			int retVal = mInputStream.read();
+			if (retVal == -1) {
+				throw new RuntimeException("End of stream reached.");
+			}
+			return retVal;
+		}
+
+		int readInt16() throws IOException {
+			int low = readByte();
+			int high = readByte();
+			if (gLogPackets) {
+				Log.i(ADK.TAG, "readInt16 low=" + low + " high=" + high);
+			}
+			return low | (high << 8);
+		}
+
+		byte[] readBuffer(int bufferSize) throws IOException {
+			byte readBuffer[] = new byte[bufferSize];
+			int index = 0;
+			int bytesToRead = bufferSize;
+			while (bytesToRead > 0) {
+				int amountRead = mInputStream.read(readBuffer, index,
+						bytesToRead);
+				if (amountRead == -1) {
+					throw new RuntimeException("End of stream reached.");
+				}
+				bytesToRead -= amountRead;
+				index += amountRead;
+			}
+			return readBuffer;
+		}
+
+		public void process() {
+			mInputStream.mark(0);
+			try {
+				while (mInputStream.available() > 0) {
+					if (gLogPackets)
+						Log.i(ADK.TAG, "about to read opcode");
+					int opCode = readByte();
+					if (gLogPackets)
+						Log.i(ADK.TAG, "opCode = " + opCode);
+					if (isValidOpCode(opCode)) {
+						int sequence = readByte();
+						if (gLogPackets)
+							Log.i(ADK.TAG, "sequence = " + sequence);
+						int replySize = readInt16();
+						if (gLogPackets)
+							Log.i(ADK.TAG, "replySize = " + replySize);
+						byte[] replyBuffer = readBuffer(replySize);
+						if (gLogPackets) {
+							Log.i(ADK.TAG,
+									"replyBuffer: "
+											+ Utilities.dumpBytes(replyBuffer,
+													replyBuffer.length));
+						}
+						processReply(opCode & 0x7f, sequence, replyBuffer);
+						mInputStream.mark(0);
+					}
+				}
+				mInputStream.reset();
+			} catch (IOException e) {
+				Log.i(ADK.TAG, "ProtocolHandler error " + e.toString());
+			}
+		}
+
+		boolean isValidOpCode(int opCodeWithReplyBitSet) {
+			if ((opCodeWithReplyBitSet & 0x80) != 0) {
+				int opCode = opCodeWithReplyBitSet & 0x7f;
+				return ((opCode >= CMD_GET_PROTO_VERSION) && (opCode <= CMD_LOCK));
+			}
+			return false;
+		}
+
+		private void processReply(int opCode, int sequence, byte[] replyBuffer) {
+			Message msg = mHandler.obtainMessage(opCode, sequence, 0,
+					replyBuffer);
+			mHandler.sendMessage(msg);
+		}
+	}
+
+	public String[] getAlarmSounds() {
+		String[] r = new String[mSoundFiles.size()];
+		return mSoundFiles.toArray(r);
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/LicenseActivity.java b/src/com/google/android/apps/adk2/activity/LicenseActivity.java
new file mode 100644
index 0000000..f642f0e
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/LicenseActivity.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.widget.TextView;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+
+public class LicenseActivity extends Adk2BaseActivity implements
+		OnSharedPreferenceChangeListener {
+	private TextView mLicenseTextView;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		setContentView(R.layout.licenses);
+
+		mLicenseTextView = (TextView) findViewById(R.id.license_text);
+
+		SharedPreferences preferences = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		preferences.registerOnSharedPreferenceChangeListener(this);
+		updateDisplay(preferences);
+	}
+
+	@Override
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+
+		if (Preferences.PREF_LICENSE_TEXT.equals(key)) {
+			updateDisplay(sharedPreferences);
+		}
+	}
+
+	private void updateDisplay(SharedPreferences sharedPreferences) {
+		String licenseText = sharedPreferences.getString(
+				Preferences.PREF_LICENSE_TEXT, "");
+		mLicenseTextView.setText(licenseText);
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/PresetsActivity.java b/src/com/google/android/apps/adk2/activity/PresetsActivity.java
new file mode 100755
index 0000000..e5faaac
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/PresetsActivity.java
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import android.app.Dialog;
+import android.app.ListActivity;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.SparseBooleanArray;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import com.google.android.apps.adk2.Presets;
+import com.google.android.apps.adk2.R;
+
+public class PresetsActivity extends ListActivity {
+
+	Presets mPresets;
+	boolean mWasPolling;
+	ArrayAdapter<Presets.Preset> mAdapter;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		mPresets = new Presets();
+		try {
+			mPresets.load(this);
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+
+		Adk2BaseActivity.maybeDisplayHomeAsUp(this);
+
+		setContentView(R.layout.presets);
+
+		mAdapter = new ArrayAdapter<Presets.Preset>(this,
+				android.R.layout.simple_list_item_multiple_choice,
+				mPresets.getPresets());
+		setListAdapter(mAdapter);
+		getListView().setMultiChoiceModeListener(new ModeCallback());
+		getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+
+		mWasPolling = HomeActivity.get().startPollingSettings();
+	}
+
+	protected void onDestroy() {
+		if (!mWasPolling) {
+			HomeActivity.get().stopPollingSettings();
+		}
+		super.onDestroy();
+	}
+
+	@Override
+	protected void onListItemClick(ListView l, View v, int position, long id) {
+		Presets.Preset p = mPresets.getPresets().get(position);
+		SharedPreferences sharedPreferences = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		p.applyToPreferences(sharedPreferences);
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu menu) {
+		MenuInflater inflater = getMenuInflater();
+		inflater.inflate(R.menu.presets_menu, menu);
+		return true;
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		if (Adk2BaseActivity.maybeHandleHomeMenuItem(item, this)) {
+			return true;
+		}
+		switch (item.getItemId()) {
+		case R.id.new_preset:
+			makeNewPreset();
+			return true;
+
+		default:
+			return false;
+		}
+	}
+
+	private void makeNewPreset() {
+		SharedPreferences sharedPreferences = PreferenceManager
+				.getDefaultSharedPreferences(this);
+		Presets.Preset p = mPresets.makeNewPreset(sharedPreferences);
+		onContentChanged();
+		RenamePresetController rpc = new RenamePresetController(p, true);
+		rpc.start();
+	}
+
+	void deletePreset(Presets.Preset preset) {
+		mAdapter.remove(preset);
+	}
+
+	private void savePresets() {
+		try {
+			mPresets.save(this);
+		} catch (IOException e) {
+			// TODO Error message for save fail
+			e.printStackTrace();
+		}
+	}
+
+	void deleteSelectedItems() {
+		ListView lv = getListView();
+		SparseBooleanArray checkedPositions = lv.getCheckedItemPositions();
+		int count = checkedPositions.size();
+		Resources res = getResources();
+		String presetsDeleted = res.getQuantityString(
+				R.plurals.number_of_presets_deleted, count, count);
+		Toast.makeText(PresetsActivity.this, presetsDeleted, Toast.LENGTH_SHORT)
+				.show();
+		ArrayList<Presets.Preset> presets = mPresets.getPresets();
+		for (int i = count - 1; i >= 0; --i) {
+			int index = checkedPositions.keyAt(i);
+			if (index != -1) {
+				Presets.Preset p = presets.get(index);
+				deletePreset(p);
+			}
+		}
+		savePresets();
+	}
+
+	void editSelectedItems() {
+		ListView lv = getListView();
+		SparseBooleanArray checkedPositions = lv.getCheckedItemPositions();
+		int firstIndex = checkedPositions.keyAt(0);
+		if (firstIndex != -1) {
+			ArrayList<Presets.Preset> presets = mPresets.getPresets();
+			Presets.Preset p = presets.get(firstIndex);
+			RenamePresetController rpc = new RenamePresetController(p, false);
+			rpc.start();
+		}
+	}
+
+	private class RenamePresetController implements OnClickListener {
+		Dialog mDialog;
+		Presets.Preset mPreset;
+		EditText mNameEdit;
+		Boolean mDeleteOnCancel;
+
+		public RenamePresetController(Presets.Preset preset,
+				Boolean deleteOnCancel) {
+			mPreset = preset;
+			mDeleteOnCancel = deleteOnCancel;
+		}
+
+		public void start() {
+			mDialog = new Dialog(PresetsActivity.this);
+			mDialog.setContentView(R.layout.preset_name_dialog);
+			Button cancel = (Button) mDialog
+					.findViewById(R.id.preset_edit_cancel);
+			cancel.setOnClickListener(this);
+			Button rename = (Button) mDialog
+					.findViewById(R.id.preset_edit_rename);
+			if (mDeleteOnCancel) {
+				rename.setText(R.string.create);
+			}
+			rename.setOnClickListener(this);
+			mNameEdit = (EditText) mDialog.findViewById(R.id.preset_name_edit);
+			mNameEdit.setText(mPreset.getName());
+			mNameEdit.selectAll();
+			mDialog.setTitle("Preset Name");
+			mDialog.show();
+		}
+
+		public void onClick(View v) {
+			if (v.getId() == R.id.preset_edit_rename) {
+				mPreset.setName(mNameEdit.getText().toString());
+				onContentChanged();
+				savePresets();
+			} else {
+				if (mDeleteOnCancel) {
+					deletePreset(mPreset);
+				}
+			}
+			mDialog.dismiss();
+
+		}
+	}
+
+	private class ModeCallback implements ListView.MultiChoiceModeListener {
+
+		public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+			MenuInflater inflater = getMenuInflater();
+			inflater.inflate(R.menu.list_select_menu, menu);
+			mode.setTitle("Select Items");
+			return true;
+		}
+
+		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+			return true;
+		}
+
+		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+			switch (item.getItemId()) {
+			case R.id.delete_preset:
+				deleteSelectedItems();
+				mode.finish();
+				break;
+			case R.id.edit_preset:
+				editSelectedItems();
+				mode.finish();
+				break;
+			}
+			return true;
+		}
+
+		public void onDestroyActionMode(ActionMode mode) {
+		}
+
+		public void onItemCheckedStateChanged(ActionMode mode, int position,
+				long id, boolean checked) {
+			final int checkedCount = getListView().getCheckedItemCount();
+			switch (checkedCount) {
+			case 0:
+				mode.setSubtitle(null);
+				break;
+			case 1:
+				mode.setSubtitle("One item selected");
+				break;
+			default:
+				mode.setSubtitle("" + checkedCount + " items selected");
+				break;
+			}
+		}
+
+	}
+}
diff --git a/src/com/google/android/apps/adk2/activity/VolumeActivity.java b/src/com/google/android/apps/adk2/activity/VolumeActivity.java
new file mode 100644
index 0000000..096e267
--- /dev/null
+++ b/src/com/google/android/apps/adk2/activity/VolumeActivity.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.activity;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.widget.SeekBarPreference;
+
+public class VolumeActivity extends Adk2PreferenceActivity {
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		addPreferencesFromResource(R.xml.volume_preferences);
+		updatePreferencesDisplay();
+	}
+
+	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+			String key) {
+		if (Preferences.PREF_VOLUME.equals(key))
+			updatePreferencesDisplay();
+	}
+
+	private void updatePreferencesDisplay() {
+		SeekBarPreference vol = (SeekBarPreference) mPreferenceManager
+				.findPreference(Preferences.PREF_VOLUME);
+		if (vol != null) {
+			vol.setValue(mPreferences.getInt(Preferences.PREF_VOLUME, 0));
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/com/google/android/apps/adk2/views/ColorSensorView.java b/src/com/google/android/apps/adk2/views/ColorSensorView.java
new file mode 100644
index 0000000..c278cfa
--- /dev/null
+++ b/src/com/google/android/apps/adk2/views/ColorSensorView.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.views;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class ColorSensorView extends View {
+	Paint mCircle;
+	Paint mBorder;
+
+	private final int kSize = 200;
+
+	public ColorSensorView(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		initColorSensorView(context);
+	}
+
+	public ColorSensorView(Context context) {
+		super(context);
+		initColorSensorView(context);
+	}
+
+	public ColorSensorView(Context context, AttributeSet attrs, int defStyle) {
+		super(context, attrs, defStyle);
+		initColorSensorView(context);
+	}
+
+	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+		setMeasuredDimension(kSize, kSize);
+	}
+
+	private void initColorSensorView(Context context) {
+		mCircle = new Paint();
+		mCircle.setARGB(255, 255, 0, 0);
+		mCircle.setStyle(Style.FILL);
+
+		mBorder = new Paint();
+		mBorder.setARGB(255, 255, 255, 255);
+		mBorder.setStyle(Style.STROKE);
+	}
+
+	public void setSensedColor(int color) {
+		mCircle.setColor(color);
+		invalidate();
+	}
+
+	@Override
+	protected void onDraw(Canvas canvas) {
+		canvas.drawRect(0, 0, kSize - 1, kSize - 1, mBorder);
+		canvas.drawCircle(kSize / 2, kSize / 2, kSize / 8, mCircle);
+	}
+}
diff --git a/src/com/google/android/apps/adk2/views/Slider.java b/src/com/google/android/apps/adk2/views/Slider.java
new file mode 100644
index 0000000..0a9ae98
--- /dev/null
+++ b/src/com/google/android/apps/adk2/views/Slider.java
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.views;
+
+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.view.MotionEvent;
+import android.view.View;
+
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.Utilities;
+
+public class Slider extends View {
+
+	public interface SliderPositionListener {
+		void onPositionChange(Slider slider, double value);
+	}
+
+	private Drawable mIndicator;
+	private Drawable mBackground;
+	private double mPosition;
+	private SliderPositionListener mListener;
+	private boolean mVertical;
+
+	public Slider(Context context) {
+		super(context);
+		initSliderView(context, false);
+	}
+
+	public Slider(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		initSliderView(context, false);
+	}
+
+	public void setSliderBackground(Drawable background) {
+		mBackground = background;
+		invalidate();
+	}
+
+	public void setPositionListener(SliderPositionListener listener) {
+		mListener = listener;
+	}
+
+	public void setPosition(double position) {
+		if (mPosition != position) {
+			invalidate();
+			mPosition = position;
+			if (mListener != null) {
+				mListener.onPositionChange(this, mPosition);
+			}
+		}
+	}
+
+	private OnTouchListener mClickListener = new OnTouchListener() {
+		public boolean onTouch(View v, MotionEvent m) {
+			Rect r = new Rect();
+			getDrawingRect(r);
+
+			double position;
+			if (mVertical) {
+				double y = m.getY();
+				position = Math.max(0, (r.bottom - y) / r.height());
+			} else {
+				double x = m.getX();
+				position = Math.max(0, (x - r.left) / r.width());
+			}
+			position = Math.min(1, position);
+			setPosition(position);
+			return true;
+		}
+	};
+
+	protected void initSliderView(Context context, boolean vertical) {
+		mPosition = 0;
+		mVertical = vertical;
+		Resources res = context.getResources();
+		if (mVertical) {
+			mBackground = res
+					.getDrawable(R.drawable.scrubber_vertical_blue_holo_dark);
+		} else {
+			mBackground = res
+					.getDrawable(R.drawable.scrubber_horizontal_holo_dark);
+		}
+		mIndicator = res.getDrawable(R.drawable.scrubber_control_holo_dark);
+		this.setOnTouchListener(mClickListener);
+	}
+
+	protected void onDraw(Canvas canvas) {
+		Rect r = new Rect();
+		getDrawingRect(r);
+		if (mVertical) {
+			int lineX = r.centerX();
+			int bgW = mBackground.getIntrinsicWidth() / 2;
+			if (bgW == 0) {
+				bgW = 5;
+			}
+			mBackground.setBounds(lineX - bgW, r.top + 10, lineX + bgW,
+					r.bottom - 10);
+			mBackground.draw(canvas);
+			final int kMargin = 48;
+			int indicatorY = (int) (r.bottom - (r.height() - kMargin)
+					* mPosition)
+					- kMargin / 2;
+			Utilities.centerAround(lineX, indicatorY, mIndicator);
+			mIndicator.draw(canvas);
+		} else {
+			int lineY = r.centerY();
+			int bgH = mBackground.getIntrinsicHeight() / 2;
+			if (bgH == 0) {
+				bgH = 5;
+			}
+			mBackground.setBounds(r.left + 10, lineY - bgH, r.right - 10, lineY
+					+ bgH);
+			mBackground.draw(canvas);
+			final int kMargin = 48;
+			int indicatorX = (int) ((r.width() - kMargin) * mPosition) + r.left
+					+ kMargin / 2;
+			Utilities.centerAround(indicatorX, lineY, mIndicator);
+			mIndicator.draw(canvas);
+		}
+	}
+
+	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+		if (mVertical) {
+			setMeasuredDimension(mIndicator.getIntrinsicWidth(),
+					getMeasuredHeight());
+		} else {
+			setMeasuredDimension(getMeasuredWidth(),
+					mIndicator.getIntrinsicHeight());
+		}
+	}
+
+}
diff --git a/src/com/google/android/apps/adk2/widget/ActivityPreference.java b/src/com/google/android/apps/adk2/widget/ActivityPreference.java
new file mode 100644
index 0000000..5eb5fe4
--- /dev/null
+++ b/src/com/google/android/apps/adk2/widget/ActivityPreference.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.widget;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.google.android.apps.adk2.ADK;
+import com.google.android.apps.adk2.R;
+
+public class ActivityPreference extends Preference {
+    String mActivityClassName;
+    
+    public ActivityPreference(Context context) {
+        this(context, null);
+    }
+    
+    public ActivityPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, android.R.attr.preferenceStyle);
+    }
+    
+    public ActivityPreference(Context context, AttributeSet attrs, int defStyle) {
+       super(context, attrs, defStyle);
+        
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActivityPreference, defStyle, 0);
+        mActivityClassName = a.getString(R.styleable.ActivityPreference_classname);
+        a.recycle();
+    }
+
+    @Override
+    protected void onClick() {
+        try {
+            Class<?> activityClass = Class.forName(mActivityClassName);
+            Intent openNewIntent = new Intent(getContext(), activityClass);
+            getContext().startActivity(openNewIntent);
+        } catch (ClassNotFoundException e) {
+            Log.e(ADK.TAG, "class not found in ActivityPreference", e);
+        }
+    }
+}
diff --git a/src/com/google/android/apps/adk2/widget/SeekBarPreference.java b/src/com/google/android/apps/adk2/widget/SeekBarPreference.java
new file mode 100644
index 0000000..b4c9c02
--- /dev/null
+++ b/src/com/google/android/apps/adk2/widget/SeekBarPreference.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import com.google.android.apps.adk2.R;
+
+public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
+    private int mMax;
+    private int mValue;
+    private boolean mTrackingTouch;
+    
+    public SeekBarPreference(Context context) {
+        this(context, null);
+    }
+    
+    public SeekBarPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, android.R.attr.preferenceStyle);
+    }
+    
+    public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
+       super(context, attrs, defStyle);
+        
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SeekBarPreference, defStyle, 0);
+        mMax = a.getInteger(R.styleable.SeekBarPreference_max, 0);
+        a.recycle();
+        
+        setLayoutResource(R.layout.seekbar_preference);
+    }
+    
+    @Override
+    protected void onBindView(View view) {
+        super.onBindView(view);
+
+        SeekBar seekBar = (SeekBar)view.findViewById(R.id.seekbar);
+        seekBar.setMax(mMax);
+        seekBar.setProgress(mValue);
+        seekBar.setEnabled(isEnabled());
+        
+        seekBar.setOnSeekBarChangeListener(this);
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setValue(restoreValue ? getPersistedInt(0) : (Integer)defaultValue);
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getInt(index, 0);
+    }
+
+    public void setValue(int value) {
+        if (value > mMax) value = mMax;
+        if (value < 0) value = 0;
+
+        if (value != mValue) {
+            mValue = value;
+            persistInt(value);
+            if (!mTrackingTouch)
+                notifyChanged();
+        }
+    }
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (progress != mValue) {
+            if (callChangeListener(progress)) {
+                setValue(progress);
+            } else {
+                seekBar.setProgress(progress);
+            }
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {        
+        mTrackingTouch = true;
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+        mTrackingTouch = false;
+    }
+}
diff --git a/src/com/google/android/apps/adk2/widget/TimeDialogPreference.java b/src/com/google/android/apps/adk2/widget/TimeDialogPreference.java
new file mode 100644
index 0000000..bc87c39
--- /dev/null
+++ b/src/com/google/android/apps/adk2/widget/TimeDialogPreference.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package com.google.android.apps.adk2.widget;
+
+import java.util.Date;
+
+import android.content.Context;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TimePicker;
+
+import com.google.android.apps.adk2.Preferences;
+import com.google.android.apps.adk2.R;
+import com.google.android.apps.adk2.Utilities;
+
+public class TimeDialogPreference extends DialogPreference {
+	private TimePicker mTimePicker;
+
+	public TimeDialogPreference(Context context, AttributeSet attrs) {
+		super(context, attrs);
+	}
+
+	@Override
+	protected void onBindDialogView(View view) {
+		super.onBindDialogView(view);
+		mTimePicker = (TimePicker) view.findViewById(R.id.time_picker);
+
+		int time = 0;
+		if (getKey().equals(Preferences.PREF_ALARM_TIME)) {
+			time = getPersistedInt(Preferences.DEFAULT_ALARM_TIME);
+		} else {
+			Date d = new Date();
+			time = Utilities.dateToTimeValue(d);
+		}
+		mTimePicker.setCurrentHour(time / 60);
+		mTimePicker.setCurrentMinute(time % 60);
+	}
+
+	@Override
+	protected void onDialogClosed(boolean positiveResult) {
+		super.onDialogClosed(positiveResult);
+
+		if (positiveResult) {
+			persistInt(Utilities.dateToTimeValue(mTimePicker.getCurrentHour(),
+					mTimePicker.getCurrentMinute()));
+		}
+	}
+}