Merge "Adding a code sample for how to write a custom action provider." into ics-mr0
diff --git a/build/sdk.atree b/build/sdk.atree
index 8742b6a..ba7cb86 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -170,7 +170,8 @@
 development/samples/NotePad                    samples/${PLATFORM_NAME}/NotePad
 development/samples/NFCDemo                    samples/${PLATFORM_NAME}/NFCDemo
 development/samples/RandomMusicPlayer          samples/${PLATFORM_NAME}/RandomMusicPlayer
-development/samples/SampleSpellCheckerService  samples/${PLATFORM_NAME}/SampleSpellCheckerService
+development/samples/SpellChecker/SampleSpellCheckerService samples/${PLATFORM_NAME}/SpellChecker/SampleSpellCheckerService
+development/samples/SpellChecker/HelloSpellChecker samples/${PLATFORM_NAME}/SpellChecker/HelloSpellChecker
 development/samples/SampleSyncAdapter          samples/${PLATFORM_NAME}/SampleSyncAdapter
 development/samples/SearchableDictionary       samples/${PLATFORM_NAME}/SearchableDictionary
 development/samples/SipDemo                    samples/${PLATFORM_NAME}/SipDemo
diff --git a/samples/SoftKeyboard/AndroidManifest.xml b/samples/SoftKeyboard/AndroidManifest.xml
index 61b5131..3d30779 100755
--- a/samples/SoftKeyboard/AndroidManifest.xml
+++ b/samples/SoftKeyboard/AndroidManifest.xml
@@ -8,5 +8,12 @@
             </intent-filter>
             <meta-data android:name="android.view.im" android:resource="@xml/method" />
         </service>
+
+        <activity android:name=".ImePreferences" android:label="@string/settings_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+
     </application>
 </manifest>
diff --git a/samples/SoftKeyboard/res/drawable-hdpi/icon_en_gb.png b/samples/SoftKeyboard/res/drawable-hdpi/icon_en_gb.png
new file mode 100644
index 0000000..53088d9
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable-hdpi/icon_en_gb.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable-hdpi/icon_en_us.png b/samples/SoftKeyboard/res/drawable-hdpi/icon_en_us.png
new file mode 100644
index 0000000..bc8b66e
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable-hdpi/icon_en_us.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable-mdpi/icon_en_gb.png b/samples/SoftKeyboard/res/drawable-mdpi/icon_en_gb.png
new file mode 100644
index 0000000..03c665a
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable-mdpi/icon_en_gb.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/drawable-mdpi/icon_en_us.png b/samples/SoftKeyboard/res/drawable-mdpi/icon_en_us.png
new file mode 100644
index 0000000..da8d43f
--- /dev/null
+++ b/samples/SoftKeyboard/res/drawable-mdpi/icon_en_us.png
Binary files differ
diff --git a/samples/SoftKeyboard/res/values/strings.xml b/samples/SoftKeyboard/res/values/strings.xml
index bc645b2..952a629 100644
--- a/samples/SoftKeyboard/res/values/strings.xml
+++ b/samples/SoftKeyboard/res/values/strings.xml
@@ -28,4 +28,14 @@
     <string name="label_go_key">Go</string>
     <string name="label_next_key">Next</string>
     <string name="label_send_key">Send</string>
+
+    <!-- Labels for subtype -->
+    <string name="label_subtype_generic">%s</string>
+    <string name="label_subtype_en_GB">English (GB)</string>
+
+    <!-- Titles for ImePreference -->
+    <string name="settings_name">Sample Soft Keyboard Settings</string>
+    <string name="language_selection_title">Input languages</string>
+    <string name="select_language">Select input languages</string>
+    <string name="general_category">General</string>
 </resources>
diff --git a/samples/SoftKeyboard/res/xml/ime_preferences.xml b/samples/SoftKeyboard/res/xml/ime_preferences.xml
new file mode 100644
index 0000000..1e973a6
--- /dev/null
+++ b/samples/SoftKeyboard/res/xml/ime_preferences.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/settings_name">
+</PreferenceScreen>
diff --git a/samples/SoftKeyboard/res/xml/method.xml b/samples/SoftKeyboard/res/xml/method.xml
index d246624..2f2d6f0 100644
--- a/samples/SoftKeyboard/res/xml/method.xml
+++ b/samples/SoftKeyboard/res/xml/method.xml
@@ -20,4 +20,17 @@
 <!-- The attributes in this XML file provide configuration information -->
 <!-- for the Search Manager. -->
 
-<input-method xmlns:android="http://schemas.android.com/apk/res/android" />
+<input-method xmlns:android="http://schemas.android.com/apk/res/android"
+        android:settingsActivity="com.example.android.softkeyboard.ImePreferences"
+>
+    <subtype
+        android:label="@string/label_subtype_generic"
+        android:icon="@drawable/icon_en_us"
+        android:imeSubtypeLocale="en_US"
+        android:imeSubtypeMode="keyboard" />
+    <subtype
+        android:label="@string/label_subtype_en_GB"
+        android:icon="@drawable/icon_en_gb"
+        android:imeSubtypeLocale="en_GB"
+        android:imeSubtypeMode="keyboard" />
+</input-method>
diff --git a/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsFragment.java b/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsFragment.java
new file mode 100644
index 0000000..b3b7c8c
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsFragment.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a part of the inputmethod-common static Java library.
+ * The original source code can be found at frameworks/opt/inputmethodcommon of Android Open Source
+ * Project.
+ */
+
+package com.android.inputmethodcommon;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+/**
+ * This is a helper class for an IME's settings preference fragment. It's recommended for every
+ * IME to have its own settings preference fragment which inherits this class.
+ */
+public abstract class InputMethodSettingsFragment extends PreferenceFragment
+        implements InputMethodSettingsInterface {
+    private final InputMethodSettingsImpl mSettings = new InputMethodSettingsImpl();
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Context context = getActivity();
+        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context));
+        mSettings.init(context, getPreferenceScreen());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setInputMethodSettingsCategoryTitle(int resId) {
+        mSettings.setInputMethodSettingsCategoryTitle(resId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setInputMethodSettingsCategoryTitle(CharSequence title) {
+        mSettings.setInputMethodSettingsCategoryTitle(title);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerTitle(int resId) {
+        mSettings.setSubtypeEnablerTitle(resId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerTitle(CharSequence title) {
+        mSettings.setSubtypeEnablerTitle(title);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerIcon(int resId) {
+        mSettings.setSubtypeEnablerIcon(resId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerIcon(Drawable drawable) {
+        mSettings.setSubtypeEnablerIcon(drawable);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onResume() {
+        super.onResume();
+        mSettings.updateSubtypeEnabler();
+    }
+}
diff --git a/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsImpl.java b/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsImpl.java
new file mode 100644
index 0000000..722148d
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsImpl.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a part of the inputmethod-common static Java library.
+ * The original source code can be found at frameworks/opt/inputmethodcommon of Android Open Source
+ * Project.
+ */
+
+package com.android.inputmethodcommon;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.List;
+
+/* package private */ class InputMethodSettingsImpl implements InputMethodSettingsInterface {
+    private Preference mSubtypeEnablerPreference;
+    private int mInputMethodSettingsCategoryTitleRes;
+    private CharSequence mInputMethodSettingsCategoryTitle;
+    private int mSubtypeEnablerTitleRes;
+    private CharSequence mSubtypeEnablerTitle;
+    private int mSubtypeEnablerIconRes;
+    private Drawable mSubtypeEnablerIcon;
+    private InputMethodManager mImm;
+    private InputMethodInfo mImi;
+    private Context mContext;
+
+    /**
+     * Initialize internal states of this object.
+     * @param context the context for this application.
+     * @param prefScreen a PreferenceScreen of PreferenceActivity or PreferenceFragment.
+     * @return true if this application is an IME and has two or more subtypes, false otherwise.
+     */
+    public boolean init(final Context context, final PreferenceScreen prefScreen) {
+        mContext = context;
+        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        mImi = getMyImi(context, mImm);
+        if (mImi == null || mImi.getSubtypeCount() <= 1) {
+            return false;
+        }
+        mSubtypeEnablerPreference = new Preference(context);
+        mSubtypeEnablerPreference
+                .setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                    @Override
+                    public boolean onPreferenceClick(Preference preference) {
+                        final CharSequence title = getSubtypeEnablerTitle(context);
+                        final Intent intent =
+                                new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
+                        intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, mImi.getId());
+                        if (!TextUtils.isEmpty(title)) {
+                            intent.putExtra(Intent.EXTRA_TITLE, title);
+                        }
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                        context.startActivity(intent);
+                        return true;
+                    }
+                });
+        prefScreen.addPreference(mSubtypeEnablerPreference);
+        updateSubtypeEnabler();
+        return true;
+    }
+
+    private static InputMethodInfo getMyImi(Context context, InputMethodManager imm) {
+        final List<InputMethodInfo> imis = imm.getInputMethodList();
+        for (int i = 0; i < imis.size(); ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            if (imis.get(i).getPackageName().equals(context.getPackageName())) {
+                return imi;
+            }
+        }
+        return null;
+    }
+
+    private static String getEnabledSubtypesLabel(
+            Context context, InputMethodManager imm, InputMethodInfo imi) {
+        if (context == null || imm == null || imi == null) return null;
+        final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi, true);
+        final StringBuilder sb = new StringBuilder();
+        final int N = subtypes.size();
+        for (int i = 0; i < N; ++i) {
+            final InputMethodSubtype subtype = subtypes.get(i);
+            if (sb.length() > 0) {
+                sb.append(", ");
+            }
+            sb.append(subtype.getDisplayName(context, imi.getPackageName(),
+                    imi.getServiceInfo().applicationInfo));
+        }
+        return sb.toString();
+    }
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setInputMethodSettingsCategoryTitle(int resId) {
+        mInputMethodSettingsCategoryTitleRes = resId;
+        updateSubtypeEnabler();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setInputMethodSettingsCategoryTitle(CharSequence title) {
+        mInputMethodSettingsCategoryTitleRes = 0;
+        mInputMethodSettingsCategoryTitle = title;
+        updateSubtypeEnabler();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerTitle(int resId) {
+        mSubtypeEnablerTitleRes = resId;
+        updateSubtypeEnabler();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerTitle(CharSequence title) {
+        mSubtypeEnablerTitleRes = 0;
+        mSubtypeEnablerTitle = title;
+        updateSubtypeEnabler();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerIcon(int resId) {
+        mSubtypeEnablerIconRes = resId;
+        updateSubtypeEnabler();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSubtypeEnablerIcon(Drawable drawable) {
+        mSubtypeEnablerIconRes = 0;
+        mSubtypeEnablerIcon = drawable;
+        updateSubtypeEnabler();
+    }
+
+    private CharSequence getSubtypeEnablerTitle(Context context) {
+        if (mSubtypeEnablerTitleRes != 0) {
+            return context.getString(mSubtypeEnablerTitleRes);
+        } else {
+            return mSubtypeEnablerTitle;
+        }
+    }
+
+    public void updateSubtypeEnabler() {
+        if (mSubtypeEnablerPreference != null) {
+            if (mSubtypeEnablerTitleRes != 0) {
+                mSubtypeEnablerPreference.setTitle(mSubtypeEnablerTitleRes);
+            } else if (!TextUtils.isEmpty(mSubtypeEnablerTitle)) {
+                mSubtypeEnablerPreference.setTitle(mSubtypeEnablerTitle);
+            }
+            final String summary = getEnabledSubtypesLabel(mContext, mImm, mImi);
+            if (!TextUtils.isEmpty(summary)) {
+                mSubtypeEnablerPreference.setSummary(summary);
+            }
+            if (mSubtypeEnablerIconRes != 0) {
+                mSubtypeEnablerPreference.setIcon(mSubtypeEnablerIconRes);
+            } else if (mSubtypeEnablerIcon != null) {
+                mSubtypeEnablerPreference.setIcon(mSubtypeEnablerIcon);
+            }
+        }
+    }
+}
diff --git a/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsInterface.java b/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsInterface.java
new file mode 100644
index 0000000..f41e224
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/android/inputmethodcommon/InputMethodSettingsInterface.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/**
+ * This is a part of the inputmethod-common static Java library.
+ * The original source code can be found at frameworks/opt/inputmethodcommon of Android Open Source
+ * Project.
+ */
+
+package com.android.inputmethodcommon;
+
+import android.graphics.drawable.Drawable;
+
+/**
+ * InputMethodSettingsInterface is the interface for adding IME related preferences to
+ * PreferenceActivity or PreferenceFragment.
+ */
+public interface InputMethodSettingsInterface {
+    /**
+     * Sets the title for the input method settings category with a resource ID.
+     * @param resId The resource ID of the title.
+     */
+    public void setInputMethodSettingsCategoryTitle(int resId);
+
+    /**
+     * Sets the title for the input method settings category with a CharSequence.
+     * @param title The title for this preference.
+     */
+    public void setInputMethodSettingsCategoryTitle(CharSequence title);
+
+    /**
+     * Sets the title for the input method enabler preference for launching subtype enabler with a
+     * resource ID.
+     * @param resId The resource ID of the title.
+     */
+    public void setSubtypeEnablerTitle(int resId);
+
+    /**
+     * Sets the title for the input method enabler preference for launching subtype enabler with a
+     * CharSequence.
+     * @param title The title for this preference.
+     */
+    public void setSubtypeEnablerTitle(CharSequence title);
+
+    /**
+     * Sets the icon for the preference for launching subtype enabler with a resource ID.
+     * @param resId The resource id of an optional icon for the preference.
+     */
+    public void setSubtypeEnablerIcon(int resId);
+
+    /**
+     * Sets the icon for the Preference for launching subtype enabler with a Drawable.
+     * @param drawable The drawable of an optional icon for the preference.
+     */
+    public void setSubtypeEnablerIcon(Drawable drawable);
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
index 7cadead..33ee467 100755
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/CandidateView.java
@@ -1,17 +1,17 @@
 /*
- * 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
- * 
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/ImePreferences.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/ImePreferences.java
new file mode 100644
index 0000000..db6c1d9
--- /dev/null
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/ImePreferences.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.softkeyboard;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import com.android.inputmethodcommon.InputMethodSettingsFragment;
+
+/**
+ * Displays the IME preferences inside the input method setting.
+ */
+public class ImePreferences extends PreferenceActivity {
+    @Override
+    public Intent getIntent() {
+        final Intent modIntent = new Intent(super.getIntent());
+        modIntent.putExtra(EXTRA_SHOW_FRAGMENT, Settings.class.getName());
+        modIntent.putExtra(EXTRA_NO_HEADERS, true);
+        return modIntent;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // We overwrite the title of the activity, as the default one is "Voice Search".
+        setTitle(R.string.settings_name);
+    }
+
+    public static class Settings extends InputMethodSettingsFragment {
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
+            setSubtypeEnablerTitle(R.string.select_language);
+
+            // Load the preferences from an XML resource
+            addPreferencesFromResource(R.xml.ime_preferences);
+        }
+    }
+}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
index 1798442..67787dc 100644
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboard.java
@@ -1,17 +1,17 @@
 /*
- * 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
- * 
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
@@ -19,14 +19,14 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
 import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.Keyboard.Key;
-import android.inputmethodservice.Keyboard.Row;
 import android.view.inputmethod.EditorInfo;
 
 public class LatinKeyboard extends Keyboard {
 
     private Key mEnterKey;
+    private Key mSpaceKey;
     
     public LatinKeyboard(Context context, int xmlLayoutResId) {
         super(context, xmlLayoutResId);
@@ -43,6 +43,8 @@
         Key key = new LatinKey(res, parent, x, y, parser);
         if (key.codes[0] == 10) {
             mEnterKey = key;
+        } else if (key.codes[0] == ' ') {
+            mSpaceKey = key;
         }
         return key;
     }
@@ -68,8 +70,7 @@
                 mEnterKey.label = res.getText(R.string.label_next_key);
                 break;
             case EditorInfo.IME_ACTION_SEARCH:
-                mEnterKey.icon = res.getDrawable(
-                        R.drawable.sym_keyboard_search);
+                mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_search);
                 mEnterKey.label = null;
                 break;
             case EditorInfo.IME_ACTION_SEND:
@@ -78,13 +79,18 @@
                 mEnterKey.label = res.getText(R.string.label_send_key);
                 break;
             default:
-                mEnterKey.icon = res.getDrawable(
-                        R.drawable.sym_keyboard_return);
+                mEnterKey.icon = res.getDrawable(R.drawable.sym_keyboard_return);
                 mEnterKey.label = null;
                 break;
         }
     }
-    
+
+    void setSpaceIcon(final Drawable icon) {
+        if (mSpaceKey != null) {
+            mSpaceKey.icon = icon;
+        }
+    }
+
     static class LatinKey extends Keyboard.Key {
         
         public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) {
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
index 7464607..489c283 100644
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
@@ -1,26 +1,27 @@
 /*
- * 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
- * 
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.inputmethodservice.KeyboardView;
 import android.util.AttributeSet;
+import android.view.inputmethod.InputMethodSubtype;
 
 public class LatinKeyboardView extends KeyboardView {
 
@@ -43,4 +44,10 @@
             return super.onLongPress(key);
         }
     }
+
+    void setSubtypeOnSpaceKey(final InputMethodSubtype subtype) {
+        final LatinKeyboard keyboard = (LatinKeyboard)getKeyboard();
+        keyboard.setSpaceIcon(getResources().getDrawable(subtype.getIconResId()));
+        invalidateAllKeys();
+    }
 }
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
index 50b3536..7c4a17e 100644
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
@@ -1,17 +1,17 @@
 /*
- * 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
- * 
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
@@ -19,8 +19,8 @@
 import android.inputmethodservice.InputMethodService;
 import android.inputmethodservice.Keyboard;
 import android.inputmethodservice.KeyboardView;
+import android.text.InputType;
 import android.text.method.MetaKeyKeyListener;
-import android.util.Log;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
@@ -28,6 +28,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -52,8 +53,10 @@
      * that are primarily intended to be used for on-screen text entry.
      */
     static final boolean PROCESS_HARD_KEYS = true;
-    
-    private KeyboardView mInputView;
+
+    private InputMethodManager mInputMethodManager;
+
+    private LatinKeyboardView mInputView;
     private CandidateView mCandidateView;
     private CompletionInfo[] mCompletions;
     
@@ -79,6 +82,7 @@
      */
     @Override public void onCreate() {
         super.onCreate();
+        mInputMethodManager = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
         mWordSeparators = getResources().getString(R.string.word_separators);
     }
     
@@ -107,7 +111,7 @@
      * a configuration change.
      */
     @Override public View onCreateInputView() {
-        mInputView = (KeyboardView) getLayoutInflater().inflate(
+        mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
                 R.layout.input, null);
         mInputView.setOnKeyboardActionListener(this);
         mInputView.setKeyboard(mQwertyKeyboard);
@@ -149,21 +153,21 @@
         
         // We are now going to initialize our state based on the type of
         // text being edited.
-        switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
-            case EditorInfo.TYPE_CLASS_NUMBER:
-            case EditorInfo.TYPE_CLASS_DATETIME:
+        switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
+            case InputType.TYPE_CLASS_NUMBER:
+            case InputType.TYPE_CLASS_DATETIME:
                 // Numbers and dates default to the symbols keyboard, with
                 // no extra features.
                 mCurKeyboard = mSymbolsKeyboard;
                 break;
                 
-            case EditorInfo.TYPE_CLASS_PHONE:
+            case InputType.TYPE_CLASS_PHONE:
                 // Phones will also default to the symbols keyboard, though
                 // often you will want to have a dedicated phone keyboard.
                 mCurKeyboard = mSymbolsKeyboard;
                 break;
                 
-            case EditorInfo.TYPE_CLASS_TEXT:
+            case InputType.TYPE_CLASS_TEXT:
                 // This is general text editing.  We will default to the
                 // normal alphabetic keyboard, and assume that we should
                 // be doing predictive text (showing candidates as the
@@ -173,23 +177,23 @@
                 
                 // We now look for a few special variations of text that will
                 // modify our behavior.
-                int variation = attribute.inputType &  EditorInfo.TYPE_MASK_VARIATION;
-                if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
-                        variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
+                int variation = attribute.inputType & InputType.TYPE_MASK_VARIATION;
+                if (variation == InputType.TYPE_TEXT_VARIATION_PASSWORD ||
+                        variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
                     // Do not display predictions / what the user is typing
                     // when they are entering a password.
                     mPredictionOn = false;
                 }
                 
-                if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS 
-                        || variation == EditorInfo.TYPE_TEXT_VARIATION_URI
-                        || variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
+                if (variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+                        || variation == InputType.TYPE_TEXT_VARIATION_URI
+                        || variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
                     // Our predictions are not useful for e-mail addresses
                     // or URIs.
                     mPredictionOn = false;
                 }
                 
-                if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
+                if ((attribute.inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
                     // If this is an auto-complete text view, then our predictions
                     // will not be shown and instead we will allow the editor
                     // to supply their own.  We only show the editor's
@@ -245,8 +249,15 @@
         // Apply the selected keyboard to the input view.
         mInputView.setKeyboard(mCurKeyboard);
         mInputView.closing();
+        final InputMethodSubtype subtype = mInputMethodManager.getCurrentInputMethodSubtype();
+        mInputView.setSubtypeOnSpaceKey(subtype);
     }
-    
+
+    @Override
+    public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
+        mInputView.setSubtypeOnSpaceKey(subtype);
+    }
+
     /**
      * Deal with the editor reporting movement of its cursor.
      */
@@ -284,7 +295,7 @@
             }
             
             List<String> stringList = new ArrayList<String>();
-            for (int i=0; i<(completions != null ? completions.length : 0); i++) {
+            for (int i = 0; i < completions.length; i++) {
                 CompletionInfo ci = completions[i];
                 if (ci != null) stringList.add(ci.getText().toString());
             }
@@ -435,7 +446,7 @@
                 && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
             int caps = 0;
             EditorInfo ei = getCurrentInputEditorInfo();
-            if (ei != null && ei.inputType != EditorInfo.TYPE_NULL) {
+            if (ei != null && ei.inputType != InputType.TYPE_NULL) {
                 caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
             }
             mInputView.setShifted(mCapsLock || caps != 0);
diff --git a/samples/SpellChecker/Android.mk b/samples/SpellChecker/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/samples/SpellChecker/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/samples/SpellChecker/HelloSpellChecker/Android.mk b/samples/SpellChecker/HelloSpellChecker/Android.mk
new file mode 100755
index 0000000..1c76f23
--- /dev/null
+++ b/samples/SpellChecker/HelloSpellChecker/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := HelloSpellChecker
+
+include $(BUILD_PACKAGE)
diff --git a/samples/SpellChecker/HelloSpellChecker/AndroidManifest.xml b/samples/SpellChecker/HelloSpellChecker/AndroidManifest.xml
new file mode 100644
index 0000000..0a6b906
--- /dev/null
+++ b/samples/SpellChecker/HelloSpellChecker/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.hellospellchecker"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="14" />
+
+    <application
+        android:label="@string/app_name" >
+        <activity
+            android:label="@string/app_name"
+            android:name=".HelloSpellCheckerActivity" >
+            <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/SpellChecker/HelloSpellChecker/_index.html b/samples/SpellChecker/HelloSpellChecker/_index.html
new file mode 100755
index 0000000..414c629
--- /dev/null
+++ b/samples/SpellChecker/HelloSpellChecker/_index.html
@@ -0,0 +1,5 @@
+<p>A simple activity that requests spelling suggestions from a spell checker service, using the <code><a
+href="../../../reference/android/view/textservice/TextServicesManager.html">TextServicesManager</a></code>
+and <code><a href="../../../reference/android/view/textservice/SpellCheckerSession.html">SpellCheckerSession</a></code>
+APIs introduced in Android 4.0 (API level 14).</p>
+<p>For an example that implements a custom spell checker service, see the <a href="../SampleSpellCheckerService/index.html">Spell Checker</a> sample app.</p>
diff --git a/samples/SpellChecker/HelloSpellChecker/res/layout/main.xml b/samples/SpellChecker/HelloSpellChecker/res/layout/main.xml
new file mode 100644
index 0000000..3d443e4
--- /dev/null
+++ b/samples/SpellChecker/HelloSpellChecker/res/layout/main.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<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:id="@+id/main"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/samples/SpellChecker/HelloSpellChecker/res/values/strings.xml b/samples/SpellChecker/HelloSpellChecker/res/values/strings.xml
new file mode 100644
index 0000000..fbcb2db
--- /dev/null
+++ b/samples/SpellChecker/HelloSpellChecker/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+
+    <string name="app_name">HelloSpellChecker</string>
+
+</resources>
diff --git a/samples/SpellChecker/HelloSpellChecker/src/com/example/android/hellospellchecker/HelloSpellCheckerActivity.java b/samples/SpellChecker/HelloSpellChecker/src/com/example/android/hellospellchecker/HelloSpellCheckerActivity.java
new file mode 100644
index 0000000..6550981
--- /dev/null
+++ b/samples/SpellChecker/HelloSpellChecker/src/com/example/android/hellospellchecker/HelloSpellCheckerActivity.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.hellospellchecker;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.textservice.SpellCheckerSession;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+import android.view.textservice.TextServicesManager;
+import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+import android.widget.TextView;
+import java.lang.StringBuilder;
+
+public class HelloSpellCheckerActivity extends Activity implements SpellCheckerSessionListener {
+    private static final String TAG = HelloSpellCheckerActivity.class.getSimpleName();
+    private TextView mMainView;
+    private SpellCheckerSession mScs;
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+        mMainView = (TextView)findViewById(R.id.main);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        final TextServicesManager tsm = (TextServicesManager) getSystemService(
+                Context.TEXT_SERVICES_MANAGER_SERVICE);
+        mScs = tsm.newSpellCheckerSession(null, null, this, true);
+        if (mScs != null) {
+            // Instantiate TextInfo for each query
+            // TextInfo can be passed a sequence number and a cookie number to identify the result
+            mScs.getSuggestions(new TextInfo("tgis"), 3);
+            mScs.getSuggestions(new TextInfo("hllo"), 3);
+            mScs.getSuggestions(new TextInfo("helloworld"), 3);
+        } else {
+            Log.e(TAG, "Couldn't obtain the spell checker service.");
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mScs != null) {
+            mScs.close();
+        }
+    }
+
+    @Override
+    public void onGetSuggestions(final SuggestionsInfo[] arg0) {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < arg0.length; ++i) {
+            // Returned suggestions are contained in SuggestionsInfo
+            final int len = arg0[i].getSuggestionsCount();
+            sb.append('\n');
+            for (int j = 0; j < len; ++j) {
+                sb.append("," + arg0[i].getSuggestionAt(j));
+            }
+            sb.append(" (" + len + ")");
+        }
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mMainView.append(sb.toString());
+            }
+        });
+    }
+}
diff --git a/samples/SampleSpellCheckerService/Android.mk b/samples/SpellChecker/SampleSpellCheckerService/Android.mk
similarity index 100%
rename from samples/SampleSpellCheckerService/Android.mk
rename to samples/SpellChecker/SampleSpellCheckerService/Android.mk
diff --git a/samples/SampleSpellCheckerService/AndroidManifest.xml b/samples/SpellChecker/SampleSpellCheckerService/AndroidManifest.xml
similarity index 100%
rename from samples/SampleSpellCheckerService/AndroidManifest.xml
rename to samples/SpellChecker/SampleSpellCheckerService/AndroidManifest.xml
diff --git a/samples/SampleSpellCheckerService/_index.html b/samples/SpellChecker/SampleSpellCheckerService/_index.html
similarity index 100%
rename from samples/SampleSpellCheckerService/_index.html
rename to samples/SpellChecker/SampleSpellCheckerService/_index.html
diff --git a/samples/SampleSpellCheckerService/res/values/strings.xml b/samples/SpellChecker/SampleSpellCheckerService/res/values/strings.xml
similarity index 100%
rename from samples/SampleSpellCheckerService/res/values/strings.xml
rename to samples/SpellChecker/SampleSpellCheckerService/res/values/strings.xml
diff --git a/samples/SampleSpellCheckerService/res/xml/spell_checker_settings.xml b/samples/SpellChecker/SampleSpellCheckerService/res/xml/spell_checker_settings.xml
similarity index 100%
rename from samples/SampleSpellCheckerService/res/xml/spell_checker_settings.xml
rename to samples/SpellChecker/SampleSpellCheckerService/res/xml/spell_checker_settings.xml
diff --git a/samples/SampleSpellCheckerService/res/xml/spellchecker.xml b/samples/SpellChecker/SampleSpellCheckerService/res/xml/spellchecker.xml
similarity index 100%
rename from samples/SampleSpellCheckerService/res/xml/spellchecker.xml
rename to samples/SpellChecker/SampleSpellCheckerService/res/xml/spellchecker.xml
diff --git a/samples/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SampleSpellCheckerService.java b/samples/SpellChecker/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SampleSpellCheckerService.java
similarity index 100%
rename from samples/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SampleSpellCheckerService.java
rename to samples/SpellChecker/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SampleSpellCheckerService.java
diff --git a/samples/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsActivity.java b/samples/SpellChecker/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsActivity.java
similarity index 100%
rename from samples/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsActivity.java
rename to samples/SpellChecker/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsActivity.java
diff --git a/samples/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsFragment.java b/samples/SpellChecker/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsFragment.java
similarity index 100%
rename from samples/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsFragment.java
rename to samples/SpellChecker/SampleSpellCheckerService/src/com/example/android/samplespellcheckerservice/SpellCheckerSettingsFragment.java
diff --git a/samples/SpellChecker/_index.html b/samples/SpellChecker/_index.html
new file mode 100644
index 0000000..d60c8ca
--- /dev/null
+++ b/samples/SpellChecker/_index.html
@@ -0,0 +1 @@
+<p>A set of samples that demonstrate how to create/use spell checker APIs.</p>
diff --git a/samples/Support4Demos/AndroidManifest.xml b/samples/Support4Demos/AndroidManifest.xml
index 6a05b73..6d71b03 100644
--- a/samples/Support4Demos/AndroidManifest.xml
+++ b/samples/Support4Demos/AndroidManifest.xml
@@ -226,5 +226,21 @@
         <service android:name=".content.LocalServiceBroadcaster$LocalService"
                 android:stopWithTask="true" />
 
+        <activity android:name=".accessibility.AccessibilityManagerSupportActivity"
+                android:label="@string/accessibility_manager_title">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".accessibility.AccessibilityDelegateSupportActivity"
+                android:label="@string/accessibility_delegate_title">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
     </application>
 </manifest>
diff --git a/samples/Support4Demos/res/layout/accessibility_delegate.xml b/samples/Support4Demos/res/layout/accessibility_delegate.xml
new file mode 100644
index 0000000..333f90d
--- /dev/null
+++ b/samples/Support4Demos/res/layout/accessibility_delegate.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/accessibility_delegate_instructions"/>
+
+    <view class="com.example.android.supportv4.accessibility.AccessibilityDelegateSupportActivity$AccessibilityDelegateSupportView"
+        android:layout_width="wrap_content"
+        android:layout_height="50dip"
+        android:layout_marginTop="50dip"
+        android:background="@android:drawable/btn_default"/>
+
+</LinearLayout>
diff --git a/samples/Support4Demos/res/layout/accessibility_manager.xml b/samples/Support4Demos/res/layout/accessibility_manager.xml
new file mode 100644
index 0000000..e8814c4
--- /dev/null
+++ b/samples/Support4Demos/res/layout/accessibility_manager.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/accessibility_manager_instructions"/>
+
+        <TextView
+            android:id="@+id/accessibility_state"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="50dip"/>
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/samples/Support4Demos/res/values/strings.xml b/samples/Support4Demos/res/values/strings.xml
index 4e8d9de..8f70fd3 100644
--- a/samples/Support4Demos/res/values/strings.xml
+++ b/samples/Support4Demos/res/values/strings.xml
@@ -102,4 +102,24 @@
     <string name="start_service">Start Service</string>
     <string name="stop_service">Stop Service</string>
 
+    <!-- Accessibility API -->
+
+    <string name="accessibility_manager_title">Accessibility/Accessibility Manager</string>
+    <string name="accessibility_manager_instructions">
+        1. Enable TalkBack from Settings->Accessibility.
+        \n2. Go back to this activity.
+        \n3. Disable TalkBack from Settings->Accessibility.</string>
+    <string name="accessibility_manager_no_enabled_services">No enabled accessibility services or API level lower than ICS.</string>
+    <string name="accessibility_manager_enabled_service">ENABLED ACCESSIBILITY SERVICES:
+        \n\nService: %1$s\nFeedback: %2$s\nDescription: %3$s\nSettings: %4$s\n</string>
+    <string name="accessibility_manager_accessibility_state">Accessibility enabled: %1$s</string>
+
+    <string name="accessibility_delegate_title">Accessibility/Accessibility Delegate</string>
+    <string name="accessibility_delegate_instructions">
+        1. Enable TalkBack from Settings->Accessibility.
+        \n2. Go back to this activity.
+        \n3. Touch the button below.</string>
+    <string name="accessibility_delegate_button">Button</string>
+    <string name="accessibility_delegate_custom_text_added">Custom text added via an accessibility delegate.</string>
+
 </resources>
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java
new file mode 100644
index 0000000..6fcf855
--- /dev/null
+++ b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.supportv4.accessibility;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.view.AccessibilityDelegateCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+
+import com.example.android.supportv4.R;
+
+/**
+ * This class demonstrates how to use the support library to register
+ * a View.AccessibilityDelegate that customizes the accessibility
+ * behavior of a View. Aiming to maximize simplicity this example
+ * tweaks the text reported to accessibility services but using
+ * these APIs a client can inject any accessibility functionality into
+ * a View.
+ */
+public class AccessibilityDelegateSupportActivity extends Activity {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.accessibility_delegate);
+    }
+
+    /**
+     * This class represents a View that is customized via an AccessibilityDelegate
+     * as opposed to inheritance. An accessibility delegate can be used for adding
+     * accessibility to custom Views, i.e. ones that extend classes from android.view,
+     * in a backwards compatible fashion. Note that overriding a method whose return
+     * type or arguments are not part of a target platform APIs makes your application
+     * not backwards compatible with that platform version.
+     */
+    public static class AccessibilityDelegateSupportView extends View {
+
+        public AccessibilityDelegateSupportView(Context context, AttributeSet attrs) {
+            super(context, attrs);
+            installAccessibilityDelegate();
+        }
+
+        private void installAccessibilityDelegate() {
+            // The accessibility delegate enables customizing accessibility behavior
+            // via composition as opposed as inheritance. The main benefit is that
+            // one can write a backwards compatible application by setting the delegate
+            // only if the API level is high enough i.e. the delegate is part of the APIs.
+            // The easiest way to achieve that is by using the support library which
+            // takes the burden of checking API version and knowing which API version
+            // introduced the delegate off the developer.
+            ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegateCompat() {
+                @Override
+                public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+                    super.onPopulateAccessibilityEvent(host, event);
+                    // Note that View.onPopulateAccessibilityEvent was introduced in
+                    // ICS and we would like to tweak a bit the text that is reported to
+                    // accessibility services via the AccessibilityEvent.
+                    event.getText().add(getContext().getString(
+                            R.string.accessibility_delegate_custom_text_added));
+                }
+
+                @Override
+                public void onInitializeAccessibilityNodeInfo(View host,
+                        AccessibilityNodeInfoCompat info) {
+                    super.onInitializeAccessibilityNodeInfo(host, info);
+                    // Note that View.onInitializeAccessibilityNodeInfo was introduced in
+                    // ICS and we would like to tweak a bit the text that is reported to
+                    // accessibility services via the AccessibilityNodeInfo.
+                    info.setText(getContext().getString(
+                            R.string.accessibility_delegate_custom_text_added));
+                }
+            });
+        }
+    }
+}
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java
new file mode 100644
index 0000000..1004270
--- /dev/null
+++ b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/AccessibilityManagerSupportActivity.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.supportv4.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Activity;
+import android.app.Service;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.support.v4.android.accessibilityservice.AccessibilityServiceInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityManagerCompat;
+import android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.android.supportv4.R;
+
+import java.util.List;
+
+/**
+ * <p>
+ * This class demonstrates how to use the support library to register
+ * an AccessibilityManager.AccessibilityStateChangeListener introduced
+ * in ICS to watch changes to the global accessibility state on the
+ * device in a backwards compatible manner.
+ * </p>
+ * <p>
+ * This class also demonstrates how to use the support library to query
+ * information about enabled accessibility services via APIs introduced
+ * in ICS in a backwards compatible manner.
+ * </p>
+ */
+public class AccessibilityManagerSupportActivity extends Activity {
+
+    /** Handle to the accessibility manager service. */
+    private AccessibilityManager mAccessibilityManager;
+
+    /** Handle to the View showing accessibility services summary */
+    private TextView mAccessibilityStateView;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.accessibility_manager);
+        mAccessibilityManager = (AccessibilityManager) getSystemService(
+                Service.ACCESSIBILITY_SERVICE);
+        mAccessibilityStateView = (TextView) findViewById(R.id.accessibility_state);
+        registerAccessibilityStateChangeListener();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateAccessibilityStateView();
+    }
+
+    /**
+     * Registers an AccessibilityStateChangeListener that show a Toast
+     * when the global accessibility state on the device changes.
+     */
+    private void registerAccessibilityStateChangeListener() {
+        // The AccessibilityStateChange listener APIs were added in ICS. Therefore to be
+        // backwards compatible we use the APIs in the support library. Note that if the
+        // platform API version is lower and the called API is not available no listener
+        // is added and you will not receive a call of onAccessibilityStateChanged.
+        AccessibilityManagerCompat.addAccessibilityStateChangeListener(mAccessibilityManager,
+                new AccessibilityStateChangeListenerCompat() {
+            @Override
+            public void onAccessibilityStateChanged(boolean enabled) {
+                Toast.makeText(AccessibilityManagerSupportActivity.this,
+                        getString(R.string.accessibility_manager_accessibility_state, enabled),
+                        Toast.LENGTH_SHORT).show();
+            }
+        });
+    }
+
+    /**
+     * Updates the content of a TextView with description of the enabled
+     * accessibility services.
+     */
+    private void updateAccessibilityStateView() {
+        // The API for getting the enabled accessibility services based on feedback
+        // type was added in ICS. Therefore to be backwards compatible we use the
+        // APIs in the support library. Note that if the platform API version is lower
+        // and the called API is not available an empty list of services is returned.
+        List<AccessibilityServiceInfo> enabledServices =
+            AccessibilityManagerCompat.getEnabledAccessibilityServiceList(mAccessibilityManager,
+                    AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+        if (!enabledServices.isEmpty()) {
+            StringBuilder builder = new StringBuilder();
+            final int enabledServiceCount = enabledServices.size();
+            for (int i = 0; i < enabledServiceCount; i++) {
+                AccessibilityServiceInfo service = enabledServices.get(i);
+                // Some new APIs were added in ICS for getting more information about
+                // an accessibility service. Again accessed them via the support library.
+                ResolveInfo resolveInfo = AccessibilityServiceInfoCompat.getResolveInfo(service);
+                String serviceDescription = getString(
+                        R.string.accessibility_manager_enabled_service,
+                        resolveInfo.loadLabel(getPackageManager()),
+                        AccessibilityServiceInfoCompat.feedbackTypeToString(service.feedbackType),
+                        AccessibilityServiceInfoCompat.getDescription(service),
+                        AccessibilityServiceInfoCompat.getSettingsActivityName(service));
+                builder.append(serviceDescription);
+            }
+            mAccessibilityStateView.setText(builder);
+        } else {
+            // Either no services or the platform API version is not high enough.
+            mAccessibilityStateView.setText(getString(
+                    R.string.accessibility_manager_no_enabled_services));
+        }
+    }
+}
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/accessibility/_index.html b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/_index.html
new file mode 100644
index 0000000..03f2fba
--- /dev/null
+++ b/samples/Support4Demos/src/com/example/android/supportv4/accessibility/_index.html
@@ -0,0 +1,20 @@
+
+<p>This section includes samples showing the use of the accessibility
+features of the static support library.</p>
+
+<h3>Accessibility Manager</h3>
+<dl>
+  <dt><a href="AccessibilityManagerSupportActivity.html">Accessibility Manager</a></dt>
+  <dd>This sample demonstrates how to use the support library to register an
+  AccessibilityManager.AccessibilityStateChangeListener to watch changes to
+  the global accessibility state and AccessibilityManager to query information
+  about enabled accessibility services.</dd>
+</dl>
+
+<h3>Accessibility Delegate</h3>
+<dl>
+  <dt><a href="AccessibilityDelegateSupportActivity.html">AccessibilityDelegate</a></dt>
+  <dd>This sample demonstrates how to use the support library to register a
+  View.AccessibilityDelegate that customizes the accessibility behavior of
+  this View.</dd>
+</dl>