Merge "[FileEncap5] Move conditional logic to caller"
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 2a47d7a..68fa8fd 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -434,4 +434,6 @@
     <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>
+    <!-- Option to show setup wizard icon. [CHAR LIMIT=30]-->
+    <string name="show_setup_wizard_icon" translatable="false">Show setup wizard icon</string>
 </resources>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 276395b..e5fef88 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -145,7 +145,7 @@
                 android:fragment="com.android.inputmethod.latin.AdditionalSubtypeSettings"
                 android:key="custom_input_styles"
                 android:title="@string/custom_input_styles_title" />
-            <!-- Values for popup dismiss delay are added programatically -->
+            <!-- Values for popup dismiss delay are added programmatically -->
             <CheckBoxPreference
                 android:key="pref_sliding_key_input_preview"
                 android:title="@string/sliding_key_input_preview"
@@ -171,6 +171,11 @@
                 android:key="pref_keypress_sound_volume"
                 android:title="@string/prefs_keypress_sound_volume_settings"
                 latin:maxValue="100" /> <!-- percent -->
+            <!-- The show setup wizard icon settings shouldn't be persistent and the default value
+                 is added programmatically. -->
+            <CheckBoxPreference
+                android:key="pref_show_setup_wizard_icon"
+                android:title="@string/show_setup_wizard_icon" />
         </PreferenceScreen>
         <PreferenceScreen
             android:key="debug_settings"
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 02b44c7..435074b 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
 import android.preference.PreferenceManager;
 
@@ -64,6 +65,7 @@
     public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail";
     public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT =
             "pref_gesture_floating_preview_text";
+    public static final String PREF_SHOW_SETUP_WIZARD_ICON = "pref_show_setup_wizard_icon";
 
     public static final String PREF_INPUT_LANGUAGE = "input_language";
     public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
@@ -260,4 +262,16 @@
     public static boolean readUseFullscreenMode(final Resources res) {
         return res.getBoolean(R.bool.config_use_fullscreen_mode);
     }
+
+    public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
+            final Context context) {
+        if (!prefs.contains(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
+            final ApplicationInfo appInfo = context.getApplicationInfo();
+            final boolean isApplicationInSystemImage =
+                    (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+            // Default value
+            return !isApplicationInSystemImage;
+        }
+        return prefs.getBoolean(Settings.PREF_SHOW_SETUP_WIZARD_ICON, false);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
index edd064c..4c90e48 100644
--- a/java/src/com/android/inputmethod/latin/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -31,6 +31,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
 import com.android.inputmethodcommon.InputMethodSettingsFragment;
 
 public final class SettingsFragment extends InputMethodSettingsFragment
@@ -155,6 +156,10 @@
             removePreference(Settings.PREF_GESTURE_SETTINGS, getPreferenceScreen());
         }
 
+        final CheckBoxPreference showSetupWizardIcon =
+                (CheckBoxPreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
+        showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, context));
+
         setupKeyLongpressTimeoutSettings(prefs, res);
         setupKeypressVibrationDurationSettings(prefs, res);
         setupKeypressSoundVolumeSettings(prefs, res);
@@ -196,6 +201,8 @@
             final boolean gestureInputEnabled = Settings.readGestureInputEnabled(prefs, res);
             setPreferenceEnabled(Settings.PREF_GESTURE_PREVIEW_TRAIL, gestureInputEnabled);
             setPreferenceEnabled(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, gestureInputEnabled);
+        } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
+            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity());
         }
         ensureConsistencyOfAutoCorrectionSettings();
         updateVoiceModeSummary();
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index acfcd53..7a604dc 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -28,6 +28,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
 import java.io.BufferedReader;
@@ -77,6 +78,7 @@
         private RingCharBuffer() {
             // Intentional empty constructor for singleton.
         }
+        @UsedForTesting
         public static RingCharBuffer getInstance() {
             return sRingCharBuffer;
         }
@@ -93,6 +95,7 @@
             return ret < 0 ? ret + BUFSIZE : ret;
         }
         // TODO: accept code points
+        @UsedForTesting
         public void push(char c, int x, int y) {
             if (!mEnabled) return;
             mCharBuf[mEnd] = c;
diff --git a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
index ad34011..1b893a6 100644
--- a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
+++ b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
@@ -16,18 +16,19 @@
 
 package com.android.inputmethod.latin.setup;
 
-import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
+import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.os.Process;
+import android.preference.PreferenceManager;
 import android.util.Log;
 
 import com.android.inputmethod.compat.IntentCompatUtils;
 import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.Settings;
 
 /**
  * This class detects the {@link Intent#ACTION_MY_PACKAGE_REPLACED} broadcast intent when this IME
@@ -60,11 +61,7 @@
     @Override
     public void onReceive(final Context context, final Intent intent) {
         if (shouldHandleThisIntent(intent, context)) {
-            if (isInSystemImage(context)) {
-                disableActivity(context, SetupActivity.class);
-            } else {
-                Log.i(TAG, "This package isn't in system image: " + context.getPackageName());
-            }
+            updateSetupWizardIconVisibility(context);
         }
 
         // The process that hosts this broadcast receiver is invoked and remains alive even after
@@ -94,32 +91,32 @@
         return false;
     }
 
-    /**
-     * Disable an activity of the specified package. Disabling an activity will also hide its
-     * icon from the launcher.
-     *
-     * @param context package context of an activity to be disabled
-     * @param activityClass activity class to be disabled
-     */
-    private static void disableActivity(final Context context,
-            final Class<? extends Activity> activityClass) {
-        final ComponentName activityComponent = new ComponentName(context, activityClass);
-        final PackageManager pm = context.getPackageManager();
-        final int activityComponentState = pm.getComponentEnabledSetting(activityComponent);
-        if (activityComponentState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
-            // This activity is already disabled.
-            Log.i(TAG, "Activity has already been disabled: " + activityComponent);
-            return;
+    public static void updateSetupWizardIconVisibility(final Context context) {
+        final ComponentName setupWizardActivity = new ComponentName(context, SetupActivity.class);
+        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        final boolean stateHasSet;
+        if (Settings.readShowSetupWizardIcon(prefs, context)) {
+            stateHasSet = setActivityState(context, setupWizardActivity,
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+            Log.i(TAG, (stateHasSet ? "Enable activity: " : "Activity has already been enabled: ")
+                    + setupWizardActivity);
+        } else {
+            stateHasSet = setActivityState(context, setupWizardActivity,
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+            Log.i(TAG, (stateHasSet ? "Disable activity: " : "Activity has already been disabled: ")
+                    + setupWizardActivity);
         }
-        // Disabling an activity will also hide its icon from the launcher.
-        pm.setComponentEnabledSetting(activityComponent,
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                PackageManager.DONT_KILL_APP);
-        Log.i(TAG, "Disable activity: " + activityComponent);
     }
 
-    private static boolean isInSystemImage(final Context context) {
-        final ApplicationInfo appInfo = context.getApplicationInfo();
-        return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    private static boolean setActivityState(final Context context,
+            final ComponentName activityComponent, final int activityState) {
+        final PackageManager pm = context.getPackageManager();
+        final int activityComponentState = pm.getComponentEnabledSetting(activityComponent);
+        if (activityComponentState == activityState) {
+            return false;
+        }
+        pm.setComponentEnabledSetting(
+                activityComponent, activityState, PackageManager.DONT_KILL_APP);
+        return true;
     }
 }
diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp
index f1148f4..8d917ea 100644
--- a/native/jni/src/char_utils.cpp
+++ b/native/jni/src/char_utils.cpp
@@ -1070,12 +1070,14 @@
     /* U+0418 */ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
         // U+0419: Manually changed from 0418 to 0419
     /* U+0420 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
-    /* U+0428 */ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+    /* U+0428 */ 0x0428, 0x0429, 0x042C, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+        // U+042A: Manually changed from 042A to 042C
     /* U+0430 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
     /* U+0438 */ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
         // U+0439: Manually changed from 0438 to 0439
     /* U+0440 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
-    /* U+0448 */ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+    /* U+0448 */ 0x0448, 0x0449, 0x044C, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+        // U+044A: Manually changed from 044A to 044C
     /* U+0450 */ 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456,
     /* U+0458 */ 0x0458, 0x0459, 0x045A, 0x045B, 0x043A, 0x0438, 0x0443, 0x045F,
     /* U+0460 */ 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467,
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 34f794d..f0d6210 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -119,7 +119,7 @@
     // proximity info state
     void initInputParams(const ProximityInfo *proximityInfo, const int *inputCodes,
             const int inputSize, const int *xCoordinates, const int *yCoordinates) {
-        mProximityInfoState.initInputParams(0, MAX_POINT_TO_KEY_LENGTH,
+        mProximityInfoState.initInputParams(0, static_cast<float>(MAX_VALUE_FOR_WEIGHTING),
                 proximityInfo, inputCodes, inputSize, xCoordinates, yCoordinates, 0, 0, false);
     }
 
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 5546876..11dc3d2 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -341,8 +341,9 @@
 #define MAX_DEPTH_MULTIPLIER 3
 #define FIRST_WORD_INDEX 0
 
-// Max Distance between point to key
-#define MAX_POINT_TO_KEY_LENGTH 10000000
+// Max value for length, distance and probability which are used in weighting
+// TODO: Remove
+#define MAX_VALUE_FOR_WEIGHTING 10000000
 
 // The max number of the keys in one keyboard layout
 #define MAX_KEY_COUNT_IN_A_KEYBOARD 64
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 81eb0b3..74b5e01 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -204,6 +204,6 @@
     if (keyId0 >= 0 && keyId1 >= 0) {
         return mKeyKeyDistancesG[keyId0][keyId1];
     }
-    return MAX_POINT_TO_KEY_LENGTH;
+    return MAX_VALUE_FOR_WEIGHTING;
 }
 } // namespace latinime
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index 3ecaade..00e7ffc 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -170,7 +170,7 @@
         return 0.0f;
     }
     // If the char is not a key on the keyboard then return the max length.
-    return MAX_POINT_TO_KEY_LENGTH;
+    return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
 }
 
 float ProximityInfoState::getPointToKeyLength_G(const int inputIndex, const int codePoint) const {
@@ -314,6 +314,6 @@
     if (it != mCharProbabilities[index].end()) {
         return it->second;
     }
-    return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+    return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
 }
 } // namespace latinime
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp
index 2bf327f..2ca39f9 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/proximity_info_state_utils.cpp
@@ -645,7 +645,7 @@
         return min((*SampledDistanceCache_G)[index] * scale, maxPointToKeyLength);
     }
     // If the char is not a key on the keyboard then return the max length.
-    return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+    return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
 }
 
 /* static */ float ProximityInfoStateUtils::getPointToKeyByIdLength(const float maxPointToKeyLength,
@@ -678,7 +678,7 @@
         const float currentAngle = getPointAngle(sampledInputXs, sampledInputYs, i);
         const float speedRate = (*sampledSpeedRates)[i];
 
-        float nearestKeyDistance = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+        float nearestKeyDistance = static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
         for (int j = 0; j < keyCount; ++j) {
             if ((*SampledNearKeySets)[i].test(j)) {
                 const float distance = getPointToKeyByIdLength(
@@ -1016,7 +1016,7 @@
     float sumLogProbability = 0.0f;
     // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases.
     for (int i = 0; i < sampledInputSize && index < MAX_WORD_LENGTH - 1; ++i) {
-        float minLogProbability = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+        float minLogProbability = static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
         int character = NOT_AN_INDEX;
         for (hash_map_compat<int, float>::const_iterator it = (*charProbabilities)[i].begin();
                 it != (*charProbabilities)[i].end(); ++it) {
diff --git a/native/jni/src/proximity_info_utils.h b/native/jni/src/proximity_info_utils.h
index 51cafba..71c97e3 100644
--- a/native/jni/src/proximity_info_utils.h
+++ b/native/jni/src/proximity_info_utils.h
@@ -226,7 +226,7 @@
             const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights,
             const int keyId, const int x, const int y) {
         // NOT_A_ID is -1, but return whenever < 0 just in case
-        if (keyId < 0) return MAX_POINT_TO_KEY_LENGTH;
+        if (keyId < 0) return MAX_VALUE_FOR_WEIGHTING;
         const int left = keyXCoordinates[keyId];
         const int top = keyYCoordinates[keyId];
         const int right = left + keyWidths[keyId];