Add preliminary setup wizard

Bug: 8159728
Change-Id: I30d9cd637fb1d2e64588550e0aa4387bc1f7e6e5
diff --git a/java/res/drawable-hdpi/ic_settings_language.png b/java/res/drawable-hdpi/ic_settings_language.png
new file mode 100644
index 0000000..f635b2e
--- /dev/null
+++ b/java/res/drawable-hdpi/ic_settings_language.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_settings_language.png b/java/res/drawable-mdpi/ic_settings_language.png
new file mode 100644
index 0000000..f8aca67
--- /dev/null
+++ b/java/res/drawable-mdpi/ic_settings_language.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_settings_language.png b/java/res/drawable-xhdpi/ic_settings_language.png
new file mode 100644
index 0000000..2c42db3
--- /dev/null
+++ b/java/res/drawable-xhdpi/ic_settings_language.png
Binary files differ
diff --git a/java/res/layout/setup_step.xml b/java/res/layout/setup_step.xml
new file mode 100644
index 0000000..26d7fe7
--- /dev/null
+++ b/java/res/layout/setup_step.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+    <TextView
+        android:id="@+id/setup_step_title"
+        style="@style/setupStepTitleStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:paddingLeft="24dp"
+        android:paddingRight="24dp" />
+    <TextView
+        android:id="@+id/setup_step_instruction"
+        style="@style/setupStepInstructionStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="16dp"
+        android:paddingLeft="24dp"
+        android:paddingRight="24dp" />
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="2dp" />
+    <TextView
+        android:id="@+id/setup_step_action_label"
+        style="@style/setupStepActionLabelStyle"
+        android:gravity="center_vertical"
+        android:drawablePadding="12dp"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:clickable="true"
+        android:focusable="true"
+        android:paddingLeft="12dp"
+        android:paddingStart="12dp"
+        android:paddingRight="24dp"
+        android:paddingEnd="24dp" />
+</LinearLayout>
diff --git a/java/res/layout/setup_wizard.xml b/java/res/layout/setup_wizard.xml
new file mode 100644
index 0000000..acbbe30
--- /dev/null
+++ b/java/res/layout/setup_wizard.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true">
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/setup_background"
+        android:paddingLeft="@dimen/setup_horizontal_padding"
+        android:paddingRight="@dimen/setup_horizontal_padding"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp">
+        <TextView
+            android:id="@+id/setup_title"
+            style="@style/setupTitleStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <LinearLayout
+            android:id="@+id/setup_step_bullets"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/setup_title"
+            android:paddingTop="16dp"
+            android:orientation="horizontal">
+            <TextView
+                style="@style/setupStepBulletStyle"
+                android:text="@string/setup_step1_bullet" />
+            <TextView
+                style="@style/setupStepBulletStyle"
+                android:text="@string/setup_step2_bullet" />
+            <TextView
+                style="@style/setupStepBulletStyle"
+                android:text="@string/setup_step3_bullet" />
+        </LinearLayout>
+        <com.android.inputmethod.latin.setup.SetupStepIndicatorView
+            android:id="@+id/setup_step_indicator"
+            android:layout_width="match_parent"
+            android:layout_height="24dp"
+            android:layout_below="@id/setup_step_bullets" />
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/setup_step_indicator">
+            <include
+                android:id="@+id/setup_step1"
+                layout="@layout/setup_step" />
+            <include
+                android:id="@+id/setup_step2"
+                layout="@layout/setup_step" />
+            <include
+                android:id="@+id/setup_step3"
+                layout="@layout/setup_step" />
+        </FrameLayout>
+    </RelativeLayout>
+</ScrollView>
diff --git a/java/res/values-sw600dp-land/setup-dimens.xml b/java/res/values-sw600dp-land/setup-dimens.xml
new file mode 100644
index 0000000..9aea214
--- /dev/null
+++ b/java/res/values-sw600dp-land/setup-dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <dimen name="setup_title_text_size">64sp</dimen>
+    <dimen name="setup_horizontal_padding">96dp</dimen>
+</resources>
diff --git a/java/res/values-sw768dp-land/setup-dimens.xml b/java/res/values-sw768dp-land/setup-dimens.xml
new file mode 100644
index 0000000..0d2af17
--- /dev/null
+++ b/java/res/values-sw768dp-land/setup-dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <dimen name="setup_title_text_size">64sp</dimen>
+    <dimen name="setup_horizontal_padding">192dp</dimen>
+</resources>
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index c0ea321..8a8049f 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -53,4 +53,9 @@
     <color name="spacebar_text_color_ics">#FFC0C0C0</color>
     <color name="spacebar_text_shadow_color_ics">#80000000</color>
     <color name="typed_word_color_ics">@color/highlight_color_ics</color>
+    <!-- Color resources for setup wizard and tutorial -->
+    <color name="setup_background">#FFEBEBEB</color>
+    <color name="setup_text_dark">#FF707070</color>
+    <color name="setup_text_action">@android:color/holo_blue_light</color>
+    <color name="setup_step_background">@android:color/background_light</color>
 </resources>
diff --git a/java/res/values/setup-dimens.xml b/java/res/values/setup-dimens.xml
new file mode 100644
index 0000000..007906d
--- /dev/null
+++ b/java/res/values/setup-dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <dimen name="setup_title_text_size">46sp</dimen>
+    <dimen name="setup_horizontal_padding">16dp</dimen>
+</resources>
diff --git a/java/res/values/setup-styles.xml b/java/res/values/setup-styles.xml
new file mode 100644
index 0000000..cfc689a
--- /dev/null
+++ b/java/res/values/setup-styles.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="setupTitleStyle">
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:textSize">@dimen/setup_title_text_size</item>
+    </style>
+    <style name="setupStepBulletStyle">
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:textSize">22sp</item>
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_weight">1.0</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:gravity">center_horizontal</item>
+    </style>
+    <style name="setupStepTitleStyle">
+        <item name="android:background">@color/setup_step_background</item>
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:textSize">22sp</item>
+    </style>
+    <style name="setupStepInstructionStyle">
+        <item name="android:background">@color/setup_step_background</item>
+        <item name="android:textColor">@color/setup_text_dark</item>
+        <item name="android:textSize">14sp</item>
+    </style>
+    <style name="setupStepActionLabelStyle">
+        <item name="android:background">@color/setup_step_background</item>
+        <item name="android:textColor">@color/setup_text_action</item>
+        <item name="android:textSize">18sp</item>
+    </style>
+</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index ee79b45..f7d34c8 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -408,4 +408,29 @@
 
     <!-- Title of the button to revert to the default value of the device in the settings dialog [CHAR LIMIT=15] -->
     <string name="button_default">Default</string>
+
+    <!-- Title of the setup wizard. [CHAR LIMT=40] -->
+    <string name="setup_title">"Installing <xliff:g id="application_name">%s</xliff:g>"</string>
+    <!-- Ordinal number of the 1st step in the setup wizard. [CHAR LIMIT=5] -->
+    <string name="setup_step1_bullet">1</string>
+    <!-- Title of the 1st step in the setup wizard. [CHAR LIMIT=64] -->
+    <string name="setup_step1_title">"Enable <xliff:g id="application_name">%s</xliff:g> in settings."</string>
+    <!-- Detailed instruction of the 1st step in the setup wizard. [CHAR LIMIT=80] -->
+    <string name="setup_step1_instruction">"For security, please check \"<xliff:g id="application_name">%s</xliff:g>\""</string>
+    <!-- Ordinal number of the 2nd step in the setup wizard. [CHAR LIMIT=5] -->
+    <string name="setup_step2_bullet">2</string>
+    <!-- Title of the 2nd step in the setup wizard. [CHAR LIMIT=64] -->
+    <string name="setup_step2_title">"Switch to <xliff:g id="application_name">%s</xliff:g>."</string>
+    <!-- Detailed instruction of the 2nd step in the setup wizard. [CHAR LIMIT=80] -->
+    <string name="setup_step2_instruction">"Now that you've enabled <xliff:g id="application_name">%s</xliff:g>, you can switch to it."</string>
+    <!-- Ordinal number of the 3rd step in the setup wizard. [CHAR LIMIT=5] -->
+    <string name="setup_step3_bullet">3</string>
+    <!-- Title of the 3rd step in the setup wizard. [CHAR LIMIT=64] -->
+    <string name="setup_step3_title">"Congratulations, you're all set!"</string>
+    <!-- Detailed instruction of the 3rd step in the setup wizard. [CHAR LIMIT=80] -->
+    <string name="setup_step3_instruction">Configure additional languages</string>
+    <!-- Title of the Language & input settings. This should be aligned with msgid="5292716747264442359" -->
+    <string name="language_settings">Language &amp; input</string>
+    <!-- Title of the Input method picker. This should be aligned with msgid="4653387336791222978" -->
+    <string name="select_input_method">Choose input method</string>
 </resources>
diff --git a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
new file mode 100644
index 0000000..d4f1ea8
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.graphics.drawable.Drawable;
+import android.widget.TextView;
+
+import java.lang.reflect.Method;
+
+public final class TextViewCompatUtils {
+    // Note that TextView.setCompoundDrawablesRelative(Drawable,Drawable,Drawable,Drawable) has
+    // been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+    private static final Method METHOD_setCompoundDrawablesRelative = CompatUtils.getMethod(
+            TextView.class, "setCompoundDrawablesRelative",
+            Drawable.class, Drawable.class, Drawable.class, Drawable.class);
+
+    private TextViewCompatUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    public static void setCompoundDrawablesRelative(final TextView textView, final Drawable start,
+            final Drawable top, final Drawable end, final Drawable bottom) {
+        if (METHOD_setCompoundDrawablesRelative == null) {
+            textView.setCompoundDrawables(start, top, end, bottom);
+            return;
+        }
+        CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelative,
+                start, top, end, bottom);
+    }
+}
diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
new file mode 100644
index 0000000..a8fab88
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.compat;
+
+import android.view.View;
+
+import java.lang.reflect.Method;
+
+public final class ViewCompatUtils {
+    // Note that View.LAYOUT_DIRECTION_LTR and View.LAYOUT_DIRECTION_RTL have been introduced in
+    // API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+    public static final int LAYOUT_DIRECTION_LTR = (Integer)CompatUtils.getFieldValue(null, 0x0,
+            CompatUtils.getField(View.class, "LAYOUT_DIRECTION_LTR"));
+    public static final int LAYOUT_DIRECTION_RTL = (Integer)CompatUtils.getFieldValue(null, 0x1,
+            CompatUtils.getField(View.class, "LAYOUT_DIRECTION_RTL"));
+
+    // Note that View.getPaddingEnd(), View.setPaddingRelative(int,int,int,int), and
+    // View.getLayoutDirection() have been introduced in API level 17
+    // (Build.VERSION_CODE.JELLY_BEAN_MR1).
+    private static final Method METHOD_getPaddingEnd = CompatUtils.getMethod(
+            View.class, "getPaddingEnd");
+    private static final Method METHOD_setPaddingRelative = CompatUtils.getMethod(
+            View.class, "setPaddingRelative",
+            Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE);
+    private static final Method METHOD_getLayoutDirection = CompatUtils.getMethod(
+            View.class, "getLayoutDirection");
+
+    private ViewCompatUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    public static int getPaddingEnd(final View view) {
+        if (METHOD_getPaddingEnd == null) {
+            return view.getPaddingRight();
+        }
+        return (Integer)CompatUtils.invoke(view, 0, METHOD_getPaddingEnd);
+    }
+
+    public static void setPaddingRelative(final View view, final int start, final int top,
+            final int end, final int bottom) {
+        if (METHOD_setPaddingRelative == null) {
+            view.setPadding(start, top, end, bottom);
+            return;
+        }
+        CompatUtils.invoke(view, null, METHOD_setPaddingRelative, start, top, end, bottom);
+    }
+
+    public static int getLayoutDirection(final View view) {
+        if (METHOD_getLayoutDirection == null) {
+            return LAYOUT_DIRECTION_LTR;
+        }
+        return (Integer)CompatUtils.invoke(view, 0, METHOD_getLayoutDirection);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index fab8945..c30ecfb 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -18,22 +18,323 @@
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.Message;
+import android.provider.Settings;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
 
+import com.android.inputmethod.compat.TextViewCompatUtils;
+import com.android.inputmethod.compat.ViewCompatUtils;
+import com.android.inputmethod.latin.CollectionUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.SettingsActivity;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+
+import java.util.HashMap;
 
 public final class SetupActivity extends Activity {
+    private SetupStepIndicatorView mStepIndicatorView;
+    private final SetupStepGroup mSetupSteps = new SetupStepGroup();
+    private static final String STATE_STEP = "step";
+    private int mStepNo;
+    private static final int STEP_1 = 1;
+    private static final int STEP_2 = 2;
+    private static final int STEP_3 = 3;
+
+    private final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this);
+
+    static final class SettingsPoolingHandler extends StaticInnerHandlerWrapper<SetupActivity> {
+        private static final int MSG_POLLING_IME_SETTINGS = 0;
+        private static final long IME_SETTINGS_POLLING_INTERVAL = 200;
+
+        public SettingsPoolingHandler(final SetupActivity outerInstance) {
+            super(outerInstance);
+        }
+
+        @Override
+        public void handleMessage(final Message msg) {
+            final SetupActivity setupActivity = getOuterInstance();
+            switch (msg.what) {
+            case MSG_POLLING_IME_SETTINGS:
+                if (setupActivity.isMyImeEnabled()) {
+                    setupActivity.invokeSetupWizardOfThisIme();
+                    return;
+                }
+                startPollingImeSettings();
+                break;
+            }
+        }
+
+        public void startPollingImeSettings() {
+            sendMessageDelayed(obtainMessage(MSG_POLLING_IME_SETTINGS),
+                    IME_SETTINGS_POLLING_INTERVAL);
+        }
+
+        public void cancelPollingImeSettings() {
+            removeMessages(MSG_POLLING_IME_SETTINGS);
+        }
+    }
+
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
+    protected void onCreate(final Bundle savedInstanceState) {
+        setTheme(android.R.style.Theme_DeviceDefault_Light_NoActionBar);
         super.onCreate(savedInstanceState);
 
-        // TODO: Implement setup wizard.
+        setContentView(R.layout.setup_wizard);
+
+        RichInputMethodManager.init(this);
+
+        if (savedInstanceState == null) {
+            mStepNo = determineSetupStepNo();
+        } else {
+            mStepNo = savedInstanceState.getInt(STATE_STEP);
+        }
+
+        if (mStepNo == STEP_3) {
+            // This IME already has been enabled and set as current IME.
+            // TODO: Implement tutorial.
+            invokeSettingsOfThisIme();
+            finish();
+            return;
+        }
+
+        // TODO: Use sans-serif-thin font family depending on the system locale white list and
+        // the SDK version.
+        final TextView titleView = (TextView)findViewById(R.id.setup_title);
+        titleView.setText(getString(R.string.setup_title, getString(R.string.english_ime_name)));
+
+        mStepIndicatorView = (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
+
+        final SetupStep step1 = new SetupStep(findViewById(R.id.setup_step1),
+                R.string.setup_step1_title, R.string.setup_step1_instruction,
+                R.drawable.ic_settings_language, R.string.language_settings);
+        step1.setAction(new Runnable() {
+            @Override
+            public void run() {
+                invokeLanguageAndInputSettings();
+                mHandler.startPollingImeSettings();
+            }
+        });
+        mSetupSteps.addStep(STEP_1, step1);
+
+        final SetupStep step2 = new SetupStep(findViewById(R.id.setup_step2),
+                R.string.setup_step2_title, R.string.setup_step2_instruction,
+                0 /* actionIcon */, R.string.select_input_method);
+        step2.setAction(new Runnable() {
+            @Override
+            public void run() {
+                // Invoke input method picker.
+                RichInputMethodManager.getInstance().getInputMethodManager()
+                        .showInputMethodPicker();
+            }
+        });
+        mSetupSteps.addStep(STEP_2, step2);
+
+        final SetupStep step3 = new SetupStep(findViewById(R.id.setup_step3),
+                R.string.setup_step3_title, 0 /* instruction */,
+                R.drawable.sym_keyboard_language_switch, R.string.setup_step3_instruction);
+        step3.setAction(new Runnable() {
+            @Override
+            public void run() {
+                invokeSubtypeEnablerOfThisIme();
+            }
+        });
+        mSetupSteps.addStep(STEP_3, step3);
+    }
+
+    private void invokeSetupWizardOfThisIme() {
         final Intent intent = new Intent();
-        intent.setClass(this, SettingsActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+        intent.setClass(this, SetupActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
         startActivity(intent);
-        finish();
+    }
+
+    private void invokeSettingsOfThisIme() {
+        final Intent intent = new Intent();
+        intent.setClass(this, SettingsActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        startActivity(intent);
+    }
+
+    private void invokeLanguageAndInputSettings() {
+        final Intent intent = new Intent();
+        intent.setAction(Settings.ACTION_INPUT_METHOD_SETTINGS);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        startActivity(intent);
+    }
+
+    private void invokeSubtypeEnablerOfThisIme() {
+        final InputMethodInfo imi =
+                RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme();
+        final Intent intent = new Intent();
+        intent.setAction(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imi.getId());
+        startActivity(intent);
+    }
+
+    private boolean isMyImeEnabled() {
+        final String packageName = getPackageName();
+        final InputMethodManager imm = RichInputMethodManager.getInstance().getInputMethodManager();
+        for (final InputMethodInfo imi : imm.getEnabledInputMethodList()) {
+            if (packageName.equals(imi.getPackageName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isMyImeCurrent() {
+        final InputMethodInfo myImi =
+                RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme();
+        final String currentImeId = Settings.Secure.getString(
+                getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        return myImi.getId().equals(currentImeId);
+    }
+
+    private int determineSetupStepNo() {
+        mHandler.cancelPollingImeSettings();
+        if (!isMyImeEnabled()) {
+            return STEP_1;
+        }
+        if (!isMyImeCurrent()) {
+            return STEP_2;
+        }
+        return STEP_3;
+    }
+
+    @Override
+    protected void onSaveInstanceState(final Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt(STATE_STEP, mStepNo);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(final Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        mStepNo = savedInstanceState.getInt(STATE_STEP);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mStepNo = determineSetupStepNo();
+    }
+
+    @Override
+    protected void onRestart() {
+        super.onRestart();
+        mStepNo = determineSetupStepNo();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        updateSetupStepView();
+    }
+
+    @Override
+    public void onWindowFocusChanged(final boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if (!hasFocus) {
+            return;
+        }
+        mStepNo = determineSetupStepNo();
+        updateSetupStepView();
+    }
+
+    private void updateSetupStepView() {
+        final int layoutDirection = ViewCompatUtils.getLayoutDirection(mStepIndicatorView);
+        mStepIndicatorView.setIndicatorPosition(
+                getIndicatorPosition(mStepNo, mSetupSteps.getTotalStep(), layoutDirection));
+        mSetupSteps.enableStep(mStepNo);
+    }
+
+    private static float getIndicatorPosition(final int step, final int totalStep,
+            final int layoutDirection) {
+        final float pos = ((step - STEP_1) * 2 + 1) / (float)(totalStep * 2);
+        return (layoutDirection == ViewCompatUtils.LAYOUT_DIRECTION_RTL) ? 1.0f - pos : pos;
+    }
+
+    static final class SetupStep implements View.OnClickListener {
+        private final View mRootView;
+        private final TextView mActionLabel;
+        private Runnable mAction;
+
+        public SetupStep(final View rootView, final int title, final int instruction,
+                final int actionIcon, final int actionLabel) {
+            mRootView = rootView;
+            final Resources res = rootView.getResources();
+            final String applicationName = res.getString(R.string.english_ime_name);
+
+            final TextView titleView = (TextView)rootView.findViewById(R.id.setup_step_title);
+            titleView.setText(res.getString(title, applicationName));
+
+            final TextView instructionView = (TextView)rootView.findViewById(
+                    R.id.setup_step_instruction);
+            if (instruction == 0) {
+                instructionView.setVisibility(View.GONE);
+            } else {
+                instructionView.setText(res.getString(instruction, applicationName));
+            }
+
+            mActionLabel = (TextView)rootView.findViewById(R.id.setup_step_action_label);
+            mActionLabel.setText(res.getString(actionLabel));
+            if (actionIcon == 0) {
+                final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
+                ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
+            } else {
+                final int overrideColor = res.getColor(R.color.setup_text_action);
+                final Drawable icon = res.getDrawable(actionIcon);
+                icon.setColorFilter(overrideColor, PorterDuff.Mode.MULTIPLY);
+                icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+                TextViewCompatUtils.setCompoundDrawablesRelative(
+                        mActionLabel, icon, null, null, null);
+            }
+        }
+
+        public void setEnabled(final boolean enabled) {
+            mRootView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+        }
+
+        public void setAction(final Runnable action) {
+            mActionLabel.setOnClickListener(this);
+            mAction = action;
+        }
+
+        @Override
+        public void onClick(final View v) {
+            if (mAction != null) {
+                mAction.run();
+            }
+        }
+    }
+
+    static final class SetupStepGroup {
+        private final HashMap<Integer, SetupStep> mGroup = CollectionUtils.newHashMap();
+
+        public void addStep(final int stepNo, final SetupStep step) {
+            mGroup.put(stepNo, step);
+        }
+
+        public void enableStep(final int enableStepNo) {
+            for (final Integer stepNo : mGroup.keySet()) {
+                final SetupStep step = mGroup.get(stepNo);
+                step.setEnabled(stepNo == enableStepNo);
+            }
+        }
+
+        public int getTotalStep() {
+            return mGroup.size();
+        }
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java b/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java
new file mode 100644
index 0000000..077a217
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.setup;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.inputmethod.latin.R;
+
+public final class SetupStepIndicatorView extends View {
+    private final Path mIndicatorPath = new Path();
+    private final Paint mIndicatorPaint = new Paint();
+    private float mXRatio;
+
+    public SetupStepIndicatorView(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mIndicatorPaint.setColor(getResources().getColor(R.color.setup_step_background));
+        mIndicatorPaint.setStyle(Paint.Style.FILL);
+    }
+
+    public void setIndicatorPosition(final float xRatio) {
+        mXRatio = xRatio;
+        invalidate();
+    }
+
+    @Override
+    protected void onDraw(final Canvas canvas) {
+        super.onDraw(canvas);
+        final int xPos = (int)(getWidth() * mXRatio);
+        final int height = getHeight();
+        mIndicatorPath.rewind();
+        mIndicatorPath.moveTo(xPos, 0);
+        mIndicatorPath.lineTo(xPos + height, height);
+        mIndicatorPath.lineTo(xPos - height, height);
+        mIndicatorPath.close();
+        canvas.drawPath(mIndicatorPath, mIndicatorPaint);
+    }
+}