Code drop from //branches/cupcake/...@124589
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 8c682ac..bfefbf0 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -92,14 +92,18 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".app.SaveRestoreState" android:label="@string/activity_save_restore">
+        <activity android:name=".app.SaveRestoreState"
+                android:label="@string/activity_save_restore"
+                android:windowSoftInputMode="stateVisible|adjustResize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.SAMPLE_CODE" />
             </intent-filter>
         </activity>
 
-        <activity android:name=".app.PersistentState" android:label="@string/activity_persistent">
+        <activity android:name=".app.PersistentState"
+                android:label="@string/activity_persistent"
+                android:windowSoftInputMode="stateVisible|adjustResize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.SAMPLE_CODE" />
@@ -139,7 +143,9 @@
         <activity android:name=".app.RedirectGetter">
         </activity>
 
-        <activity android:name=".app.CustomTitle" android:label="@string/activity_custom_title">
+        <activity android:name=".app.CustomTitle"
+                android:label="@string/activity_custom_title"
+                android:windowSoftInputMode="stateVisible|adjustPan">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.SAMPLE_CODE" />
@@ -261,7 +267,20 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".app.StatusBarNotifications" android:label="App/Notification/Status Bar">
+        <!-- This is used to display a notification selected by the user
+             from StatusBarNotifications.  Note the configuration here so
+             that the activity layers on top of whatever the user is doing,
+             allowing them to press back to return. -->
+        <activity android:name=".app.NotificationDisplay"
+                android:theme="@style/Theme.Transparent"
+                android:taskAffinity=""
+                android:excludeFromRecents="true"
+                android:noHistory="true">
+        </activity>
+
+        <activity android:name=".app.StatusBarNotifications"
+                android:label="App/Notification/Status Bar"
+                android:launchMode="singleTop">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.SAMPLE_CODE" />
@@ -444,6 +463,16 @@
             </intent-filter>
         </activity>
 
+
+        <!-- Voice Recognition Samples -->
+
+        <activity android:name=".app.VoiceRecognition" android:label="@string/voice_recognition">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
         <!-- ************************************* -->
         <!--        CONTENT PACKAGE SAMPLES        -->
         <!-- ************************************* -->
@@ -1335,6 +1364,16 @@
             </intent-filter>
         </activity>
         
+        <activity android:name=".graphics.TouchRotateActivity"
+                android:label="Graphics/OpenGL ES/Touch Rotate"
+                android:theme="@android:style/Theme.NoTitleBar"
+                android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        
         <activity android:name=".graphics.PolyToPoly" android:label="Graphics/PolyToPoly">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -1596,6 +1635,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".text.Marquee" android:label="Text/Marquee">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        
         <activity android:name=".text.LogTextBox1" android:label="Text/LogTextBox">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/samples/ApiDemos/res/layout/link.xml b/samples/ApiDemos/res/layout/link.xml
index 07f8325..a65d000 100644
--- a/samples/ApiDemos/res/layout/link.xml
+++ b/samples/ApiDemos/res/layout/link.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -14,10 +14,43 @@
      limitations under the License.
 -->
 
-<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:autoLink="all"
-    android:text="@string/link_text"
- />
- 
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content">
+
+  <!-- Four TextView widgets, each one displaying text containing links. -->
+
+  <!-- text1 automatically linkifies things like URLs and phone numbers. -->
+  <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/text1"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:autoLink="all"
+            android:text="@string/link_text_auto"
+            />
+
+  <!-- text2 uses a string resource containing explicit <a> tags to
+       specify links. -->
+  <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/text2"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:text="@string/link_text_manual"
+            />
+
+  <!-- text3 builds the text in the Java code using HTML. -->
+  <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/text3"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            />
+
+  <!-- text4 builds the text in the Java code without using HTML. -->
+  <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/text4"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            />
+
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/marquee.xml b/samples/ApiDemos/res/layout/marquee.xml
new file mode 100644
index 0000000..6d40c84
--- /dev/null
+++ b/samples/ApiDemos/res/layout/marquee.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent">
+    
+    <Button
+        android:layout_width="150dip" 
+        android:layout_height="wrap_content"
+        android:text="@string/marquee_default"
+        android:singleLine="true"
+        android:ellipsize="marquee"/>
+        
+    <Button
+        android:layout_width="150dip" 
+        android:layout_height="wrap_content"
+        android:text="@string/marquee_once"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:marqueeRepeatLimit="1"/>
+        
+    <Button
+        android:layout_width="150dip" 
+        android:layout_height="wrap_content"
+        android:text="@string/marquee_forever"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:marqueeRepeatLimit="marquee_forever"/>  
+           
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/surface_view_overlay.xml b/samples/ApiDemos/res/layout/surface_view_overlay.xml
index c514206..a557e22 100644
--- a/samples/ApiDemos/res/layout/surface_view_overlay.xml
+++ b/samples/ApiDemos/res/layout/surface_view_overlay.xml
@@ -28,7 +28,7 @@
             android:layout_height="0px"
             android:layout_weight="1">
 
-        <com.example.android.apis.graphics.GLSurfaceView android:id="@+id/glsurfaceview"
+        <android.opengl.GLSurfaceView android:id="@+id/glsurfaceview"
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent" />
 
diff --git a/samples/ApiDemos/res/layout/voice_recognition.xml b/samples/ApiDemos/res/layout/voice_recognition.xml
new file mode 100644
index 0000000..2db4a72
--- /dev/null
+++ b/samples/ApiDemos/res/layout/voice_recognition.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<!-- This activity displays UI for launching voice recognition -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+    
+    <TextView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="4dip"
+        android:text="@string/voice_recognition_prompt" />
+        
+    <Button android:id="@+id/btn_speak"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/speak_button" />
+        
+    <ListView android:id="@+id/list"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1" />
+
+ </LinearLayout>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index b1e12b8..2b2cc16 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -44,7 +44,7 @@
             whatever is behind it.</string>
 
     <string name="activity_translucent_blur">App/Activity/Translucent Blur</string>
-    
+
     <string name="activity_save_restore">App/Activity/Save &amp; Restore State</string>
     <string name="save_restore_msg">Demonstration of saving and restoring activity state in onSaveInstanceState() and onCreate().</string>
     <string name="saves_state">This text field saves its state:</string>
@@ -116,16 +116,16 @@
     <string name="remote_call_failed">Failure calling remote service</string>
 
     <string name="service_arguments_started">"Started with arguments: "</string>
-    <string name="service_arguments_stopped">Finished arguments, 
+    <string name="service_arguments_stopped">Finished arguments,
         stopping.</string>
     <string name="service_start_arguments_label">Sample Service Start Arguments
     </string>
 
-    <string name="activity_service_start_arguments_controller">App/Service/Service 
+    <string name="activity_service_start_arguments_controller">App/Service/Service
         Start Arguments Controller
     </string>
-    <string name="service_start_arguments_controller">This demonstrates how 
-        service can be started with arguments, and run until all arguments are 
+    <string name="service_start_arguments_controller">This demonstrates how
+        service can be started with arguments, and run until all arguments are
         processed.
     </string>
     <string name="start1_service">Start with \"One\"</string>
@@ -178,7 +178,7 @@
 
     <string name="notifying_service_controller">This service will update a status bar notification
                   every 5 seconds for a minute</string>
-        
+
     <string name="activity_custom_title">App/Activity/Custom Title</string>
     <string name="custom_title_left">Left is best</string>
     <string name="custom_title_right">Right is always right</string>
@@ -189,6 +189,8 @@
     <string name="menu_from_xml_instructions_press_menu">Select a menu resource and press the menu key.</string>
     <string name="menu_from_xml_instructions_go_back">If you want to choose another menu resource, go back and re-run this activity.</string>
 
+   <string name="voice_recognition">App/Voice Recognition</string>
+
     <!-- ============================== -->
     <!--  app/content examples strings  -->
     <!-- ============================== -->
@@ -199,7 +201,7 @@
     <string name="styled_text_prog">Assigned programmatically:</string>
 
     <string name="activity_read_asset">Content/Assets/Read Asset</string>
-    
+
     <string name="activity_themes">Content/Resources/Themes</string>
     <string name="activity_resources">Content/Resources/Resources</string>
 
@@ -216,23 +218,23 @@
     <string name="short_right_notification">Short right.</string>
     <string name="custom_notification">Custom Notification:</string>
     <string name="custom_notification_button">With a Button</string>
-    
+
     <string name="status_bar_notifications_icons_only">Icons only</string>
     <string name="status_bar_notifications_icons_and_marquee">Icons and marquee</string>
     <string name="status_bar_notifications_remote_views">Use remote views in balloon</string>
     <string name="status_bar_notifications_defaults">Use default values where applicable</string>
     <string name="status_bar_notifications_happy">:-)</string>
-    <string name="status_bar_notifications_ok">:-|</string> 
-    <string name="status_bar_notifications_sad">:-(</string>   
+    <string name="status_bar_notifications_ok">:-|</string>
+    <string name="status_bar_notifications_sad">:-(</string>
     <string name="status_bar_notifications_happy_message">I am happy</string>
     <string name="status_bar_notifications_ok_message">I am ok</string>
-    <string name="status_bar_notifications_sad_message">I am sad</string>  
+    <string name="status_bar_notifications_sad_message">I am sad</string>
     <string name="status_bar_notifications_clear">Clear notification</string>
     <string name="status_bar_notifications_mood_title">Mood ring</string>
     <string name="status_bar_notifications_default_sound">Sound</string>
     <string name="status_bar_notifications_default_vibrate">Vibrate</string>
     <string name="status_bar_notifications_default_all">All</string>
-      
+
     <!-- ============================== -->
     <!--  app/dialog examples strings  -->
     <!-- ============================== -->
@@ -250,13 +252,13 @@
     <string name="alert_dialog_two_buttons_title">
         Lorem ipsum dolor sit aie consectetur adipiscing\nPlloaso mako nuto
         siwuf cakso dodtos anr koop.
-    </string>    
+    </string>
     <string name="alert_dialog_two_buttons_msg">Header title</string>
     <string name="alert_dialog_two_buttons2_msg">
         Plloaso mako nuto siwuf cakso dodtos anr koop a
         cupy uf cak vux noaw yerw phuno. Whag schengos, uf efed, quiel
-        ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad. 
-        Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz 
+        ba mada su otrenzr.\n\nSwipontgwook proudgs hus yag su ba dagarmidad.
+        Plasa maku noga wipont trenzsa schengos ent kaap zux comy.\n\nWipont trenz
         kipg naar mixent phona. Cak pwico siructiun
         ruous nust apoply tyu cak Uhex sisulutiun munityuw uw dseg
     </string>
@@ -266,10 +268,10 @@
     <string name="alert_dialog_cancel">Cancel</string>
     <string name="alert_dialog_progress_text1">34<xliff:g id="percent">%</xliff:g></string>
     <string name="alert_dialog_progress_text2">145/305 KB</string>
-    
+
     <string name="select_dialog">Header title</string>
     <string name="select_dialog_show">List dialog</string>
-      
+
     <!-- ============================== -->
     <!--  app/menu examples strings     -->
     <!-- ============================== -->
@@ -295,7 +297,7 @@
     <!-- ============================== -->
     <!--  app/menu examples strings     -->
     <!-- ============================== -->
-    
+
     <string name="preferences_from_xml">App/Preferences/1. Preferences from XML</string>
     <string name="launching_preferences">App/Preferences/2. Launching preferences</string>
     <string name="preference_dependencies">App/Preferences/3. Preference dependencies</string>
@@ -305,7 +307,7 @@
 
     <string name="launch_preference_activity">Launch PreferenceActivity</string>
     <string name="counter_value_is">The counter value is</string>
-    
+
     <string name="inline_preferences">In-line preferences</string>
     <string name="dialog_based_preferences">Dialog-based preferences</string>
     <string name="launch_preferences">Launch preferences</string>
@@ -316,7 +318,7 @@
 
     <string name="title_checkbox_preference">Checkbox preference</string>
     <string name="summary_checkbox_preference">This is a checkbox</string>
-    
+
     <string name="title_yesno_preference">Yes or no preference</string>
     <string name="summary_yesno_preference">An example that uses a yes/no dialog</string>
     <string name="dialog_title_yesno_preference">Do you like bananas?</string>
@@ -349,7 +351,7 @@
     <string name="summary_parent_preference">This is visually a parent</string>
     <string name="title_child_preference">Child toggle</string>
     <string name="summary_child_preference">This is visually a child</string>
-    
+
     <string name="example_preference_dependency">Example preference dependency</string>
     <string name="title_wifi">WiFi</string>
     <string name="title_wifi_settings">WiFi settings</string>
@@ -374,10 +376,10 @@
     <string name="label_search_query">"Query String: "</string>
     <string name="label_search_appdata">"Query App Data: "</string>
     <string name="label_search_deliveredby">"Activity Method: "</string>
-    
+
     <string name="search_label">Search Demo</string>
     <string name="search_hint">Search Demo Hint</string>
-    
+
     <!-- ================================ -->
     <!--  app/shortcuts examples strings  -->
     <!-- ================================ -->
@@ -385,16 +387,24 @@
     <string name="shortcuts">App/Launcher Shortcuts</string>
     <string name="sample_shortcuts">ApiDemos</string>
     <string name="shortcut_name">Sample</string>
-    
+
     <string name="msg_launcher_shortcuts">This activity creates shortcuts for the launcher (home screen), and receives intents from those shortcuts.  To try it, return to the launcher and long-press to create a shortcut.</string>
     <string name="label_intent">Intent:</string>
     
+    <!-- ============================== -->
+    <!--  app/voice recognition examples strings  -->
+    <!-- ============================== -->
+
+    <string name="voice_recognition_prompt">This activity demonstrates the voice recognition APIs.</string>
+    <string name="speak_button">Speak!</string>
+    <string name="voice_recognition_results">Results:</string>
+    
     <!-- ============================ -->
     <!--  graphics examples strings  -->
     <!-- ============================ -->
 
     <string name="hide_me">Hide Me!</string>
-    
+
     <!-- ============================ -->
     <!--  media examples strings  -->
     <!-- ============================ -->
@@ -426,13 +436,13 @@
     <string name="table_layout_7_ctrlq">Ctrl-Q</string>
     <string name="table_layout_8_quit">Quit</string>
     <string name="table_layout_8_ctrlq">Ctrl-Q</string>
-    
+
     <string name="seekbar_tracking_on">Tracking on</string>
     <string name="seekbar_tracking_off">Tracking off</string>
     <string name="seekbar_from_touch">from touch</string>
-    
+
     <string name="ratingbar_rating">Rating:</string>
-    
+
     <!-- ============================== -->
     <!--  GoogleLogin examples strings  -->
     <!-- ============================== -->
@@ -542,10 +552,20 @@
     <string name="linear_layout_8_b">B</string>
     <string name="linear_layout_8_c">C</string>
     <string name="linear_layout_9_button">Button</string>
-    <string name="link_text">This is some text.  In this text are some things that are actionable.  For instance, you can click on http://www.google.com and it will launch the web browser.  You can click on google.com too.  And, if you click on (415) 555-1212 it should dial the phone.</string>
+    <string name="link_text_auto"><b>text1:</b> This is some text.  In
+      this text are some things that are actionable.  For instance,
+      you can click on http://www.google.com and it will launch the
+      web browser.  You can click on google.com too.  And, if you
+      click on (415) 555-1212 it should dial the phone.
+    </string>
+    <string name="link_text_manual"><b>text2:</b> This is some other
+      text, with a <a href="http://www.google.com">link</a> specified
+      via an &lt;a&gt; tag.  Use a \"tel:\" URL
+      to <a href="tel:4155551212">dial a phone number</a>.
+    </string>
     <string name="list_8_new_photo">New photo</string>
     <string name="list_8_clear_photos">Clear photos</string>
-    <string name="list_8_no_photos">No photos</string> 
+    <string name="list_8_no_photos">No photos</string>
     <string name="progressbar_1_plus">+</string>
     <string name="progressbar_1_minus">-</string>
     <string name="progressbar_1_default_progress">Default progress:</string>
@@ -585,19 +605,19 @@
     <string name="scrollbar_1_text">Lorem ipsum dolor sit amet.</string>
     <string name="scrollbar_2_text">Lorem ipsum dolor sit amet.</string>
     <string name="scrollbar_3_text">
- The Android platform is a software stack for mobile devices including an 
- operating system, middleware and key applications. Developers can create 
- applications for the platform using the Android SDK. Applications are written 
- using the Java programming language and run on Dalvik, a custom virtual 
+ The Android platform is a software stack for mobile devices including an
+ operating system, middleware and key applications. Developers can create
+ applications for the platform using the Android SDK. Applications are written
+ using the Java programming language and run on Dalvik, a custom virtual
  machine designed for embedded use which runs on top of a Linux kernel.
 
- If you want to know how to develop applications for Android, you're in the 
- right place. This site provides a variety of documentation that will help you 
+ If you want to know how to develop applications for Android, you're in the
+ right place. This site provides a variety of documentation that will help you
  learn about Android and develop mobile applications for the platform.
 
- An early look at the the Android SDK is also available. It includes sample 
- projects with source code, development tools, an emulator, and of course all 
- the libraries you'll need to build an Android application. What would it take 
+ An early look at the the Android SDK is also available. It includes sample
+ projects with source code, development tools, an emulator, and of course all
+ the libraries you'll need to build an Android application. What would it take
  to build a better mobile phone?
     </string>
     <string name="spinner_1_color">Color:</string>
@@ -722,6 +742,10 @@
     <string name="notify_with_text_long_notify_text">Show Long Notification</string>
     <string name="notify_with_text_short_notify_text">Show Short Notification</string>
 
+    <string name="marquee_default">This use the default marquee animation limit of 3</string>
+    <string name="marquee_once">This will run the marquee animation once</string>
+    <string name="marquee_forever">This will run the marquee animation forever</string>
+
     <string name="table_layout_10_password_text"></string>
     <string name="table_layout_10_username_text"></string>
 
@@ -730,7 +754,7 @@
     <string name="date_widgets_example_dateDisplay_text"></string>
     <string name="date_widgets_example_pickTime_text">change the time</string>
     <string name="date_widgets_example_pickDate_text">change the date</string>
-    
+
     <string name="buttons_1_normal">Normal</string>
     <string name="buttons_1_right">Right</string>
     <string name="buttons_1_small">Small</string>
@@ -739,7 +763,7 @@
     <string name="buttons_1_small_up">S U</string>
     <string name="buttons_1_small_down">S D</string>
     <string name="buttons_1_toggle">Toggle</string>
-    
+
     <string name="expandable_list_sample_action">Sample action</string>
 
     <string name="chronometer_start">Start</string>
@@ -754,8 +778,8 @@
     <!-- ============================ -->
 
     <string name="vibrate">Vibrate</string>
-    
-    
+
+
     <string name="image_view_large_normal">Large image at normal size</string>
     <string name="image_view_large_at_most">Large image scaled to at most 50x50</string>
     <string name="image_view_large_at_most_padded">Large image scaled to at most 70x70 with padding</string>
@@ -764,7 +788,7 @@
     <string name="image_view_small_at_most">Small image scaled to at most 50x50</string>
     <string name="image_view_small_at_most_padded">Small image scaled to at most 70x70 with padding</string>
     <string name="image_view_small_exactly_padded">Small image scaled to exactly 70x70 with padding</string>
-    
+
     <!-- Shouldn't be localized -->
     <string name="textColorPrimary">textColorPrimary</string>
     <string name="textColorSecondary">textColorSecondary</string>
diff --git a/samples/ApiDemos/src/com/android/samples/app/VoiceRecognition.java b/samples/ApiDemos/src/com/android/samples/app/VoiceRecognition.java
new file mode 100644
index 0000000..aa45c8e
--- /dev/null
+++ b/samples/ApiDemos/src/com/android/samples/app/VoiceRecognition.java
@@ -0,0 +1,84 @@
+/* 
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.samples.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+
+import com.example.android.apis.R;
+
+import java.util.ArrayList;
+
+public class VoiceRecognition extends Activity {
+    
+    private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
+    
+    private ListView mList;
+
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Inflate our UI from its XML layout description.
+        setContentView(R.layout.voice_recognition);
+
+        // Get display items for later interaction
+        Button speakButton = (Button) findViewById(R.id.btn_speak);
+        
+        mList = (ListView) findViewById(R.id.list);
+
+        // Attach actions to buttons
+        speakButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                startVoiceRecognitionActivity();
+            }
+        });
+    }
+
+    void startVoiceRecognitionActivity() {
+        Intent intent = new Intent("android.intent.action.VOICE_RECOGNITION");
+        this.startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        
+        android.util.Log.d("mike", "**************  onActivityResult" + data );
+        
+        if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
+            ArrayList<String>matches = data.getStringArrayListExtra("queries");
+            
+            
+            android.util.Log.d("mike", "**************  onActivityResult" + matches);
+            
+            mList.setAdapter(new ArrayAdapter<String>(this,
+                    android.R.layout.simple_list_item_1, matches));
+        }
+        
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java b/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java
new file mode 100644
index 0000000..a6c20ea
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/NotificationDisplay.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+
+/**
+ * Activity used by StatusBarNotification to show the notification to the user.
+ */
+public class NotificationDisplay extends Activity implements View.OnClickListener {
+    /**
+     * Initialization of the Activity after it is first created.  Must at least
+     * call {@link android.app.Activity#setContentView setContentView()} to
+     * describe what is to be displayed in the screen.
+     */
+    @Override
+    protected void onCreate(Bundle icicle) {
+        // Be sure to call the super class.
+        super.onCreate(icicle);
+
+        // Have the system blur any windows behind this one.
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
+                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
+        
+        RelativeLayout container = new RelativeLayout(this);
+        
+        ImageButton button = new ImageButton(this);
+        button.setImageResource(getIntent().getIntExtra("moodimg", 0));
+        button.setOnClickListener(this);
+        
+        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+                RelativeLayout.LayoutParams.WRAP_CONTENT,
+                RelativeLayout.LayoutParams.WRAP_CONTENT);
+        lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+        
+        container.addView(button, lp);
+        
+        setContentView(container);
+    }
+
+    public void onClick(View v) {
+        // The user has confirmed this notification, so remove it.
+        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+                .cancel(R.layout.status_bar_notifications);
+        
+        // Pressing on the button brings the user back to our mood ring,
+        // as part of the api demos app.  Note the use of NEW_TASK here,
+        // since the notification display activity is run as a separate task.
+        Intent intent = new Intent(this, StatusBarNotifications.class);
+        intent.setAction(Intent.ACTION_MAIN);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        startActivity(intent);
+        
+        // We're done.
+        finish();
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java b/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
index a625434..a8d350c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SearchInvoke.java
@@ -22,6 +22,7 @@
 import android.app.AlertDialog;
 import android.app.SearchManager;
 import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -111,6 +112,8 @@
         
             // first, get rid of our menus (if any)
         menu.removeItem(0);
+        menu.removeItem(1);
+        
             // next, add back item(s) based on current menu mode
         switch (mMenuMode.getSelectedItemPosition())
         {
@@ -131,6 +134,8 @@
             item = menu.add( 0, 0, 0, "(Disabled)");
             break;
         }
+        
+        item = menu.add(0, 1, 0, "Clear History");
         return true;
     }
     
@@ -167,6 +172,9 @@
                 break;
             }
             break;
+        case 1:
+            clearSearchHistory();
+            break;
         }
     
          return super.onOptionsItemSelected(item);
@@ -211,4 +219,23 @@
         return true;
     }
     
+    /**
+     * Any application that implements search suggestions based on previous actions (such as
+     * recent queries, page/items viewed, etc.) should provide a way for the user to clear the
+     * history.  This gives the user a measure of privacy, if they do not wish for their recent
+     * searches to be replayed by other users of the device (via suggestions).
+     * 
+     * This example shows how to clear the search history for apps that use 
+     * android.provider.SearchRecentSuggestions.  If you have developed a custom suggestions
+     * provider, you'll need to provide a similar API for clearing history.
+     * 
+     * In this sample app we call this method from a "Clear History" menu item.  You could also 
+     * implement the UI in your preferences, or any other logical place in your UI.
+     */
+    private void clearSearchHistory() {
+        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, 
+                SearchSuggestionSampleProvider.AUTHORITY, SearchSuggestionSampleProvider.MODE);
+        suggestions.clearHistory();
+    }
+    
 }
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java b/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
index bc69e7b..97f6199 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/StatusBarNotifications.java
@@ -144,6 +144,19 @@
         });
     }
 
+    private PendingIntent makeMoodIntent(int moodId) {
+        // The PendingIntent to launch our activity if the user selects this
+        // notification.  Note the use of FLAG_UPDATE_CURRENT so that if there
+        // is already an active matching pending intent, we will update its
+        // extras to be the ones passed in here.
+        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+                new Intent(this, NotificationDisplay.class)
+                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                        .putExtra("moodimg", moodId),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+        return contentIntent;
+    }
+    
     private void setMood(int moodId, int textId, boolean showTicker) {
         // In this sample, we'll use the same text for the ticker and the expanded notification
         CharSequence text = getText(textId);
@@ -155,13 +168,9 @@
         Notification notification = new Notification(moodId, tickerText,
                 System.currentTimeMillis());
 
-        // The PendingIntent to launch our activity if the user selects this notification
-        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
-                new Intent(this, StatusBarNotifications.class), 0);
-
         // Set the info for the views that show in the notification panel.
         notification.setLatestEventInfo(this, getText(R.string.status_bar_notifications_mood_title),
-                       text, contentIntent);
+                       text, makeMoodIntent(moodId));
 
         // Send the notification.
         // We use a layout id because it is a unique number.  We use it later to cancel.
@@ -176,8 +185,7 @@
         Notification notif = new Notification();
 
         // This is who should be launched if the user selects our notification.
-        notif.contentIntent = PendingIntent.getActivity(this, 0,
-                new Intent(this, StatusBarNotifications.class), 0);
+        notif.contentIntent = makeMoodIntent(moodId);
 
         // In this sample, we'll use the same text for the ticker and the expanded notification
         CharSequence text = getText(textId);
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
index eb5712f..88f0c1d 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapDecode.java
@@ -28,6 +28,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
 
 public class BitmapDecode extends GraphicsActivity {
     
@@ -47,6 +48,19 @@
         private Movie mMovie;
         private long mMovieStart;
         
+        private static byte[] streamToBytes(InputStream is) {
+            ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
+            byte[] buffer = new byte[1024];
+            int len;
+            try {
+                while ((len = is.read(buffer)) >= 0) {
+                    os.write(buffer, 0, len);
+                }
+            } catch (java.io.IOException e) {
+            }
+            return os.toByteArray();
+        }
+        
         public SampleView(Context context) {
             super(context);
             setFocusable(true);
@@ -87,7 +101,12 @@
             mDrawable.setBounds(150, 20, 300, 100);
             
             is = context.getResources().openRawResource(R.drawable.animated_gif);
-            mMovie = Movie.decodeStream(is);
+            if (true) {
+                mMovie = Movie.decodeStream(is);
+            } else {
+                byte[] array = streamToBytes(is);
+                mMovie = Movie.decodeByteArray(array, 0, array.length);
+            }
         }
         
         @Override protected void onDraw(Canvas canvas) {
@@ -107,11 +126,17 @@
             if (mMovieStart == 0) {   // first time
                 mMovieStart = now;
             }
-            int relTime = (int)((now - mMovieStart) % mMovie.duration());
-            mMovie.setTime(relTime);
-            mMovie.draw(canvas, getWidth() - mMovie.width(),
-                        getHeight() - mMovie.height());
-            invalidate();
+            if (mMovie != null) {
+                int dur = mMovie.duration();
+                if (dur == 0) {
+                    dur = 1000;
+                }
+                int relTime = (int)((now - mMovieStart) % dur);
+                mMovie.setTime(relTime);
+                mMovie.draw(canvas, getWidth() - mMovie.width(),
+                            getHeight() - mMovie.height());
+                invalidate();
+            }
         }
     }
 }
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
index 8e6e158..ceff150 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
@@ -23,7 +23,7 @@
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.Window;
-
+import java.io.IOException;
 
 // ----------------------------------------------------------------------
 
@@ -64,7 +64,13 @@
         // The Surface has been created, acquire the camera and tell it where
         // to draw.
         mCamera = Camera.open();
-        mCamera.setPreviewDisplay(holder);
+        try {
+           mCamera.setPreviewDisplay(holder);
+        } catch (IOException exception) {
+            mCamera.release();
+            mCamera = null;
+            // TODO: add more exception handling logic here
+        }
     }
 
     public void surfaceDestroyed(SurfaceHolder holder) {
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
index 6117a60..527e2bc 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.java
@@ -17,8 +17,11 @@
 package com.example.android.apis.graphics;
 
 import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
+import android.opengl.GLSurfaceView;
+
 /**
  * Render a pair of tumbling cubes.
  */
@@ -29,7 +32,7 @@
         mCube = new Cube();
     }
 
-    public void drawFrame(GL10 gl) {
+    public void onDrawFrame(GL10 gl) {
         /*
          * Usually, the first thing one might want to do is to clear
          * the screen. The most efficient way of doing this is to use
@@ -84,7 +87,7 @@
             }
     }
 
-    public void sizeChanged(GL10 gl, int width, int height) {
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
          gl.glViewport(0, 0, width, height);
 
          /*
@@ -99,7 +102,7 @@
          gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
     }
 
-    public void surfaceCreated(GL10 gl) {
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         /*
          * By default, OpenGL enables features that improve quality
          * but reduce performance. One might want to tweak that
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceView.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceView.java
deleted file mode 100644
index 16a17dd..0000000
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceView.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.android.apis.graphics;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-
-import java.util.ArrayList;
-import java.util.concurrent.Semaphore;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * An implementation of SurfaceView that uses the dedicated surface for
- * displaying an OpenGL animation.  This allows the animation to run in a
- * separate thread, without requiring that it be driven by the update mechanism
- * of the view hierarchy.
- *
- * The application-specific rendering code is delegated to a GLView.Renderer
- * instance.
- */
-public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
-    public GLSurfaceView(Context context) {
-        super(context);
-        init();
-    }
-
-    public GLSurfaceView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    private void init() {
-        // Install a SurfaceHolder.Callback so we get notified when the
-        // underlying surface is created and destroyed
-        mHolder = getHolder();
-        mHolder.addCallback(this);
-        mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
-    }
-
-    public SurfaceHolder getSurfaceHolder() {
-        return mHolder;
-    }
-
-    public void setGLWrapper(GLWrapper glWrapper) {
-        mGLWrapper = glWrapper;
-    }
-
-    public void setRenderer(Renderer renderer) {
-        mGLThread = new GLThread(renderer);
-        mGLThread.start();
-    }
-
-    public void surfaceCreated(SurfaceHolder holder) {
-        mGLThread.surfaceCreated();
-    }
-
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        // Surface will be destroyed when we return
-        mGLThread.surfaceDestroyed();
-    }
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        // Surface size or format has changed. This should not happen in this
-        // example.
-        mGLThread.onWindowResize(w, h);
-    }
-
-    /**
-     * Inform the view that the activity is paused.
-     */
-    public void onPause() {
-        mGLThread.onPause();
-    }
-
-    /**
-     * Inform the view that the activity is resumed.
-     */
-    public void onResume() {
-        mGLThread.onResume();
-    }
-
-    /**
-     * Inform the view that the window focus has changed.
-     */
-    @Override public void onWindowFocusChanged(boolean hasFocus) {
-        super.onWindowFocusChanged(hasFocus);
-        mGLThread.onWindowFocusChanged(hasFocus);
-    }
-
-    /**
-     * Queue an "event" to be run on the GL rendering thread.
-     * @param r the runnable to be run on the GL rendering thread.
-     */
-    public void queueEvent(Runnable r) {
-        mGLThread.queueEvent(r);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mGLThread.requestExitAndWait();
-    }
-
-    // ----------------------------------------------------------------------
-
-    public interface GLWrapper {
-      GL wrap(GL gl);
-    }
-
-    // ----------------------------------------------------------------------
-
-    /**
-     * A generic renderer interface.
-     */
-    public interface Renderer {
-        /**
-         * @return the EGL configuration specification desired by the renderer.
-         */
-        int[] getConfigSpec();
-
-        /**
-         * Surface created.
-         * Called when the surface is created. Called when the application
-         * starts, and whenever the GPU is reinitialized. This will
-         * typically happen when the device awakes after going to sleep.
-         * Set your textures here.
-         */
-        void surfaceCreated(GL10 gl);
-        /**
-         * Surface changed size.
-         * Called after the surface is created and whenever
-         * the OpenGL ES surface size changes. Set your viewport here.
-         * @param gl
-         * @param width
-         * @param height
-         */
-        void sizeChanged(GL10 gl, int width, int height);
-        /**
-         * Draw the current frame.
-         * @param gl
-         */
-        void drawFrame(GL10 gl);
-    }
-
-    /**
-     * An EGL helper class.
-     */
-
-    private class EglHelper {
-        public EglHelper() {
-
-        }
-
-        /**
-         * Initialize EGL for a given configuration spec.
-         * @param configSpec
-         */
-        public void start(int[] configSpec){
-            /*
-             * Get an EGL instance
-             */
-            mEgl = (EGL10) EGLContext.getEGL();
-
-            /*
-             * Get to the default display.
-             */
-            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
-            /*
-             * We can now initialize EGL for that display
-             */
-            int[] version = new int[2];
-            mEgl.eglInitialize(mEglDisplay, version);
-
-            EGLConfig[] configs = new EGLConfig[1];
-            int[] num_config = new int[1];
-            mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1,
-                    num_config);
-            mEglConfig = configs[0];
-
-            /*
-            * Create an OpenGL ES context. This must be done only once, an
-            * OpenGL context is a somewhat heavy object.
-            */
-            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
-                    EGL10.EGL_NO_CONTEXT, null);
-
-            mEglSurface = null;
-        }
-
-        /*
-         * Create and return an OpenGL surface
-         */
-        public GL createSurface(SurfaceHolder holder) {
-            /*
-             *  The window size has changed, so we need to create a new
-             *  surface.
-             */
-            if (mEglSurface != null) {
-
-                /*
-                 * Unbind and destroy the old EGL surface, if
-                 * there is one.
-                 */
-                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-            }
-
-            /*
-             * Create an EGL surface we can render into.
-             */
-            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,
-                    mEglConfig, holder, null);
-
-            /*
-             * Before we can issue GL commands, we need to make sure
-             * the context is current and bound to a surface.
-             */
-            mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-                    mEglContext);
-
-
-            GL gl = mEglContext.getGL();
-            if (mGLWrapper != null) {
-                gl = mGLWrapper.wrap(gl);
-            }
-            return gl;
-        }
-
-        /**
-         * Display the current render surface.
-         * @return false if the context has been lost.
-         */
-        public boolean swap() {
-            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
-
-            /*
-             * Always check for EGL_CONTEXT_LOST, which means the context
-             * and all associated data were lost (For instance because
-             * the device went to sleep). We need to sleep until we
-             * get a new surface.
-             */
-            return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
-        }
-
-        public void finish() {
-            if (mEglSurface != null) {
-                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_CONTEXT);
-                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-                mEglSurface = null;
-            }
-            if (mEglContext != null) {
-                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-                mEglContext = null;
-            }
-            if (mEglDisplay != null) {
-                mEgl.eglTerminate(mEglDisplay);
-                mEglDisplay = null;
-            }
-        }
-
-        EGL10 mEgl;
-        EGLDisplay mEglDisplay;
-        EGLSurface mEglSurface;
-        EGLConfig mEglConfig;
-        EGLContext mEglContext;
-    }
-
-    /**
-     * A generic GL Thread. Takes care of initializing EGL and GL. Delegates
-     * to a Renderer instance to do the actual drawing.
-     *
-     */
-
-    class GLThread extends Thread {
-        GLThread(Renderer renderer) {
-            super();
-            mDone = false;
-            mWidth = 0;
-            mHeight = 0;
-            mRenderer = renderer;
-            setName("GLThread");
-        }
-
-        @Override
-        public void run() {
-            /*
-             * When the android framework launches a second instance of
-             * an activity, the new instance's onCreate() method may be
-             * called before the first instance returns from onDestroy().
-             *
-             * This semaphore ensures that only one instance at a time
-             * accesses EGL.
-             */
-            try {
-                try {
-                sEglSemaphore.acquire();
-                } catch (InterruptedException e) {
-                    return;
-                }
-                guardedRun();
-            } catch (InterruptedException e) {
-                // fall thru and exit normally
-            } finally {
-                sEglSemaphore.release();
-            }
-        }
-
-        private void guardedRun() throws InterruptedException {
-            mEglHelper = new EglHelper();
-            /*
-             * Specify a configuration for our opengl session
-             * and grab the first configuration that matches is
-             */
-            int[] configSpec = mRenderer.getConfigSpec();
-            mEglHelper.start(configSpec);
-
-            GL10 gl = null;
-            boolean tellRendererSurfaceCreated = true;
-            boolean tellRendererSurfaceChanged = true;
-
-            /*
-             * This is our main activity thread's loop, we go until
-             * asked to quit.
-             */
-            while (!mDone) {
-
-                /*
-                 *  Update the asynchronous state (window size)
-                 */
-                int w, h;
-                boolean changed;
-                boolean needStart = false;
-                synchronized (this) {
-                    Runnable r;
-                    while ((r = getEvent()) != null) {
-                        r.run();
-                    }
-                    if (mPaused) {
-                        mEglHelper.finish();
-                        needStart = true;
-                    }
-                    if(needToWait()) {
-                        while (needToWait()) {
-                            wait();
-                        }
-                    }
-                    if (mDone) {
-                        break;
-                    }
-                    changed = mSizeChanged;
-                    w = mWidth;
-                    h = mHeight;
-                    mSizeChanged = false;
-                }
-                if (needStart) {
-                    mEglHelper.start(configSpec);
-                    tellRendererSurfaceCreated = true;
-                    changed = true;
-                }
-                if (changed) {
-                    gl = (GL10) mEglHelper.createSurface(mHolder);
-                    tellRendererSurfaceChanged = true;
-                }
-                if (tellRendererSurfaceCreated) {
-                    mRenderer.surfaceCreated(gl);
-                    tellRendererSurfaceCreated = false;
-                }
-                if (tellRendererSurfaceChanged) {
-                    mRenderer.sizeChanged(gl, w, h);
-                    tellRendererSurfaceChanged = false;
-                }
-                if ((w > 0) && (h > 0)) {
-                    /* draw a frame here */
-                    mRenderer.drawFrame(gl);
-
-                    /*
-                     * Once we're done with GL, we need to call swapBuffers()
-                     * to instruct the system to display the rendered frame
-                     */
-                    mEglHelper.swap();
-                }
-             }
-
-            /*
-             * clean-up everything...
-             */
-            mEglHelper.finish();
-        }
-
-        private boolean needToWait() {
-            return (mPaused || (! mHasFocus) || (! mHasSurface) || mContextLost)
-                && (! mDone);
-        }
-
-        public void surfaceCreated() {
-            synchronized(this) {
-                mHasSurface = true;
-                mContextLost = false;
-                notify();
-            }
-        }
-
-        public void surfaceDestroyed() {
-            synchronized(this) {
-                mHasSurface = false;
-                notify();
-            }
-        }
-
-        public void onPause() {
-            synchronized (this) {
-                mPaused = true;
-            }
-        }
-
-        public void onResume() {
-            synchronized (this) {
-                mPaused = false;
-                notify();
-            }
-        }
-
-        public void onWindowFocusChanged(boolean hasFocus) {
-            synchronized (this) {
-                mHasFocus = hasFocus;
-                if (mHasFocus == true) {
-                    notify();
-                }
-            }
-        }
-        public void onWindowResize(int w, int h) {
-            synchronized (this) {
-                mWidth = w;
-                mHeight = h;
-                mSizeChanged = true;
-            }
-        }
-
-        public void requestExitAndWait() {
-            // don't call this from GLThread thread or it is a guaranteed
-            // deadlock!
-            synchronized(this) {
-                mDone = true;
-                notify();
-            }
-            try {
-                join();
-            } catch (InterruptedException ex) {
-                Thread.currentThread().interrupt();
-            }
-        }
-
-        /**
-         * Queue an "event" to be run on the GL rendering thread.
-         * @param r the runnable to be run on the GL rendering thread.
-         */
-        public void queueEvent(Runnable r) {
-            synchronized(this) {
-                mEventQueue.add(r);
-            }
-        }
-
-        private Runnable getEvent() {
-            synchronized(this) {
-                if (mEventQueue.size() > 0) {
-                    return mEventQueue.remove(0);
-                }
-
-            }
-            return null;
-        }
-
-        private boolean mDone;
-        private boolean mPaused;
-        private boolean mHasFocus;
-        private boolean mHasSurface;
-        private boolean mContextLost;
-        private int mWidth;
-        private int mHeight;
-        private Renderer mRenderer;
-        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
-        private EglHelper mEglHelper;
-    }
-
-    private static final Semaphore sEglSemaphore = new Semaphore(1);
-    private boolean mSizeChanged = true;
-
-    private SurfaceHolder mHolder;
-    private GLThread mGLThread;
-    private GLWrapper mGLWrapper;
-}
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
index aa46036..f852186 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.java
@@ -17,6 +17,7 @@
 package com.example.android.apis.graphics;
 
 import android.app.Activity;
+import android.opengl.GLSurfaceView;
 import android.os.Bundle;
 
 /**
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java b/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
index da2a1e5..45e5d60 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/SurfaceViewOverlay.java
@@ -17,6 +17,7 @@
 package com.example.android.apis.graphics;
 
 import android.app.Activity;
+import android.opengl.GLSurfaceView;
 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java
new file mode 100644
index 0000000..09d3694
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.graphics;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+/**
+ * Wrapper activity demonstrating the use of {@link GLSurfaceView}, a view
+ * that uses OpenGL drawing into a dedicated surface.
+ *
+ * Shows:
+ * + How to redraw in response to user input.
+ */
+public class TouchRotateActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mGLSurfaceView = new TouchSurfaceView(this);
+        setContentView(mGLSurfaceView);
+        mGLSurfaceView.requestFocus();
+        mGLSurfaceView.setFocusableInTouchMode(true);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onResume();
+        mGLSurfaceView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onPause();
+        mGLSurfaceView.onPause();
+    }
+
+    private GLSurfaceView mGLSurfaceView;
+}
+
+/**
+ * Implement a simple rotation control.
+ *
+ */
+class TouchSurfaceView extends GLSurfaceView {
+
+    public TouchSurfaceView(Context context) {
+        super(context);
+        mRenderer = new CubeRenderer();
+        setRenderer(mRenderer);
+        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+    }
+
+    @Override public boolean onTrackballEvent(MotionEvent e) {
+        mRenderer.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR;
+        mRenderer.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR;
+        requestRender();
+        return true;
+    }
+
+    @Override public boolean onTouchEvent(MotionEvent e) {
+        float x = e.getX();
+        float y = e.getY();
+        switch (e.getAction()) {
+        case MotionEvent.ACTION_MOVE:
+            float dx = x - mPreviousX;
+            float dy = y - mPreviousY;
+            mRenderer.mAngleX += dx * TOUCH_SCALE_FACTOR;
+            mRenderer.mAngleY += dy * TOUCH_SCALE_FACTOR;
+            requestRender();
+        }
+        mPreviousX = x;
+        mPreviousY = y;
+        return true;
+    }
+
+    /**
+     * Render a cube.
+     */
+    private class CubeRenderer implements GLSurfaceView.Renderer {
+        public CubeRenderer() {
+            mCube = new Cube();
+        }
+
+        public void onDrawFrame(GL10 gl) {
+            /*
+             * Usually, the first thing one might want to do is to clear
+             * the screen. The most efficient way of doing this is to use
+             * glClear().
+             */
+
+            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+            /*
+             * Now we're ready to draw some 3D objects
+             */
+
+            gl.glMatrixMode(GL10.GL_MODELVIEW);
+            gl.glLoadIdentity();
+            gl.glTranslatef(0, 0, -3.0f);
+            gl.glRotatef(mAngleX, 0, 1, 0);
+            gl.glRotatef(mAngleY, 1, 0, 0);
+
+            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+            mCube.draw(gl);
+        }
+
+        public int[] getConfigSpec() {
+            // We want a depth buffer, don't care about the
+            // details of the color buffer.
+            int[] configSpec = {
+                    EGL10.EGL_DEPTH_SIZE,   16,
+                    EGL10.EGL_NONE
+            };
+            return configSpec;
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+             gl.glViewport(0, 0, width, height);
+
+             /*
+              * Set our projection matrix. This doesn't have to be done
+              * each time we draw, but usually a new projection needs to
+              * be set when the viewport is resized.
+              */
+
+             float ratio = (float) width / height;
+             gl.glMatrixMode(GL10.GL_PROJECTION);
+             gl.glLoadIdentity();
+             gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            /*
+             * By default, OpenGL enables features that improve quality
+             * but reduce performance. One might want to tweak that
+             * especially on software renderer.
+             */
+            gl.glDisable(GL10.GL_DITHER);
+
+            /*
+             * Some one-time OpenGL initialization can be made here
+             * probably based on features of this particular context
+             */
+             gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+                     GL10.GL_FASTEST);
+
+
+             gl.glClearColor(1,1,1,1);
+             gl.glEnable(GL10.GL_CULL_FACE);
+             gl.glShadeModel(GL10.GL_SMOOTH);
+             gl.glEnable(GL10.GL_DEPTH_TEST);
+        }
+        private Cube mCube;
+        public float mAngleX;
+        public float mAngleY;
+    }
+
+    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
+    private final float TRACKBALL_SCALE_FACTOR = 36.0f;
+    private CubeRenderer mRenderer;
+    private float mPreviousX;
+    private float mPreviousY;
+}
+
+
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
index 23558e4..750a47b 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TranslucentGLSurfaceViewActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
 import android.os.Bundle;
 
 
@@ -37,7 +38,7 @@
         // of the cube:
         mGLSurfaceView.setRenderer(new CubeRenderer(true));
         // Use a surface format with an Alpha channel:
-        mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);
+        mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
         setContentView(mGLSurfaceView);
     }
 
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
index a09d0ca..59f3c6c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleActivity.java
@@ -17,6 +17,7 @@
 package com.example.android.apis.graphics;
 
 import android.app.Activity;
+import android.opengl.GLSurfaceView;
 import android.os.Bundle;
 
 public class TriangleActivity extends Activity {
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
index 5871857..451b927 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/TriangleRenderer.java
@@ -16,7 +16,6 @@
 
 package com.example.android.apis.graphics;
 
-import com.example.android.apis.R;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
@@ -24,15 +23,19 @@
 import java.nio.FloatBuffer;
 import java.nio.ShortBuffer;
 
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.opengl.GLSurfaceView;
 import android.opengl.GLU;
 import android.opengl.GLUtils;
 import android.os.SystemClock;
 
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.opengles.GL10;
+import com.example.android.apis.R;
 
 public class TriangleRenderer implements GLSurfaceView.Renderer{
 
@@ -51,7 +54,7 @@
         return configSpec;
     }
 
-    public void surfaceCreated(GL10 gl) {
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         /*
          * By default, OpenGL enables features that improve quality
          * but reduce performance. One might want to tweak that
@@ -113,7 +116,7 @@
         bitmap.recycle();
     }
 
-    public void drawFrame(GL10 gl) {
+    public void onDrawFrame(GL10 gl) {
         /*
          * By default, OpenGL enables features that improve quality
          * but reduce performance. One might want to tweak that
@@ -159,7 +162,7 @@
         mTriangle.draw(gl);
     }
 
-    public void sizeChanged(GL10 gl, int w, int h) {
+    public void onSurfaceChanged(GL10 gl, int w, int h) {
         gl.glViewport(0, 0, w, h);
 
         /*
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
index 4f9a488..9332941 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/Kube.java
@@ -20,7 +20,7 @@
 import android.os.Bundle;
 import android.view.Window;
 
-import com.example.android.apis.graphics.GLSurfaceView;
+import android.opengl.GLSurfaceView;
 
 import java.util.Random;
 
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
index e1e7635..252f566 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/kube/KubeRenderer.java
@@ -16,9 +16,10 @@
 
 package com.example.android.apis.graphics.kube;
 
-import com.example.android.apis.graphics.GLSurfaceView;
+import android.opengl.GLSurfaceView;
 
 import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 
@@ -36,7 +37,7 @@
         mCallback = callback;
     }
 
-    public void drawFrame(GL10 gl) {
+    public void onDrawFrame(GL10 gl) {
          if (mCallback != null) {
              mCallback.animate();
          }
@@ -82,7 +83,7 @@
         return configSpec;
     }
 
-    public void sizeChanged(GL10 gl, int width, int height) {
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
         gl.glViewport(0, 0, width, height);
 
         /*
@@ -105,7 +106,7 @@
         gl.glActiveTexture(GL10.GL_TEXTURE0);
     }
 
-    public void surfaceCreated(GL10 gl) {
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         // Nothing special, don't have any textures we need to recreate.
     }
 
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
index c41b684..1e58dae 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextActivity.java
@@ -16,11 +16,10 @@
 
 package com.example.android.apis.graphics.spritetext;
 
-import com.example.android.apis.graphics.GLSurfaceView;
-
 import javax.microedition.khronos.opengles.GL;
 
 import android.app.Activity;
+import android.opengl.GLSurfaceView;
 import android.os.Bundle;
 
 public class SpriteTextActivity extends Activity {
diff --git a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
index 835e832..b9369cd 100644
--- a/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
+++ b/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext/SpriteTextRenderer.java
@@ -16,17 +16,6 @@
 
 package com.example.android.apis.graphics.spritetext;
 
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Paint;
-import android.opengl.GLU;
-import android.opengl.GLUtils;
-import android.os.SystemClock;
-
-import com.example.android.apis.R;
-import com.example.android.apis.graphics.GLSurfaceView;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
@@ -35,8 +24,20 @@
 import java.nio.ShortBuffer;
 
 import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Paint;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+import android.os.SystemClock;
+
+import com.example.android.apis.R;
+
 public class SpriteTextRenderer implements GLSurfaceView.Renderer{
 
     public SpriteTextRenderer(Context context) {
@@ -59,7 +60,7 @@
         return configSpec;
     }
 
-    public void surfaceCreated(GL10 gl) {
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         /*
          * By default, OpenGL enables features that improve quality
          * but reduce performance. One might want to tweak that
@@ -141,7 +142,7 @@
         mNumericSprite.initialize(gl, mLabelPaint);
     }
 
-    public void drawFrame(GL10 gl) {
+    public void onDrawFrame(GL10 gl) {
         /*
          * By default, OpenGL enables features that improve quality
          * but reduce performance. One might want to tweak that
@@ -237,7 +238,7 @@
         mLabels.draw(gl, tx, ty, labelId);
     }
 
-    public void sizeChanged(GL10 gl, int w, int h) {
+    public void onSurfaceChanged(GL10 gl, int w, int h) {
         mWidth = w;
         mHeight = h;
         gl.glViewport(0, 0, w, h);
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/Link.java b/samples/ApiDemos/src/com/example/android/apis/text/Link.java
index b8d83c2..b569d19 100644
--- a/samples/ApiDemos/src/com/example/android/apis/text/Link.java
+++ b/samples/ApiDemos/src/com/example/android/apis/text/Link.java
@@ -19,13 +19,66 @@
 import com.example.android.apis.R;
 
 import android.app.Activity;
+import android.graphics.Typeface;
 import android.os.Bundle;
+import android.text.Html;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.StyleSpan;
+import android.text.style.URLSpan;
+import android.widget.TextView;
 
 public class Link extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
         setContentView(R.layout.link);
+
+        // text1 shows the android:autoLink property, which
+        // automatically linkifies things like URLs and phone numbers
+        // found in the text.  No java code is needed to make this
+        // work.
+
+        // text2 has links specified by putting <a> tags in the string
+        // resource.  By default these links will appear but not
+        // respond to user input.  To make them active, you need to
+        // call setMovementMethod() on the TextView object.
+
+        TextView t2 = (TextView) findViewById(R.id.text2);
+        t2.setMovementMethod(LinkMovementMethod.getInstance());
+
+        // text3 shows creating text with links from HTML in the Java
+        // code, rather than from a string resource.  Note that for a
+        // fixed string, using a (localizable) resource as shown above
+        // is usually a better way to go; this example is intended to
+        // illustrate how you might display text that came from a
+        // dynamic source (eg, the network).
+
+        TextView t3 = (TextView) findViewById(R.id.text3);
+        t3.setText(
+            Html.fromHtml(
+                "<b>text3:</b>  Text with a " +
+                "<a href=\"http://www.google.com\">link</a> " +
+                "created in the Java source code using HTML."));
+        t3.setMovementMethod(LinkMovementMethod.getInstance());
+
+        // text4 illustrates constructing a styled string containing a
+        // link without using HTML at all.  Again, for a fixed string
+        // you should probably be using a string resource, not a
+        // hardcoded value.
+
+        SpannableString ss = new SpannableString(
+            "text4: Click here to dial the phone.");
+
+        ss.setSpan(new StyleSpan(Typeface.BOLD), 0, 6,
+                   Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        ss.setSpan(new URLSpan("tel:4155551212"), 13, 17,
+                   Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        TextView t4 = (TextView) findViewById(R.id.text4);
+        t4.setText(ss);
+        t4.setMovementMethod(LinkMovementMethod.getInstance());
     }
 }
diff --git a/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java b/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java
new file mode 100644
index 0000000..ba82ed6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/text/Marquee.java
@@ -0,0 +1,31 @@
+/* 
+ * Copyright (C) 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.text;
+
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Marquee extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.marquee);
+    }
+}
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
index 97192e1..3074ca6 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/ApiDemosApplicationTests.java
@@ -17,6 +17,8 @@
 package com.example.android.apis;
 
 import android.test.ApplicationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * This is a simple framework for a test of an Application.  See 
@@ -45,12 +47,14 @@
        * explain any and all failures in other tests.  This is not guaranteed
        * to run before other tests, as junit uses reflection to find the tests.
        */
+      @SmallTest
       public void testPreconditions() {
       }
       
       /**
        * Test basic startup/shutdown of Application
        */
+      @MediumTest
       public void testSimpleCreate() {
           createApplication(); 
       }
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
index 5332fd5..340bedb 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/app/ForwardingTest.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.test.ActivityUnitTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.Button;
 
 /**
@@ -68,6 +69,7 @@
      * explain any and all failures in other tests.  This is not guaranteed
      * to run before other tests, as junit uses reflection to find the tests.
      */
+    @MediumTest
     public void testPreconditions() {
         startActivity(mStartIntent, null, null);
         mButton = (Button) getActivity().findViewById(R.id.go);
@@ -80,6 +82,7 @@
      * This test demonstrates examining the way that activity calls startActivity() to launch 
      * other activities.
      */
+    @MediumTest
     public void testSubLaunch() {
         Forwarding activity = startActivity(mStartIntent, null, null);
         mButton = (Button) activity.findViewById(R.id.go);
@@ -95,6 +98,7 @@
     /**
      * This test demonstrates ways to exercise the Activity's life cycle.
      */
+    @MediumTest
     public void testLifeCycleCreate() {
         Forwarding activity = startActivity(mStartIntent, null, null);
         
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
index 488a349..78fee41 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/app/LocalServiceTest.java
@@ -24,6 +24,8 @@
 import android.os.IBinder;
 import android.test.MoreAsserts;
 import android.test.ServiceTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * This is a simple framework for a test of a Service.  See {@link android.test.ServiceTestCase
@@ -51,12 +53,14 @@
      * explain any and all failures in other tests.  This is not guaranteed
      * to run before other tests, as junit uses reflection to find the tests.
      */
+    @SmallTest
     public void testPreconditions() {
     }
     
     /**
      * Test basic startup/shutdown of Service
      */
+    @SmallTest
     public void testStartable() {
         Intent startIntent = new Intent();
         startIntent.setClass(getContext(), LocalService.class);
@@ -66,6 +70,7 @@
     /**
      * Test binding to service
      */
+    @MediumTest
     public void testBindable() {
         Intent startIntent = new Intent();
         startIntent.setClass(getContext(), LocalService.class);
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
index c16ae5a..7cf0395 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/os/MorseCodeConverterTest.java
@@ -17,6 +17,7 @@
 package com.example.android.apis.os;
 
 import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * An example of a true unit test that tests the utility class {@link MorseCodeConverter}.
@@ -28,6 +29,7 @@
  */
 public class MorseCodeConverterTest extends TestCase {
 
+    @SmallTest
     public void testCharacterS() throws Exception {
 
         long[] expectedBeeps = {
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
index 2e8c1cd..91f712f 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2ActivityTest.java
@@ -19,6 +19,7 @@
 import com.example.android.apis.R;
 
 import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 
@@ -67,6 +68,7 @@
      * explain any and all failures in other tests.  This is not guaranteed
      * to run before other tests, as junit uses reflection to find the tests.
      */
+    @MediumTest
     public void testPreconditions() {
         assertTrue("center button should be right of left button",
                 mLeftButton.getRight() < mCenterButton.getLeft());
@@ -75,11 +77,13 @@
         assertTrue("left button should be focused", mLeftButton.isFocused());
     }
 
+    @MediumTest
     public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
         assertTrue("right button should be focused", mRightButton.isFocused());
     }
 
+    @MediumTest
     public void testGoingLeftFromRightButtonGoesToCenter()  {
         // Give right button focus by having it request focus.  We post it
         // to the UI thread because we are not running on the same thread, and
diff --git a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
index 8c9c8a5..b52e4b8 100644
--- a/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
+++ b/samples/ApiDemos/tests/src/com/example/android/apis/view/Focus2AndroidTest.java
@@ -20,6 +20,7 @@
 
 import android.content.Context;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.view.FocusFinder;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -87,6 +88,7 @@
      * explain any and all failures in other tests.  This is not guaranteed
      * to run before other tests, as junit uses reflection to find the tests.
      */
+    @SmallTest
     public void testPreconditions() {
         assertNotNull(mLeftButton);
         assertTrue("center button should be right of left button",
@@ -95,12 +97,14 @@
                 mCenterButton.getRight() < mRightButton.getLeft());
     }
 
+    @SmallTest
     public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
         assertEquals("right should be next focus from left",
                 mRightButton,
                 mFocusFinder.findNextFocus(mRoot, mLeftButton, View.FOCUS_RIGHT));
     }
 
+    @SmallTest
     public void testGoingLeftFromRightButtonGoesToCenter() {
         assertEquals("center should be next focus from right",
                 mCenterButton,
diff --git a/samples/Compass/Android.mk b/samples/Compass/Android.mk
new file mode 100644
index 0000000..9434582
--- /dev/null
+++ b/samples/Compass/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Compass
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/Compass/AndroidManifest.xml b/samples/Compass/AndroidManifest.xml
new file mode 100644
index 0000000..9aa5636
--- /dev/null
+++ b/samples/Compass/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This file describes the code in the Compass package, which is
+     used by the system to determine how to start your application and
+     integrate it with the rest of the system.  -->
+
+<!-- Declare the contents of this Android application.  The namespace
+     attribute brings in the Android platform namespace, and the package
+     supplies a unique name for the application.  When writing your
+     own application, the package name must be changed from "com.example.*"
+     to come from a domain that you own or have control over. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.compass">
+
+    <!-- This package contains an application...  The 'label' is the name
+         to display to the user for the overall application, and provides
+         a default label for all following components.  The syntax here is a
+         reference to one of our string resources.-->
+    <application android:label="@string/compass_app">
+
+        <!-- An Activity in the application - this is something the user
+             can launch and interact with.  The "name" attribute is the
+             name of the class within your package that implements this
+             activity. -->
+        <activity android:name="CompassActivity">
+
+            <!-- An IntentFilter tells the system when it should use your
+                 activity.  This allows the user to get to your activity
+                 without someone having to explicitly know to launch your
+                 class "com.example.android.compass_app.CompassActivity". -->
+            <intent-filter>
+                <!-- The MAIN action describes a main entry point into an
+                     activity, without any associated data. -->
+                <action android:name="android.intent.action.MAIN" />
+
+                <!-- This places this activity into the main app list. -->
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+        </activity>
+
+    </application>
+
+</manifest>
diff --git a/samples/Compass/res/values/strings.xml b/samples/Compass/res/values/strings.xml
new file mode 100644
index 0000000..7cf3da4
--- /dev/null
+++ b/samples/Compass/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+     them to be changed based on the locale and options. -->
+
+<resources>
+    <!-- Simple strings. -->
+    <string name="compass_app">Compass</string>
+</resources>
+
diff --git a/samples/Compass/src/com/example/android/compass/CompassActivity.java b/samples/Compass/src/com/example/android/compass/CompassActivity.java
new file mode 100644
index 0000000..c4b9566
--- /dev/null
+++ b/samples/Compass/src/com/example/android/compass/CompassActivity.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.compass;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+import static javax.microedition.khronos.opengles.GL10.*;
+
+import android.app.Activity;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLSurfaceView.Renderer;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * This class provides a basic demonstration of how to use the
+ * {@link android.hardware.SensorManager SensorManager} API to draw
+ * a 3D compass.
+ */
+public class CompassActivity extends Activity implements Renderer, SensorEventListener {
+    private GLSurfaceView mGLSurfaceView;
+    private SensorManager mSensorManager;
+    private float[] mGData = new float[3];
+    private float[] mMData = new float[3];
+    private float[] mR = new float[16];
+    private float[] mI = new float[16];
+    private FloatBuffer mVertexBuffer;
+    private FloatBuffer mColorBuffer;
+    private ByteBuffer mIndexBuffer;
+    private float[] mOrientation = new float[3];
+    private int mCount;
+
+    public CompassActivity() {
+    }
+
+    /** Called with the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+        mGLSurfaceView = new GLSurfaceView(this);
+        mGLSurfaceView.setRenderer(this);
+        setContentView(mGLSurfaceView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onResume();
+        mGLSurfaceView.onResume();
+        Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+        Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+        mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);
+        mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_GAME);
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onPause();
+        mGLSurfaceView.onPause();
+        mSensorManager.unregisterListener(this);
+    }
+
+    public int[] getConfigSpec() {
+        // We want a depth buffer, don't care about the
+        // details of the color buffer.
+        int[] configSpec = {
+                EGL10.EGL_DEPTH_SIZE,   16,
+                EGL10.EGL_NONE
+        };
+        return configSpec;
+    }
+
+    public void onDrawFrame(GL10 gl) {
+        /*
+         * Usually, the first thing one might want to do is to clear
+         * the screen. The most efficient way of doing this is to use
+         * glClear().
+         */
+
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+        /*
+         * Now we're ready to draw some 3D objects
+         */
+
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+        gl.glTranslatef(0, 0, -2);
+
+        /*
+         * All the magic happens here. The rotation matrix mR reported by
+         * SensorManager.getRotationMatrix() is a 4x4 row-major matrix.
+         * We need to use its inverse for rendering. The inverse is
+         * simply calculated by taking the matrix' transpose. However, since
+         * glMultMatrixf() expects a column-major matrix, we can use mR
+         * directly!
+         */
+        gl.glMultMatrixf(mR, 0);
+        // some test code which will be used/cleaned up before we ship this.
+        //gl.glMultMatrixf(mI, 0);
+
+        gl.glVertexPointer(3, GL_FLOAT, 0, mVertexBuffer);
+        gl.glColorPointer(4, GL_FLOAT, 0, mColorBuffer);
+        gl.glDrawElements(GL_LINES, 6, GL_UNSIGNED_BYTE, mIndexBuffer);
+    }
+
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
+        gl.glViewport(0, 0, width, height);
+
+        /*
+         * Set our projection matrix. This doesn't have to be done
+         * each time we draw, but usually a new projection needs to
+         * be set when the viewport is resized.
+         */
+
+        float ratio = (float) width / height;
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+    }
+
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        /*
+         * By default, OpenGL enables features that improve quality
+         * but reduce performance. One might want to tweak that
+         * especially on software renderer.
+         */
+        gl.glDisable(GL10.GL_DITHER);
+
+        /*
+         * Some one-time OpenGL initialization can be made here
+         * probably based on features of this particular context
+         */
+        gl.glClearColor(1,1,1,1);
+        gl.glEnable(GL10.GL_CULL_FACE);
+        gl.glShadeModel(GL10.GL_SMOOTH);
+        gl.glEnable(GL10.GL_DEPTH_TEST);
+
+        /*
+         * create / load the our 3D models here
+         */
+
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+        float vertices[] = {
+                0,0,0,
+                1,0,0,
+                0,1,0,
+                0,0,1
+        };
+        float colors[] = {
+                0,0,0,0,
+                1,0,0,1,
+                0,1,0,1,
+                0,0,1,1
+        };
+        byte indices[] = { 0, 1, 0, 2, 0, 3 };
+
+        // Buffers to be passed to gl*Pointer() functions
+        // must be direct, i.e., they must be placed on the
+        // native heap where the garbage collector cannot
+        // move them.
+        //
+        // Buffers with multi-byte datatypes (e.g., short, int, float)
+        // must have their byte order set to native order
+
+        ByteBuffer vbb;
+        vbb = ByteBuffer.allocateDirect(vertices.length*4);
+        vbb.order(ByteOrder.nativeOrder());
+        mVertexBuffer = vbb.asFloatBuffer();
+        mVertexBuffer.put(vertices);
+        mVertexBuffer.position(0);
+
+        vbb = ByteBuffer.allocateDirect(colors.length*4);
+        vbb.order(ByteOrder.nativeOrder());
+        mColorBuffer = vbb.asFloatBuffer();
+        mColorBuffer.put(colors);
+        mColorBuffer.position(0);
+
+        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
+        mIndexBuffer.put(indices);
+        mIndexBuffer.position(0);
+    }
+
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    public void onSensorChanged(SensorEvent event) {
+        int type = event.sensor.getType();
+        float[] data;
+        if (type == Sensor.TYPE_ACCELEROMETER) {
+            data = mGData;
+        } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
+            data = mMData;
+        } else {
+            // we should not be here.
+            return;
+        }
+        for (int i=0 ; i<3 ; i++)
+            data[i] = event.values[i];
+
+        SensorManager.getRotationMatrix(mR, mI, mGData, mMData);
+// some test code which will be used/cleaned up before we ship this.
+//        SensorManager.remapCoordinateSystem(mR,
+//                SensorManager.AXIS_X, SensorManager.AXIS_Z, mR);
+//        SensorManager.remapCoordinateSystem(mR,
+//                SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, mR);
+        SensorManager.getOrientation(mR, mOrientation);
+        float incl = SensorManager.getInclination(mI);
+
+        if (mCount++ > 50) {
+            final float rad2deg = (float)(180.0f/Math.PI);
+            mCount = 0;
+            Log.d("Compass", "yaw: " + (int)(mOrientation[0]*rad2deg) +
+                    "  pitch: " + (int)(mOrientation[1]*rad2deg) +
+                    "  roll: " + (int)(mOrientation[2]*rad2deg) +
+                    "  incl: " + (int)(incl*rad2deg)
+                    );
+        }
+    }
+}
diff --git a/samples/GlobalTime/src/com/android/globaltime/Clock.java b/samples/GlobalTime/src/com/android/globaltime/Clock.java
index 4b6c0f7..9aad71a 100644
--- a/samples/GlobalTime/src/com/android/globaltime/Clock.java
+++ b/samples/GlobalTime/src/com/android/globaltime/Clock.java
@@ -24,7 +24,7 @@
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
-import android.pim.DateUtils;
+import android.text.format.DateUtils;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.Interpolator;
 
diff --git a/samples/HelloActivity/tests/AndroidManifest.xml b/samples/HelloActivity/tests/AndroidManifest.xml
index 29b3a9a..5294d07 100644
--- a/samples/HelloActivity/tests/AndroidManifest.xml
+++ b/samples/HelloActivity/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
-      package="com.android.helloactivity.tests">
+      package="com.example.android.helloactivity.tests">
 
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
diff --git a/samples/HelloActivity/tests/src/com/android/helloactivity/HelloActivityTest.java b/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
similarity index 95%
rename from samples/HelloActivity/tests/src/com/android/helloactivity/HelloActivityTest.java
rename to samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
index 76eecf2..6e032da 100644
--- a/samples/HelloActivity/tests/src/com/android/helloactivity/HelloActivityTest.java
+++ b/samples/HelloActivity/tests/src/com/example/android/helloactivity/HelloActivityTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.helloactivity;
+package com.example.android.helloactivity;
 
 import android.test.ActivityInstrumentationTestCase;
 
diff --git a/samples/Home/res/values-cs/strings.xml b/samples/Home/res/values-cs/strings.xml
index 6d91727..2830534 100644
--- a/samples/Home/res/values-cs/strings.xml
+++ b/samples/Home/res/values-cs/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="home_title">Domů</string>
-  <string name="menu_notifications">Oznámení</string>
-  <string name="menu_search">Hledat</string>
-  <string name="menu_wallpaper">Tapeta</string>
-  <string name="show_all_apps">Vše</string>
-  <string name="wallpaper_instructions">Klepnutím na obrázek nastavíte tapetu portrétu</string>
+    <string name="home_title">"Domů"</string>
+    <string name="show_all_apps">"Vše"</string>
+    <string name="menu_wallpaper">"Tapeta"</string>
+    <string name="menu_search">"Hledat"</string>
+    <!-- no translation found for menu_settings (1769059051084007158) -->
+    <skip />
+    <string name="wallpaper_instructions">"Klepnutím na obrázek nastavíte tapetu portrétu"</string>
 </resources>
diff --git a/samples/Home/res/values-de-rDE/strings.xml b/samples/Home/res/values-de-rDE/strings.xml
index aa5c4c1..28a1b7c 100644
--- a/samples/Home/res/values-de-rDE/strings.xml
+++ b/samples/Home/res/values-de-rDE/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="home_title">Startseite</string>
-  <string name="menu_notifications">Benachrichtigungen</string>
-  <string name="menu_search">Suchen</string>
-  <string name="menu_wallpaper">Bildschirmhintergrund</string>
-  <string name="show_all_apps">Alle</string>
-  <string name="wallpaper_instructions">Tippen Sie auf Bild, um Porträt-Bildschirmhintergrund einzustellen</string>
+    <string name="home_title">"Startseite"</string>
+    <string name="show_all_apps">"Alle"</string>
+    <string name="menu_wallpaper">"Bildschirmhintergrund"</string>
+    <string name="menu_search">"Suchen"</string>
+    <!-- no translation found for menu_settings (1769059051084007158) -->
+    <skip />
+    <string name="wallpaper_instructions">"Tippen Sie auf Bild, um Porträt-Bildschirmhintergrund einzustellen"</string>
 </resources>
diff --git a/samples/Home/res/values-es-rUS/strings.xml b/samples/Home/res/values-es-rUS/strings.xml
index a0a5657..63252cc 100644
--- a/samples/Home/res/values-es-rUS/strings.xml
+++ b/samples/Home/res/values-es-rUS/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="home_title">Casa</string>
-  <string name="menu_notifications">Notificaciones</string>
-  <string name="menu_search">Búsqueda</string>
-  <string name="menu_wallpaper">Papel tapiz</string>
-  <string name="show_all_apps">Todo</string>
-  <string name="wallpaper_instructions">Puntee en la imagen para establecer papel tapiz vertical</string>
+    <string name="home_title">"Casa"</string>
+    <string name="show_all_apps">"Todo"</string>
+    <string name="menu_wallpaper">"Papel tapiz"</string>
+    <string name="menu_search">"Búsqueda"</string>
+    <!-- no translation found for menu_settings (1769059051084007158) -->
+    <skip />
+    <string name="wallpaper_instructions">"Puntee en la imagen para establecer papel tapiz vertical"</string>
 </resources>
diff --git a/samples/Home/res/values-nl-rNL/strings.xml b/samples/Home/res/values-nl-rNL/strings.xml
index 9e3a49d..4a5ae4f 100644
--- a/samples/Home/res/values-nl-rNL/strings.xml
+++ b/samples/Home/res/values-nl-rNL/strings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="home_title">Start</string>
-  <string name="menu_notifications">Meldingen</string>
-  <string name="menu_search">Zoeken</string>
-  <string name="menu_wallpaper">Achtergrond</string>
-  <string name="show_all_apps">Alles</string>
-  <string name="wallpaper_instructions">Tik op afbeelding om portretachtergrond in te stellen</string>
+    <string name="home_title">"Start"</string>
+    <string name="show_all_apps">"Alles"</string>
+    <string name="menu_wallpaper">"Achtergrond"</string>
+    <string name="menu_search">"Zoeken"</string>
+    <!-- no translation found for menu_settings (1769059051084007158) -->
+    <skip />
+    <string name="wallpaper_instructions">"Tik op afbeelding om portretachtergrond in te stellen"</string>
 </resources>
diff --git a/samples/LunarLander/tests/AndroidManifest.xml b/samples/LunarLander/tests/AndroidManifest.xml
index 656e302..1bc8364 100644
--- a/samples/LunarLander/tests/AndroidManifest.xml
+++ b/samples/LunarLander/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
-      package="com.android.lunarlander.tests">
+      package="com.example.android.lunarlander.tests">
     
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
diff --git a/samples/LunarLander/tests/src/com/android/lunarlander/LunarLanderTest.java b/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
similarity index 96%
rename from samples/LunarLander/tests/src/com/android/lunarlander/LunarLanderTest.java
rename to samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
index ce9d5f8..fae02da 100644
--- a/samples/LunarLander/tests/src/com/android/lunarlander/LunarLanderTest.java
+++ b/samples/LunarLander/tests/src/com/example/android/lunarlander/LunarLanderTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.lunarlander;
+package com.example.android.lunarlander;
 
 import android.test.ActivityInstrumentationTestCase;
 
diff --git a/samples/NotePad/AndroidManifest.xml b/samples/NotePad/AndroidManifest.xml
index 2dd675b..84e87dd 100644
--- a/samples/NotePad/AndroidManifest.xml
+++ b/samples/NotePad/AndroidManifest.xml
@@ -51,6 +51,8 @@
         <activity android:name="NoteEditor"
             android:theme="@android:style/Theme.Light"
             android:label="@string/title_note"
+            android:screenOrientation="sensor"
+            android:configChanges="keyboardHidden|orientation"
         >
             <!-- This filter says that we can view or edit the data of
                  a single note -->
diff --git a/samples/NotePad/res/layout/note_editor.xml b/samples/NotePad/res/layout/note_editor.xml
index dba55a1..c54a963 100644
--- a/samples/NotePad/res/layout/note_editor.xml
+++ b/samples/NotePad/res/layout/note_editor.xml
@@ -24,5 +24,6 @@
     android:scrollbars="vertical"
     android:fadingEdge="vertical"
     android:gravity="top"
+    android:textSize="22sp"
     android:capitalize="sentences"
 />
diff --git a/samples/NotePad/src/com/google/provider/NotePad.java b/samples/NotePad/src/com/google/provider/NotePad.java
new file mode 100644
index 0000000..f8de69b
--- /dev/null
+++ b/samples/NotePad/src/com/google/provider/NotePad.java
@@ -0,0 +1,65 @@
+/* 
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.provider;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for NotePadProvider
+ */
+public final class NotePad {
+    /**
+     * Notes table
+     */
+    public static final class Notes implements BaseColumns {
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI
+                = Uri.parse("content://com.google.provider.NotePad/notes");
+
+        /**
+         * The default sort order for this table
+         */
+        public static final String DEFAULT_SORT_ORDER = "modified DESC";
+
+        /**
+         * The title of the note
+         * <P>Type: TEXT</P>
+         */
+        public static final String TITLE = "title";
+
+        /**
+         * The note itself
+         * <P>Type: TEXT</P>
+         */
+        public static final String NOTE = "note";
+
+        /**
+         * The timestamp for when the note was created
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String CREATED_DATE = "created";
+
+        /**
+         * The timestamp for when the note was last modified
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String MODIFIED_DATE = "modified";
+    }
+}
diff --git a/samples/NotePad/tests/AndroidManifest.xml b/samples/NotePad/tests/AndroidManifest.xml
index fc6c1cd..afd502b 100644
--- a/samples/NotePad/tests/AndroidManifest.xml
+++ b/samples/NotePad/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
-      package="com.android.notepad.tests">
+      package="com.example.android.notepad.tests">
     
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
diff --git a/samples/NotePad/tests/src/com/android/notepad/NotePadTest.java b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
similarity index 96%
rename from samples/NotePad/tests/src/com/android/notepad/NotePadTest.java
rename to samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
index 48fc264..452c599 100644
--- a/samples/NotePad/tests/src/com/android/notepad/NotePadTest.java
+++ b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.notepad;
+package com.example.android.notepad;
 
 import android.test.ActivityInstrumentationTestCase;
 
diff --git a/samples/PlatformLibrary/Android.mk b/samples/PlatformLibrary/Android.mk
new file mode 100644
index 0000000..d700386
--- /dev/null
+++ b/samples/PlatformLibrary/Android.mk
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This makefile shows how to build your own shared library that can be
+# shipped on the system of a phone, and included additional examples of
+# including JNI code with the library and writing client applications against it.
+
+LOCAL_PATH := $(call my-dir)
+
+# the library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= com.example.android.platform_library
+
+# Only compile source java files for the platform library.
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+
+include $(BUILD_JAVA_LIBRARY)
+
+# ============================================================
+
+# Also build all of the sub-targets under this one: the library's
+# associated JNI code, and a sample client of the library.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/PlatformLibrary/README.txt b/samples/PlatformLibrary/README.txt
new file mode 100644
index 0000000..e2a7c80
--- /dev/null
+++ b/samples/PlatformLibrary/README.txt
@@ -0,0 +1,78 @@
+Platform Library Example
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+This directory contains a full example of writing your own Android platform
+shared library, without changing the Android framework.  It also shows how to
+write JNI code for incorporating native code into the library, and a client
+application that uses the library.
+
+This example is ONLY for people working with the open source platform to
+create a system image that will be delivered on a device which will include
+a custom library as shown here.  It can not be used to create a third party
+shared library, which is not currently supported in Android.
+
+Note that while this example is almost entirely self-contained -- you can
+build it and run the client app without any changes to the framework -- there
+is one change you must make so that the system will recognize your library:
+
+In frameworks/base/data/etc/permissions.xml is a list of all of the optional
+shared libraries available in the system.  You will need to add an entry at
+the bottom of this file for your own shared library, which looks like this
+for our sample code here:
+
+    <library name="com.example.android.platform_library"
+            file="/system/framework/com.example.android.platform_library.jar"/>
+
+
+There are three major parts of this example, supplying three distinct
+build targets and corresponding build outputs:
+
+
+com.example.android.platform_library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The top-level Android.mk defines the rules to build the shared library itself,
+whose target is "com.example.android.platform_library".  The code for this
+library lives under java/.
+
+Note that the product for this library is a raw .jar file, NOT a .apk, which
+means there is no manifest or resources associated with the library.
+Unfortunately this means that if you need any resources for the library, such
+as drawables or layout files, you will need to add these to the core framework
+resources under frameworks/base/res.  Please make sure when doing this that
+you do not make any of these resources public, they should not become part of
+the Android API.  In the future we will allow shared libraries to have their
+own resources.
+
+Other than that, the library is very straight-forward, and you can write
+basically whatever code you want.  You can also put code in other Java
+namespaces -- the namespace given in the <library> tag above is just the
+public unique name by which clients will link to your library, but once this
+link happens all of the Java namespaces in that library will be available
+to the client.
+
+
+libplatform_library_jni
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This is an optional example of how to write JNI code associated with a
+shared library.  This code lives under jni/.  The jni/Android.mk file defines
+the rules for building the final .so in which the code lives.  This example
+provides everything needed to hook up the native code with the Java library
+and call through to it, plus a very simple JNI call.
+
+
+PlatformLibraryClient
+~~~~~~~~~~~~~~~~~~~~~
+
+This shows an example of how you can write client applications for your new
+shared library.  This code lives under client/.  Note that the example is
+simply a regular Android .apk, like all of the other .apks created by the
+build system.  The only two special things needed to use your library are:
+
+- A LOCAL_JAVA_LIBRARIES line in the Android.mk to have the build system link
+against your shared library.
+
+- A <uses-library> line in the AndroidManifest.xml to have the runtime load
+your library into the application.
diff --git a/samples/PlatformLibrary/client/Android.mk b/samples/PlatformLibrary/client/Android.mk
new file mode 100644
index 0000000..cfd5493
--- /dev/null
+++ b/samples/PlatformLibrary/client/Android.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This makefile is an example of writing an application that will link against
+# a custom shared library included with an Android system.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_PACKAGE_NAME := PlatformLibraryClient
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Link against the current Android SDK.
+LOCAL_SDK_VERSION := current
+
+# Also link against our own custom library.
+LOCAL_JAVA_LIBRARIES := com.example.android.platform_library
+
+include $(BUILD_PACKAGE)
diff --git a/samples/PlatformLibrary/client/AndroidManifest.xml b/samples/PlatformLibrary/client/AndroidManifest.xml
new file mode 100644
index 0000000..be0d9a1
--- /dev/null
+++ b/samples/PlatformLibrary/client/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is an example of writing a client application for a custom
+     platform library. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.platform_library.client">
+    
+    <application android:label="Platform Lib Client">
+    
+        <!-- This tells the system about the custom library used by the
+             application, so that it can be properly loaded and linked
+             to the app when the app is initialized. -->
+        <uses-library android:name="com.example.android.platform_library" />
+        
+        <activity android:name="Client">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java b/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java
new file mode 100644
index 0000000..8722c72
--- /dev/null
+++ b/samples/PlatformLibrary/client/src/com/example/android/platform_library/client/Client.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.platform_library.client;
+
+import com.example.android.platform_library.PlatformLibrary;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+/**
+ * Use a custom platform library.
+ */
+public class Client extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Call an API on the library.
+        PlatformLibrary pl = new PlatformLibrary();
+        int res = pl.getInt(false);
+        
+        // We'll just make our own view to show the result.
+        TextView tv = new TextView(this);
+        tv.setText("Got from lib: " + res);
+        setContentView(tv);
+    }
+}
+
diff --git a/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java b/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
new file mode 100644
index 0000000..68154ec
--- /dev/null
+++ b/samples/PlatformLibrary/java/com/example/android/platform_library/PlatformLibrary.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.platform_library;
+
+import android.util.Config;
+import android.util.Log;
+
+public final class PlatformLibrary {    
+    static {
+        /*
+         * Load the library.  If it's already loaded, this does nothing.
+         */
+        System.loadLibrary("platform_library_jni");
+    }
+
+    private int mJniInt = -1;
+
+    public PlatformLibrary() {}
+
+    /*
+     * Test native methods.
+     */
+    public int getInt(boolean bad) {
+        /* this alters mJniInt */
+        int result = getJniInt(bad);
+
+        /* reverse a string, for no very good reason */
+        String reverse = reverseString("Android!");
+
+        Log.i("PlatformLibrary", "getInt: " + result + ", '" + reverse + "'");
+
+        return mJniInt;
+    }
+
+    /*
+     * Simple method, called from native code.
+     */
+    private static void yodel(String msg) {
+        Log.d("PlatformLibrary", "yodel: " + msg);
+    }
+
+    /*
+     * Trivial native method call.  If "bad" is true, this will throw an
+     * exception.
+     */
+    native private int getJniInt(boolean bad);
+
+    /*
+     * Native method that returns a new string that is the reverse of
+     * the original.  This also calls yodel().
+     */
+    native private static String reverseString(String str);
+}
diff --git a/samples/PlatformLibrary/jni/Android.mk b/samples/PlatformLibrary/jni/Android.mk
new file mode 100644
index 0000000..1bdefa1
--- /dev/null
+++ b/samples/PlatformLibrary/jni/Android.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This makefile supplies the rules for building a library of JNI code for
+# use by our example platform shared library.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# This is the target being built.
+LOCAL_MODULE:= libplatform_library_jni
+
+# All of the source files that we will compile.
+LOCAL_SRC_FILES:= \
+	PlatformLibrary.cpp
+
+# All of the shared libraries we link against.
+LOCAL_SHARED_LIBRARIES := \
+	libandroid_runtime \
+	libnativehelper \
+	libcutils \
+	libutils
+
+# No static libraries.
+LOCAL_STATIC_LIBRARIES :=
+
+# Also need the JNI headers.
+LOCAL_C_INCLUDES += \
+	$(JNI_H_INCLUDE)
+
+# No specia compiler flags.
+LOCAL_CFLAGS +=
+
+# Don't prelink this library.  For more efficient code, you may want
+# to add this library to the prelink map and set this to true.
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/samples/PlatformLibrary/jni/PlatformLibrary.cpp b/samples/PlatformLibrary/jni/PlatformLibrary.cpp
new file mode 100644
index 0000000..ad60002
--- /dev/null
+++ b/samples/PlatformLibrary/jni/PlatformLibrary.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PlatformLibrary"
+#include "utils/Log.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "jni.h"
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Field/method IDs and class object references.
+ *
+ * You should not need to store the JNIEnv pointer in here.  It is
+ * thread-specific and will be passed back in on every call.
+ */
+static struct {
+    jclass      platformLibraryClass;
+    jfieldID    jniInt;
+    jmethodID   yodel;
+} gCachedState;
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Helper function to throw an arbitrary exception.
+ *
+ * Takes the exception class name, a format string, and one optional integer
+ * argument (useful for including an error code, perhaps from errno).
+ */
+static void throwException(JNIEnv* env, const char* ex, const char* fmt,
+    int data) {
+
+    if (jclass cls = env->FindClass(ex)) {
+        if (fmt != NULL) {
+            char msg[1000];
+            snprintf(msg, sizeof(msg), fmt, data);
+            env->ThrowNew(cls, msg);
+        } else {
+            env->ThrowNew(cls, NULL);
+        }
+
+        /*
+         * This is usually not necessary -- local references are released
+         * automatically when the native code returns to the VM.  It's
+         * required if the code doesn't actually return, e.g. it's sitting
+         * in a native event loop.
+         */
+        env->DeleteLocalRef(cls);
+    }
+}
+
+/*
+ * Trivial sample method.
+ *
+ * If "bad" is true, this throws an exception.  Otherwise, this sets the
+ * "mJniInt" field to 42 and returns 24.
+ */
+static jint PlatformLibrary_getJniInt(JNIEnv* env, jobject thiz, jboolean bad) {
+    if (bad) {
+        throwException(env, "java/lang/IllegalStateException",
+                "you are bad", 0);
+        return 0;       /* return value will be ignored */
+    }
+    env->SetIntField(thiz, gCachedState.jniInt, 42);
+    return (jint)24;
+}
+
+/*
+ * A more complex sample method.
+ *
+ * This takes a String as an argument, and returns a new String with
+ * characters in reverse order.  The new string is passed to another method.
+ * This demonstrates basic String manipulation functions and method
+ * invocation.
+ *
+ * This method is declared "static", so there's no "this" pointer; instead,
+ * we get a pointer to the class object.
+ */
+static jstring PlatformLibrary_reverseString(JNIEnv* env, jclass clazz,
+    jstring str) {
+
+    if (str == NULL) {
+        throwException(env, "java/lang/NullPointerException", NULL, 0);
+        return NULL;
+    }
+
+    /*
+     * Get a pointer to the string's UTF-16 character data.  The data
+     * may be a copy or a pointer to the original.  Since String data
+     * is immutable, we're not allowed to touch it.
+     */
+    const jchar* strChars = env->GetStringChars(str, NULL);
+    if (strChars == NULL) {
+        /* something went wrong */
+        LOGW("Couldn't get string chars\n");
+        return NULL;
+    }
+    jsize strLength = env->GetStringLength(str);
+
+    /*
+     * Write a progress message to the log.  Log messages are UTF-8, so
+     * we want to convert the string to show it.
+     */
+    const char* printable = env->GetStringUTFChars(str, NULL);
+    if (printable != NULL) {
+        LOGD("Reversing string '%s'\n", printable);
+        env->ReleaseStringUTFChars(str, printable);
+    }
+
+    /*
+     * Copy the characters to temporary storage, reversing as we go.
+     */
+    jchar tempChars[strLength];
+    for (int i = 0; i < strLength; i++) {
+        tempChars[i] = strChars[strLength -1 -i];
+    }
+
+    /*
+     * Release the original String.  That way, if something fails later on,
+     * we don't have to worry about this leading to a memory leak.
+     */
+    env->ReleaseStringChars(str, strChars);
+    strChars = NULL;            /* this pointer no longer valid */
+
+    /*
+     * Create a new String with the chars.
+     */
+    jstring result = env->NewString(tempChars, strLength);
+    if (result == NULL) {
+        LOGE("NewString failed\n");
+        return NULL;
+    }
+
+    /*
+     * Now let's do something with it.  We already have the methodID for
+     * "yodel", so we can invoke it directly.  It's in our class, so we
+     * can use the Class object reference that was passed in.
+     */
+    env->CallStaticVoidMethod(clazz, gCachedState.yodel, result);
+
+    return result;
+}
+
+
+// ----------------------------------------------------------------------------
+
+/*
+ * Array of methods.
+ *
+ * Each entry has three fields: the name of the method, the method
+ * signature, and a pointer to the native implementation.
+ */
+static const JNINativeMethod gMethods[] = {
+    { "getJniInt",          "(Z)I",
+                        (void*)PlatformLibrary_getJniInt },
+    { "reverseString",      "(Ljava/lang/String;)Ljava/lang/String;",
+                        (void*)PlatformLibrary_reverseString },
+};
+
+/*
+ * Do some (slow-ish) lookups now and save the results.
+ *
+ * Returns 0 on success.
+ */
+static int cacheIds(JNIEnv* env, jclass clazz) {
+    /*
+     * Save the class in case we want to use it later.  Because this is a
+     * reference to the Class object, we need to convert it to a JNI global
+     * reference.
+     */
+    gCachedState.platformLibraryClass = (jclass) env->NewGlobalRef(clazz);
+    if (clazz == NULL) {
+        LOGE("Can't create new global ref\n");
+        return -1;
+    }
+
+    /*
+     * Cache field and method IDs.  IDs are not references, which means we
+     * don't need to call NewGlobalRef on them.
+     */
+    gCachedState.jniInt = env->GetFieldID(clazz, "mJniInt", "I");
+    if (gCachedState.jniInt == NULL) {
+        LOGE("Can't find PlatformLibrary.mJniInt\n");
+        return -1;
+    }
+
+    gCachedState.yodel = env->GetStaticMethodID(clazz, "yodel",
+        "(Ljava/lang/String;)V");
+    if (gCachedState.yodel == NULL) {
+        LOGE("Can't find PlatformLibrary.yodel\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * Explicitly register all methods for our class.
+ *
+ * While we're at it, cache some class references and method/field IDs.
+ *
+ * Returns 0 on success.
+ */
+static int registerMethods(JNIEnv* env) {
+    static const char* const kClassName =
+        "com/example/android/platform_library/PlatformLibrary";
+    jclass clazz;
+
+    /* look up the class */
+    clazz = env->FindClass(kClassName);
+    if (clazz == NULL) {
+        LOGE("Can't find class %s\n", kClassName);
+        return -1;
+    }
+
+    /* register all the methods */
+    if (env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
+    {
+        LOGE("Failed registering methods for %s\n", kClassName);
+        return -1;
+    }
+
+    /* fill out the rest of the ID cache */
+    return cacheIds(env, clazz);
+}
+
+// ----------------------------------------------------------------------------
+
+/*
+ * This is called by the VM when the shared library is first loaded.
+ */
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    if (registerMethods(env) != 0) {
+        LOGE("ERROR: PlatformLibrary native registration failed\n");
+        goto bail;
+    }
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/samples/SkeletonApp/tests/AndroidManifest.xml b/samples/SkeletonApp/tests/AndroidManifest.xml
index 2a6a7d6..fac1f41 100644
--- a/samples/SkeletonApp/tests/AndroidManifest.xml
+++ b/samples/SkeletonApp/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
-      package="com.android.skeletonapp.tests">
+      package="com.example.android.skeletonapp.tests">
     
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
diff --git a/samples/SkeletonApp/tests/src/com/android/skeletonapp/SkeletonAppTest.java b/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
similarity index 96%
rename from samples/SkeletonApp/tests/src/com/android/skeletonapp/SkeletonAppTest.java
rename to samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
index 58518e2..3123348 100644
--- a/samples/SkeletonApp/tests/src/com/android/skeletonapp/SkeletonAppTest.java
+++ b/samples/SkeletonApp/tests/src/com/example/android/skeletonapp/SkeletonAppTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.skeletonapp;
+package com.example.android.skeletonapp;
 
 import android.test.ActivityInstrumentationTestCase;
 
diff --git a/samples/Snake/tests/AndroidManifest.xml b/samples/Snake/tests/AndroidManifest.xml
index 63eadf4..382506c 100644
--- a/samples/Snake/tests/AndroidManifest.xml
+++ b/samples/Snake/tests/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
-      package="com.android.snake.tests">
+      package="com.example.android.snake.tests">
     
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
diff --git a/samples/Snake/tests/src/com/android/snake/SnakeTest.java b/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
similarity index 96%
rename from samples/Snake/tests/src/com/android/snake/SnakeTest.java
rename to samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
index 554bdbf..35d1b12 100644
--- a/samples/Snake/tests/src/com/android/snake/SnakeTest.java
+++ b/samples/Snake/tests/src/com/example/android/snake/SnakeTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.snake;
+package com.example.android.snake;
 
 import android.test.ActivityInstrumentationTestCase;
 
diff --git a/samples/SoftKeyboard/Android.mk b/samples/SoftKeyboard/Android.mk
new file mode 100755
index 0000000..dfd546e
--- /dev/null
+++ b/samples/SoftKeyboard/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := SoftKeyboard
+
+include $(BUILD_PACKAGE)
diff --git a/samples/SoftKeyboard/AndroidManifest.xml b/samples/SoftKeyboard/AndroidManifest.xml
new file mode 100755
index 0000000..61b5131
--- /dev/null
+++ b/samples/SoftKeyboard/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
+        package="com.example.android.softkeyboard">
+    <application android:label="@string/ime_name">
+        <service android:name="SoftKeyboard"
+                android:permission="android.permission.BIND_INPUT_METHOD">
+            <intent-filter>
+                <action android:name="android.view.InputMethod" />
+            </intent-filter>
+            <meta-data android:name="android.view.im" android:resource="@xml/method" />
+        </service>
+    </application>
+</manifest>
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png
new file mode 100644
index 0000000..6cee596
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_delete.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png
new file mode 100755
index 0000000..c0d6d13
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_done.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png
new file mode 100644
index 0000000..cbe2b15
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_return.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png
new file mode 100644
index 0000000..d059628
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_shift.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png b/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png
new file mode 100644
index 0000000..09b94d9
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable/sym_keyboard_space.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/layout/input.xml b/samples/SoftKeyboard/res/layout/input.xml
new file mode 100755
index 0000000..1b57468
--- /dev/null
+++ b/samples/SoftKeyboard/res/layout/input.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<com.example.android.softkeyboard.LatinKeyboardView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/keyboard"
+        android:layout_alignParentBottom="true"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        />
diff --git a/samples/SoftKeyboard/res/values-land/dimens.xml b/samples/SoftKeyboard/res/values-land/dimens.xml
new file mode 100644
index 0000000..1929ae0
--- /dev/null
+++ b/samples/SoftKeyboard/res/values-land/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <dimen name="key_height">46px</dimen>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/colors.xml b/samples/SoftKeyboard/res/values/colors.xml
new file mode 100644
index 0000000..74d103a
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+<resources>
+    <color name="candidate_normal">#FF000000</color>
+    <color name="candidate_recommended">#FFE35900</color>
+    <color name="candidate_other">#ff808080</color>
+    <color name="candidate_background">#bbffffff</color>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/dimens.xml b/samples/SoftKeyboard/res/values/dimens.xml
new file mode 100644
index 0000000..cea6e50
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <dimen name="key_height">50px</dimen>
+    <dimen name="candidate_font_height">16sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/values/strings.xml b/samples/SoftKeyboard/res/values/strings.xml
new file mode 100644
index 0000000..c1e306d
--- /dev/null
+++ b/samples/SoftKeyboard/res/values/strings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Title for Latin keyboard  -->
+    <string name="ime_name">Sample Soft Keyboard</string>
+
+    <!-- Symbols that are commonly considered word separators in this language -->
+    <string name="word_separators">\u0020.,;:!?\n()[]*&amp;@{}/&lt;&gt;_+=|&quot;</string>
+    
+    <!-- Labels on soft keys -->
+    <string name="label_done">Done</string>
+    <string name="label_search">Search</string>
+    <string name="label_enter">Enter</string>
+    <string name="label_next">Next</string>
+    <string name="label_previous">Previous</string>
+</resources>
diff --git a/samples/SoftKeyboard/res/xml/method.xml b/samples/SoftKeyboard/res/xml/method.xml
new file mode 100644
index 0000000..d246624
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/method.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2008, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Search Manager. -->
+
+<input-method xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/samples/SoftKeyboard/res/xml/qwerty.xml b/samples/SoftKeyboard/res/xml/qwerty.xml
new file mode 100755
index 0000000..e81d9f1
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/qwerty.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="10%p"
+    android:horizontalGap="0px"
+    android:verticalGap="0px"
+    android:keyHeight="@dimen/key_height"
+    >
+
+    <Row>
+        <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
+        <Key android:codes="119" android:keyLabel="w"/>
+        <Key android:codes="101" android:keyLabel="e"/>
+        <Key android:codes="114" android:keyLabel="r"/>
+        <Key android:codes="116" android:keyLabel="t"/>
+        <Key android:codes="121" android:keyLabel="y"/>
+        <Key android:codes="117" android:keyLabel="u"/>
+        <Key android:codes="105" android:keyLabel="i"/>
+        <Key android:codes="111" android:keyLabel="o"/>
+        <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p" 
+                android:keyEdgeFlags="left"/>
+        <Key android:codes="115" android:keyLabel="s"/>
+        <Key android:codes="100" android:keyLabel="d"/>
+        <Key android:codes="102" android:keyLabel="f"/>
+        <Key android:codes="103" android:keyLabel="g"/>
+        <Key android:codes="104" android:keyLabel="h"/>
+        <Key android:codes="106" android:keyLabel="j"/>
+        <Key android:codes="107" android:keyLabel="k"/>
+        <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift" 
+                android:keyWidth="15%p" android:isModifier="true"
+                android:isSticky="true" android:keyEdgeFlags="left"/>
+        <Key android:codes="122" android:keyLabel="z"/>
+        <Key android:codes="120" android:keyLabel="x"/>
+        <Key android:codes="99" android:keyLabel="c"/>
+        <Key android:codes="118" android:keyLabel="v"/>
+        <Key android:codes="98" android:keyLabel="b"/>
+        <Key android:codes="110" android:keyLabel="n"/>
+        <Key android:codes="109" android:keyLabel="m"/>
+        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete" 
+                android:keyWidth="15%p" android:keyEdgeFlags="right"
+                android:isRepeatable="true"/>
+    </Row>
+    
+    <Row android:rowEdgeFlags="bottom">
+        <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done" 
+                android:keyWidth="20%p" android:keyEdgeFlags="left"/>
+        <Key android:codes="-2" android:keyLabel="123" android:keyWidth="15%p"/>
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
+                android:keyWidth="30%p" android:isRepeatable="true"/>
+        <Key android:codes="46,44" android:keyLabel=". ,"
+                android:keyWidth="15%p"/>
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return" 
+                android:keyWidth="20%p" android:keyEdgeFlags="right"/>
+    </Row>
+</Keyboard>
+    
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/xml/symbols.xml b/samples/SoftKeyboard/res/xml/symbols.xml
new file mode 100755
index 0000000..a28d752
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/symbols.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="10%p"
+    android:horizontalGap="0px"
+    android:verticalGap="0px"
+    android:keyHeight="@dimen/key_height"
+    >
+
+    <Row>
+        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
+        <Key android:codes="50" android:keyLabel="2"/>
+        <Key android:codes="51" android:keyLabel="3"/>
+        <Key android:codes="52" android:keyLabel="4"/>
+        <Key android:codes="53" android:keyLabel="5"/>
+        <Key android:codes="54" android:keyLabel="6"/>
+        <Key android:codes="55" android:keyLabel="7"/>
+        <Key android:codes="56" android:keyLabel="8"/>
+        <Key android:codes="57" android:keyLabel="9"/>
+        <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:codes="64" android:keyLabel="\@" android:keyEdgeFlags="left"/>
+        <Key android:codes="35" android:keyLabel="\#"/>
+        <Key android:codes="36" android:keyLabel="$"/>
+        <Key android:codes="37" android:keyLabel="%"/>
+        <Key android:codes="38" android:keyLabel="&amp;"/>
+        <Key android:codes="42" android:keyLabel="*"/>
+        <Key android:codes="45" android:keyLabel="-"/>
+        <Key android:codes="61" android:keyLabel="="/>
+        <Key android:codes="40" android:keyLabel="("/>
+        <Key android:codes="41" android:keyLabel=")" android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+                android:keyWidth="15%p" android:isModifier="true"
+                android:isSticky="true" android:keyEdgeFlags="left"/>
+        <Key android:codes="33" android:keyLabel="!" />
+        <Key android:codes="34" android:keyLabel="&quot;"/>
+        <Key android:codes="39" android:keyLabel="\'"/>
+        <Key android:codes="58" android:keyLabel=":"/>
+        <Key android:codes="59" android:keyLabel=";"/>
+        <Key android:codes="47" android:keyLabel="/" />
+        <Key android:codes="63" android:keyLabel="\?"/>
+        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+                android:keyWidth="15%p" android:keyEdgeFlags="right"
+                android:isRepeatable="true"/>
+    </Row>
+    
+    <Row  android:rowEdgeFlags="bottom">
+        <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
+                android:keyWidth="20%p" android:keyEdgeFlags="left" />
+        <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p" 
+                android:isRepeatable="true"/>
+        <Key android:codes="44" android:keyLabel="," android:keyWidth="15%p" />
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+                android:keyWidth="20%p" android:keyEdgeFlags="right"
+                />
+    </Row>
+</Keyboard>
\ No newline at end of file
diff --git a/samples/SoftKeyboard/res/xml/symbols_shift.xml b/samples/SoftKeyboard/res/xml/symbols_shift.xml
new file mode 100755
index 0000000..d7139f3
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/symbols_shift.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="10%p"
+    android:horizontalGap="0px"
+    android:verticalGap="0px"
+    android:keyHeight="@dimen/key_height"
+    >
+
+    <Row>
+        <Key android:codes="126" android:keyLabel="~" android:keyEdgeFlags="left"/>
+        <Key android:codes="177" android:keyLabel="±"/>
+        <Key android:codes="215" android:keyLabel="×"/>
+        <Key android:codes="247" android:keyLabel="÷"/>
+        <Key android:codes="8226" android:keyLabel="•"/>
+        <Key android:codes="176" android:keyLabel="°"/>
+        <Key android:codes="96" android:keyLabel="`"/>
+        <Key android:codes="180" android:keyLabel="´"/>
+        <Key android:codes="123" android:keyLabel="{"/>
+        <Key android:codes="125" android:keyLabel="}" android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:codes="169" android:keyLabel="©" android:keyEdgeFlags="left"/>
+        <Key android:codes="163" android:keyLabel="£"/>
+        <Key android:codes="8364" android:keyLabel="€"/>
+        <Key android:codes="94" android:keyLabel="^"/>
+        <Key android:codes="174" android:keyLabel="®"/>
+        <Key android:codes="165" android:keyLabel="¥"/>
+        <Key android:codes="95" android:keyLabel="_"/>
+        <Key android:codes="43" android:keyLabel="+"/>
+        <Key android:codes="91" android:keyLabel="["/>
+        <Key android:codes="93" android:keyLabel="]" android:keyEdgeFlags="right"/>
+    </Row>
+    
+    <Row>
+        <Key android:codes="-1" android:keyIcon="@drawable/sym_keyboard_shift"
+                android:keyWidth="15%p" android:isModifier="true"
+                android:isSticky="true" android:keyEdgeFlags="left"/>
+        <Key android:codes="161" android:keyLabel="¡" />
+        <Key android:codes="60" android:keyLabel="&lt;"/>
+        <Key android:codes="62" android:keyLabel="&gt;"/>
+        <Key android:codes="162" android:keyLabel="¢"/>
+        <Key android:codes="124" android:keyLabel="|"/>
+        <Key android:codes="92" android:keyLabel="\\" />
+        <Key android:codes="191" android:keyLabel="¿"/>
+        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+                android:keyWidth="15%p" android:keyEdgeFlags="right"
+                android:isRepeatable="true"/>
+    </Row>
+    
+    <Row android:rowEdgeFlags="bottom">
+        <Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done" 
+                android:keyWidth="20%p" android:keyEdgeFlags="left" />
+        <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
+        <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p" 
+                android:isRepeatable="true"/>
+        <Key android:codes="8230" android:keyLabel="…" android:keyWidth="15%p" />
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
+                android:keyWidth="20%p" android:keyEdgeFlags="right" />
+    </Row>
+</Keyboard>
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
new file mode 100755
index 0000000..1e79cd7
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.example.android.softkeyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CandidateView extends View {
+
+    private static final int OUT_OF_BOUNDS = -1;
+
+    private SoftKeyboard mService;
+    private List<String> mSuggestions;
+    private int mSelectedIndex;
+    private int mTouchX = OUT_OF_BOUNDS;
+    private Drawable mSelectionHighlight;
+    private boolean mTypedWordValid;
+    
+    private Rect mBgPadding;
+
+    private static final int MAX_SUGGESTIONS = 32;
+    private static final int SCROLL_PIXELS = 20;
+    
+    private int[] mWordWidth = new int[MAX_SUGGESTIONS];
+    private int[] mWordX = new int[MAX_SUGGESTIONS];
+
+    private static final int X_GAP = 10;
+    
+    private static final List<String> EMPTY_LIST = new ArrayList<String>();
+
+    private int mColorNormal;
+    private int mColorRecommended;
+    private int mColorOther;
+    private Paint mPaint;
+    private boolean mScrolled;
+    private int mTargetScrollX;
+    
+    private int mTotalWidth;
+    
+    private GestureDetector mGestureDetector;
+
+    /**
+     * Construct a CandidateView for showing suggested words for completion.
+     * @param context
+     * @param attrs
+     */
+    public CandidateView(Context context) {
+        super(context);
+        mSelectionHighlight = context.getResources().getDrawable(
+                android.R.drawable.list_selector_background);
+        mSelectionHighlight.setState(new int[] {
+                android.R.attr.state_enabled,
+                android.R.attr.state_focused,
+                android.R.attr.state_window_focused,
+                android.R.attr.state_pressed
+        });
+
+        Resources r = context.getResources();
+        
+        setBackgroundColor(r.getColor(R.color.candidate_background));
+        
+        mColorNormal = r.getColor(R.color.candidate_normal);
+        mColorRecommended = r.getColor(R.color.candidate_recommended);
+        mColorOther = r.getColor(R.color.candidate_other);
+        
+        mPaint = new Paint();
+        mPaint.setColor(mColorNormal);
+        mPaint.setAntiAlias(true);
+        mPaint.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_font_height));
+        mPaint.setStrokeWidth(0);
+        
+        mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
+            @Override
+            public boolean onScroll(MotionEvent e1, MotionEvent e2,
+                    float distanceX, float distanceY) {
+                mScrolled = true;
+                int sx = getScrollX();
+                sx += distanceX;
+                if (sx < 0) {
+                    sx = 0;
+                }
+                if (sx + getWidth() > mTotalWidth) {                    
+                    sx -= distanceX;
+                }
+                mTargetScrollX = sx;
+                scrollTo(sx, getScrollY());
+                invalidate();
+                return true;
+            }
+        });
+        setHorizontalFadingEdgeEnabled(true);
+        setWillNotDraw(false);
+        setHorizontalScrollBarEnabled(false);
+        setVerticalScrollBarEnabled(false);
+    }
+    
+    /**
+     * A connection back to the service to communicate with the text field
+     * @param listener
+     */
+    public void setService(SoftKeyboard listener) {
+        mService = listener;
+    }
+    
+    @Override
+    public int computeHorizontalScrollRange() {
+        return mTotalWidth;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int measuredWidth = resolveSize(50, widthMeasureSpec);
+        
+        // Get the desired height of the icon menu view (last row of items does
+        // not have a divider below)
+        Rect padding = new Rect();
+        mSelectionHighlight.getPadding(padding);
+        final int desiredHeight = ((int)mPaint.getTextSize()) + 1
+                + padding.top + padding.bottom;
+        
+        // Maximum possible width and desired height
+        setMeasuredDimension(measuredWidth,
+                resolveSize(desiredHeight, heightMeasureSpec));
+    }
+
+    /**
+     * If the canvas is null, then only touch calculations are performed to pick the target
+     * candidate.
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (canvas != null) {
+            super.onDraw(canvas);
+        }
+        mTotalWidth = 0;
+        if (mSuggestions == null) return;
+        
+        if (mBgPadding == null) {
+            mBgPadding = new Rect(0, 0, 0, 0);
+            if (getBackground() != null) {
+                getBackground().getPadding(mBgPadding);
+            }
+        }
+        int x = 0;
+        final int count = mSuggestions.size(); 
+        final int height = getHeight();
+        final Rect bgPadding = mBgPadding;
+        final Paint paint = mPaint;
+        final int touchX = mTouchX;
+        final int scrollX = getScrollX();
+        final boolean scrolled = mScrolled;
+        final boolean typedWordValid = mTypedWordValid;
+        final int y = (int) (height + mPaint.getTextSize()) / 2;
+
+        for (int i = 0; i < count; i++) {
+            String suggestion = mSuggestions.get(i);
+            float textWidth = paint.measureText(suggestion);
+            final int wordWidth = (int) textWidth + X_GAP * 2;
+
+            mWordX[i] = x;
+            mWordWidth[i] = wordWidth;
+            paint.setColor(mColorNormal);
+            if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled) {
+                if (canvas != null) {
+                    canvas.translate(x, 0);
+                    mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
+                    mSelectionHighlight.draw(canvas);
+                    canvas.translate(-x, 0);
+                }
+                mSelectedIndex = i;
+            }
+
+            if (canvas != null) {
+                if ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid)) {
+                    paint.setFakeBoldText(true);
+                    paint.setColor(mColorRecommended);
+                } else if (i != 0) {
+                    paint.setColor(mColorOther);
+                }
+                canvas.drawText(suggestion, x + X_GAP, y, paint);
+                paint.setColor(mColorOther); 
+                canvas.drawLine(x + wordWidth + 0.5f, bgPadding.top, 
+                        x + wordWidth + 0.5f, height + 1, paint);
+                paint.setFakeBoldText(false);
+            }
+            x += wordWidth;
+        }
+        mTotalWidth = x;
+        if (mTargetScrollX != getScrollX()) {
+            scrollToTarget();
+        }
+    }
+    
+    private void scrollToTarget() {
+        int sx = getScrollX();
+        if (mTargetScrollX > sx) {
+            sx += SCROLL_PIXELS;
+            if (sx >= mTargetScrollX) {
+                sx = mTargetScrollX;
+                requestLayout();
+            }
+        } else {
+            sx -= SCROLL_PIXELS;
+            if (sx <= mTargetScrollX) {
+                sx = mTargetScrollX;
+                requestLayout();
+            }
+        }
+        scrollTo(sx, getScrollY());
+        invalidate();
+    }
+    
+    public void setSuggestions(List<String> suggestions, boolean completions,
+            boolean typedWordValid) {
+        clear();
+        if (suggestions != null) {
+            mSuggestions = new ArrayList<String>(suggestions);
+        }
+        mTypedWordValid = typedWordValid;
+        scrollTo(0, 0);
+        mTargetScrollX = 0;
+        // Compute the total width
+        onDraw(null);
+        invalidate();
+        requestLayout();
+    }
+
+    public void clear() {
+        mSuggestions = EMPTY_LIST;
+        mTouchX = OUT_OF_BOUNDS;
+        mSelectedIndex = -1;
+        invalidate();
+    }
+    
+    @Override
+    public boolean onTouchEvent(MotionEvent me) {
+
+        if (mGestureDetector.onTouchEvent(me)) {
+            return true;
+        }
+
+        int action = me.getAction();
+        int x = (int) me.getX();
+        int y = (int) me.getY();
+        mTouchX = x;
+
+        switch (action) {
+        case MotionEvent.ACTION_DOWN:
+            mScrolled = false;
+            invalidate();
+            break;
+        case MotionEvent.ACTION_MOVE:
+            if (y <= 0) {
+                // Fling up!?
+                if (mSelectedIndex >= 0) {
+                    mService.pickSuggestionManually(mSelectedIndex);
+                    mSelectedIndex = -1;
+                }
+            }
+            invalidate();
+            break;
+        case MotionEvent.ACTION_UP:
+            if (!mScrolled) {
+                if (mSelectedIndex >= 0) {
+                    mService.pickSuggestionManually(mSelectedIndex);
+                }
+            }
+            mSelectedIndex = -1;
+            removeHighlight();
+            requestLayout();
+            break;
+        }
+        return true;
+    }
+    
+    /**
+     * For flick through from keyboard, call this method with the x coordinate of the flick 
+     * gesture.
+     * @param x
+     */
+    public void takeSuggestionAt(float x) {
+        mTouchX = (int) x;
+        // To detect candidate
+        onDraw(null);
+        if (mSelectedIndex >= 0) {
+            mService.pickSuggestionManually(mSelectedIndex);
+        }
+        invalidate();
+    }
+
+    private void removeHighlight() {
+        mTouchX = OUT_OF_BOUNDS;
+        invalidate();
+    }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
new file mode 100644
index 0000000..944cefb
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.example.android.softkeyboard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.inputmethodservice.Keyboard;
+
+public class LatinKeyboard extends Keyboard {
+
+    public LatinKeyboard(Context context, int xmlLayoutResId) {
+        super(context, xmlLayoutResId);
+    }
+
+    public LatinKeyboard(Context context, int layoutTemplateResId, 
+            CharSequence characters, int columns, int horizontalPadding) {
+        super(context, layoutTemplateResId, characters, columns, horizontalPadding);
+    }
+
+    @Override
+    protected Key createKeyFromXml(Resources res, Row parent, int x, int y, 
+            XmlResourceParser parser) {
+        return new LatinKey(res, parent, x, y, parser);
+    }
+    
+    static class LatinKey extends Keyboard.Key {
+        
+        public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) {
+            super(res, parent, x, y, parser);
+        }
+        
+        /**
+         * Overriding this method so that we can reduce the target area for the key that
+         * closes the keyboard. 
+         */
+        @Override
+        public boolean isInside(int x, int y) {
+            return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
+        }
+    }
+
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
new file mode 100644
index 0000000..7464607
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.example.android.softkeyboard;
+
+import android.content.Context;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.inputmethodservice.Keyboard.Key;
+import android.util.AttributeSet;
+
+public class LatinKeyboardView extends KeyboardView {
+
+    static final int KEYCODE_OPTIONS = -100;
+
+    public LatinKeyboardView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected boolean onLongPress(Key key) {
+        if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
+            getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
+            return true;
+        } else {
+            return super.onLongPress(key);
+        }
+    }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
new file mode 100644
index 0000000..baa4594
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2008-2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.example.android.softkeyboard;
+
+import android.content.Context;
+import android.inputmethodservice.InputMethodService;
+import android.inputmethodservice.Keyboard;
+import android.inputmethodservice.KeyboardView;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Example of writing an input method for a soft keyboard.  This code is
+ * focused on simplicity over completeness, so it should in no way be considered
+ * to be a complete soft keyboard implementation.  Its purpose is to provide
+ * a basic example for how you would get started writing an input method, to
+ * be fleshed out as appropriate.
+ */
+public class SoftKeyboard extends InputMethodService 
+        implements KeyboardView.OnKeyboardActionListener {
+    static final boolean DEBUG = false;
+    
+    private KeyboardView mInputView;
+    private CandidateView mCandidateView;
+    private CompletionInfo[] mCompletions;
+    
+    private StringBuilder mComposing = new StringBuilder();
+    private boolean mPredicting;
+    private boolean mPredictionOn;
+    private boolean mCompletionOn;
+    private int mLastDisplayWidth;
+    private boolean mCapsLock;
+    private long mLastShiftTime;
+    
+    private Keyboard mSymbolsKeyboard;
+    private Keyboard mSymbolsShiftedKeyboard;
+    private Keyboard mQwertyKeyboard;
+    
+    private String mWordSeparators;
+    
+    private InputConnection mOldConnection;
+
+    private void makeKeyboards() {
+        // Configuration change is coming after the keyboard gets recreated. So don't rely on that.
+        // If keyboards have already been made, check if we have a screen width change and 
+        // create the keyboard layouts again at the correct orientation
+        if (mQwertyKeyboard != null) {
+            WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+            int displayWidth = wm.getDefaultDisplay().getWidth();
+            if (displayWidth == mLastDisplayWidth) return;
+            mLastDisplayWidth = displayWidth;
+        }
+        mQwertyKeyboard = new LatinKeyboard(this, R.xml.qwerty);
+        mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
+        mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
+    }
+    
+    @Override public void onCreate() {
+        super.onCreate();
+        //setStatusIcon(R.drawable.ime_qwerty);
+        makeKeyboards();
+        mWordSeparators = getResources().getString(R.string.word_separators);
+    }
+    
+    @Override
+    public View onCreateInputView() {
+        makeKeyboards();
+        mInputView = (KeyboardView) getLayoutInflater().inflate(
+                R.layout.input, null);
+        mInputView.setOnKeyboardActionListener(this);
+        mInputView.setKeyboard(mQwertyKeyboard);
+        return mInputView;
+    }
+
+    @Override
+    public View onCreateCandidatesView() {
+        makeKeyboards();
+        mCandidateView = new CandidateView(this);
+        mCandidateView.setService(this);
+        return mCandidateView;
+    }
+
+    @Override 
+    public void onStartInputView(EditorInfo attribute, boolean restarting) {
+        // In landscape mode, this method gets called without the input view being created.
+        if (mInputView == null) {
+            return;
+        }
+
+        if (mQwertyKeyboard == null) {
+            makeKeyboards();
+        }
+
+        if (mOldConnection != null) {
+            commitTyped(mOldConnection);
+        }
+        
+        mPredictionOn = false;
+        mCompletionOn = false;
+        mCompletions = null;
+        switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
+            case EditorInfo.TYPE_CLASS_NUMBER:
+            case EditorInfo.TYPE_CLASS_DATETIME:
+                mInputView.setKeyboard(mSymbolsKeyboard);
+                break;
+            case EditorInfo.TYPE_CLASS_PHONE:
+                mInputView.setKeyboard(mSymbolsKeyboard);
+                break;
+            default:
+                mInputView.setKeyboard(mQwertyKeyboard);
+                //startPrediction();
+                mPredictionOn = true;
+                // Make sure that passwords are not displayed in candidate view
+                int variation = attribute.inputType &  EditorInfo.TYPE_MASK_VARIATION;
+                if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) {
+                    mPredictionOn = false;
+                }
+                if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS 
+                        || variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
+                    mPredictionOn = false;
+                }
+                if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
+                    mPredictionOn = false;
+                    mCompletionOn = isFullscreenMode();
+                }
+                updateShiftKeyState(attribute);
+                break;
+        }
+        mInputView.closing();
+        mComposing.setLength(0);
+        mCandidateView.setSuggestions(null, false, false);
+        mOldConnection = getCurrentInputConnection();
+        setCandidatesViewShown(mPredictionOn || mCompletionOn);
+    }
+
+    @Override
+    public void onFinishInput() {
+        super.onFinishInput();
+        commitTyped(mOldConnection);
+        if (mInputView != null) {
+            mInputView.closing();
+        }
+    }
+    
+    @Override
+    public void onDisplayCompletions(CompletionInfo[] completions) {
+        if (false) {
+            Log.i("foo", "Received completions:");
+            for (int i=0; i<(completions != null ? completions.length : 0); i++) {
+                Log.i("foo", "  #" + i + ": " + completions[i]);
+            }
+        }
+        if (mCompletionOn) {
+            mCompletions = completions;
+            if (completions == null) {
+                mCandidateView.setSuggestions(null, false, false);
+                return;
+            }
+            
+            List<String> stringList = new ArrayList<String>();
+            for (int i=0; i<(completions != null ? completions.length : 0); i++) {
+                CompletionInfo ci = completions[i];
+                if (ci != null) stringList.add(ci.getText().toString());
+            }
+            mCandidateView.setSuggestions(stringList, true, true);
+        }
+    }
+    
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK:
+                if (event.getRepeatCount() == 0 && mInputView != null) {
+                    if (mInputView.handleBack()) {
+                        return true;
+                    }
+                }
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                abortComposition();
+                break;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                // Enable shift key and DPAD to do selections
+                if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) {
+                    event = new KeyEvent(event.getDownTime(), event.getEventTime(), 
+                            event.getAction(), event.getKeyCode(), event.getRepeatCount(), 
+                            KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
+                    getCurrentInputConnection().sendKeyEvent(event);
+                    return true;
+                }
+                break;
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+
+    private void commitTyped(InputConnection inputConnection) {
+        if (mComposing.length() > 0) {
+            inputConnection.commitText(mComposing, mComposing.length());
+            mComposing.setLength(0);
+            updateCandidates();
+        }
+    }
+
+    public void updateShiftKeyState(EditorInfo attr) {
+        if (attr != null 
+                && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
+            int caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
+            mInputView.setShifted(mCapsLock || caps != 0);
+        }
+    }
+    
+    private boolean isAlphabet(int code) {
+        if (Character.isLetter(code)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    
+    private void keyDownUp(int keyEventCode) {
+        getCurrentInputConnection().sendKeyEvent(
+                new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
+        getCurrentInputConnection().sendKeyEvent(
+                new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
+    }
+    
+    private void sendKey(int keyCode) {
+        switch (keyCode) {
+            case 10:
+                keyDownUp(KeyEvent.KEYCODE_ENTER);
+                break;
+            default:
+                if (keyCode >= '0' && keyCode <= '9') {
+                    keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
+                } else {
+                    getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
+                }
+                break;
+        }
+    }
+
+    // Implementation of KeyboardViewListener
+
+    public void onKey(int primaryCode, int[] keyCodes) {
+        if (isWordSeparator(primaryCode)) {
+            // Handle separator
+            if (mPredicting) {
+                commitTyped(getCurrentInputConnection());
+            }
+            sendKey(primaryCode);
+            updateShiftKeyState(getCurrentInputInfo());
+        } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
+            handleBackspace();
+        } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
+            handleShift();
+        } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
+            handleClose();
+            return;
+        } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
+            // Show a menu or somethin'
+        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
+            Keyboard current = mInputView.getKeyboard();
+            if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
+                current = mQwertyKeyboard;
+            } else {
+                current = mSymbolsKeyboard;
+            }
+            mInputView.setKeyboard(current);
+            if (current == mSymbolsKeyboard) {
+                current.setShifted(false);
+            }
+        } else {
+            handleCharacter(primaryCode, keyCodes);
+        }
+    }
+
+    /**
+     * Update the list of available candidates from the current composing
+     * text.  This will need to be filled in by however you are determining
+     * candidates.
+     */
+    private void updateCandidates() {
+        if (!mCompletionOn) {
+            if (mComposing.length() > 0) {
+                ArrayList<String> list = new ArrayList<String>();
+                list.add(mComposing.toString());
+                mCandidateView.setSuggestions(list, true, true);
+            } else {
+                mCandidateView.setSuggestions(null, false, false);
+            }
+        }
+    }
+    
+    private void handleBackspace() {
+        if (mPredicting) {
+            final int length = mComposing.length();
+            if (length > 0) {
+                mComposing.delete(length - 1, length);
+                getCurrentInputConnection().setComposingText(mComposing, mComposing.length());
+                updateCandidates();
+                if (mComposing.length() == 0) {
+                    mPredicting = false;
+                }
+            } else {
+                getCurrentInputConnection().deleteSurroundingText(1, 0);
+            }
+        } else {
+            //getCurrentInputConnection().deleteSurroundingText(1, 0);
+            keyDownUp(KeyEvent.KEYCODE_DEL);
+        }
+        updateShiftKeyState(getCurrentInputInfo());
+    }
+
+    private void handleShift() {
+        Keyboard currentKeyboard = mInputView.getKeyboard();
+        if (mQwertyKeyboard == currentKeyboard) {
+            // Alphabet keyboard
+            checkToggleCapsLock();
+            mInputView.setShifted(mCapsLock || !mInputView.isShifted());
+        } else if (currentKeyboard == mSymbolsKeyboard) {
+            mSymbolsKeyboard.setShifted(true);
+            mInputView.setKeyboard(mSymbolsShiftedKeyboard);
+            mSymbolsShiftedKeyboard.setShifted(true);
+        } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
+            mSymbolsShiftedKeyboard.setShifted(false);
+            mInputView.setKeyboard(mSymbolsKeyboard);
+            mSymbolsKeyboard.setShifted(false);
+        }
+    }
+    
+    private void handleCharacter(int primaryCode, int[] keyCodes) {
+        if (isAlphabet(primaryCode) && mPredictionOn && !isCursorTouchingWord()) {
+            if (!mPredicting) {
+                mPredicting = true;
+                mComposing.setLength(0);
+            }
+        }
+        if (mInputView.isShifted()) {
+            primaryCode = Character.toUpperCase(primaryCode);
+        }
+        mComposing.append((char) primaryCode);
+        getCurrentInputConnection().setComposingText(mComposing, mComposing.length());
+        updateShiftKeyState(getCurrentInputInfo());
+        updateCandidates();
+    }
+
+    private void handleClose() {
+        commitTyped(getCurrentInputConnection());
+        dismissSoftInput();
+        mInputView.closing();
+    }
+
+    private void checkToggleCapsLock() {
+        long now = System.currentTimeMillis();
+        if (mLastShiftTime + 800 > now) {
+            mCapsLock = !mCapsLock;
+            mLastShiftTime = 0;
+        } else {
+            mLastShiftTime = now;
+        }
+    }
+    
+    private boolean isCursorTouchingWord() {
+        CharSequence toLeft = getCurrentInputConnection().getTextBeforeCursor(1);
+        CharSequence toRight = getCurrentInputConnection().getTextAfterCursor(1);
+        if (!TextUtils.isEmpty(toLeft)
+                && !isWordSeparator(toLeft.charAt(0))) {
+            return true;
+        }
+        if (!TextUtils.isEmpty(toRight) 
+                && !isWordSeparator(toRight.charAt(0))) {
+            return true;
+        }
+        return false;
+    }
+    
+    protected String getWordSeparators() {
+        return mWordSeparators;
+    }
+    
+    public boolean isWordSeparator(int code) {
+        String separators = getWordSeparators();
+        return separators.contains(String.valueOf((char)code));
+    }
+
+    public void pickDefaultCandidate() {
+        pickSuggestionManually(0);
+    }
+    
+    public void pickSuggestionManually(int index) {
+        if (mCompletionOn && mCompletions != null && index >= 0
+                && index < mCompletions.length) {
+            CompletionInfo ci = mCompletions[index];
+            getCurrentInputConnection().commitCompletion(ci);
+            if (mCandidateView != null) {
+                mCandidateView.clear();
+            }
+            updateShiftKeyState(getCurrentInputInfo());
+        }
+    }
+    
+    public void swipeRight() {
+        if (mCompletionOn) {
+            pickDefaultCandidate();
+        }
+    }
+    
+    public void swipeLeft() {
+        handleBackspace();
+    }
+
+    public void swipeDown() {
+        handleClose();
+    }
+
+    public void swipeUp() {
+        // ?
+    }
+
+    private void abortComposition() {
+        commitTyped(getCurrentInputConnection());
+        mComposing.setLength(0); // Don't want to allow uncommit after this
+        updateCandidates();
+    }
+}