Merge "Mark isDefault="true" for all supported subtypes" into lmp-dev
diff --git a/java/res/values/donottranslate-text-decorator.xml b/java/res/values/donottranslate-text-decorator.xml
index a200349..832610b 100644
--- a/java/res/values/donottranslate-text-decorator.xml
+++ b/java/res/values/donottranslate-text-decorator.xml
@@ -61,24 +61,18 @@
     <!-- Coordinates of the closed path to be used to render the commit indicator.
          The format is:  X[0], Y[0], X[1], Y[1], ..., X[N-1], Y[N-1] -->
     <integer-array name="text_decorator_commit_indicator_path">
-        <item>240</item>
-        <item>80</item>
-        <item>212</item>
-        <item>108</item>
+        <item>180</item>
         <item>323</item>
-        <item>220</item>
-        <item>80</item>
-        <item>220</item>
-        <item>80</item>
-        <item>260</item>
-        <item>323</item>
-        <item>260</item>
-        <item>212</item>
-        <item>372</item>
+        <item>97</item>
         <item>240</item>
-        <item>400</item>
-        <item>400</item>
-        <item>240</item>
+        <item>68</item>
+        <item>268</item>
+        <item>180</item>
+        <item>380</item>
+        <item>420</item>
+        <item>140</item>
+        <item>392</item>
+        <item>112</item>
     </integer-array>
 
     <!-- Background color to be used to highlight the target text when the add-to-dictionary
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
index 3a86ccb..8a28185 100644
--- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -34,10 +34,15 @@
      */
     public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
 
+    /**
+     * The insertion marker or character bounds is placed at right-to-left (RTL) character.
+     */
+    public static final int FLAG_IS_RTL = 0x04;
+
     // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX).
     private static final CompatUtils.ClassWrapper sCursorAnchorInfoClass;
-    private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterRectMethod;
-    private static final CompatUtils.ToIntMethodWrapper sGetCharacterRectFlagsMethod;
+    private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterBoundsMethod;
+    private static final CompatUtils.ToIntMethodWrapper sGetCharacterBoundsFlagsMethod;
     private static final CompatUtils.ToObjectMethodWrapper<CharSequence> sGetComposingTextMethod;
     private static final CompatUtils.ToIntMethodWrapper sGetComposingTextStartMethod;
     private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBaselineMethod;
@@ -51,10 +56,10 @@
     static {
         sCursorAnchorInfoClass = CompatUtils.getClassWrapper(
                 "android.view.inputmethod.CursorAnchorInfo");
-        sGetCharacterRectMethod = sCursorAnchorInfoClass.getMethod(
-                "getCharacterRect", (RectF)null, int.class);
-        sGetCharacterRectFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getCharacterRectFlags", 0, int.class);
+        sGetCharacterBoundsMethod = sCursorAnchorInfoClass.getMethod(
+                "getCharacterBounds", (RectF)null, int.class);
+        sGetCharacterBoundsFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
+                "getCharacterBoundsFlags", 0, int.class);
         sGetComposingTextMethod = sCursorAnchorInfoClass.getMethod(
                 "getComposingText", (CharSequence)null);
         sGetComposingTextStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
@@ -112,12 +117,12 @@
         return sGetMatrixMethod.invoke(mInstance);
     }
 
-    public RectF getCharacterRect(final int index) {
-        return sGetCharacterRectMethod.invoke(mInstance, index);
+    public RectF getCharacterBounds(final int index) {
+        return sGetCharacterBoundsMethod.invoke(mInstance, index);
     }
 
-    public int getCharacterRectFlags(final int index) {
-        return sGetCharacterRectFlagsMethod.invoke(mInstance, index);
+    public int getCharacterBoundsFlags(final int index) {
+        return sGetCharacterBoundsFlagsMethod.invoke(mInstance, index);
     }
 
     public float getInsertionMarkerBaseline() {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index ec089f7..e487516 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -38,6 +38,7 @@
 import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.SubtypeSwitcher;
 import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
@@ -60,7 +61,6 @@
     private KeyboardLayoutSet mKeyboardLayoutSet;
     // TODO: The following {@link KeyboardTextsSet} should be in {@link KeyboardLayoutSet}.
     private final KeyboardTextsSet mKeyboardTextsSet = new KeyboardTextsSet();
-    private SettingsValues mCurrentSettingsValues;
 
     private KeyboardTheme mKeyboardTheme;
     private Context mThemeContext;
@@ -120,7 +120,6 @@
         builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey);
         builder.setLanguageSwitchKeyEnabled(mLatinIME.shouldShowLanguageSwitchKey());
         mKeyboardLayoutSet = builder.build();
-        mCurrentSettingsValues = settingsValues;
         try {
             mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState);
             mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale(), mThemeContext);
@@ -144,22 +143,24 @@
 
     private void setKeyboard(final Keyboard keyboard) {
         // Make {@link MainKeyboardView} visible and hide {@link EmojiPalettesView}.
-        setMainKeyboardFrame();
+        final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent();
+        setMainKeyboardFrame(currentSettingsValues);
+        // TODO: pass this object to setKeyboard instead of getting the current values.
         final MainKeyboardView keyboardView = mKeyboardView;
         final Keyboard oldKeyboard = keyboardView.getKeyboard();
         keyboardView.setKeyboard(keyboard);
         mCurrentInputView.setKeyboardTopPadding(keyboard.mTopPadding);
         keyboardView.setKeyPreviewPopupEnabled(
-                mCurrentSettingsValues.mKeyPreviewPopupOn,
-                mCurrentSettingsValues.mKeyPreviewPopupDismissDelay);
+                currentSettingsValues.mKeyPreviewPopupOn,
+                currentSettingsValues.mKeyPreviewPopupDismissDelay);
         keyboardView.setKeyPreviewAnimationParams(
-                mCurrentSettingsValues.mHasCustomKeyPreviewAnimationParams,
-                mCurrentSettingsValues.mKeyPreviewShowUpStartXScale,
-                mCurrentSettingsValues.mKeyPreviewShowUpStartYScale,
-                mCurrentSettingsValues.mKeyPreviewShowUpDuration,
-                mCurrentSettingsValues.mKeyPreviewDismissEndXScale,
-                mCurrentSettingsValues.mKeyPreviewDismissEndYScale,
-                mCurrentSettingsValues.mKeyPreviewDismissDuration);
+                currentSettingsValues.mHasCustomKeyPreviewAnimationParams,
+                currentSettingsValues.mKeyPreviewShowUpStartXScale,
+                currentSettingsValues.mKeyPreviewShowUpStartYScale,
+                currentSettingsValues.mKeyPreviewShowUpDuration,
+                currentSettingsValues.mKeyPreviewDismissEndXScale,
+                currentSettingsValues.mKeyPreviewDismissEndYScale,
+                currentSettingsValues.mKeyPreviewDismissDuration);
         keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
         final boolean subtypeChanged = (oldKeyboard == null)
                 || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
@@ -236,22 +237,13 @@
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
     }
 
-    private void setMainKeyboardFrame() {
-        mMainKeyboardFrame.setVisibility(hasHardwareKeyboard() ? View.GONE : View.VISIBLE);
+    private void setMainKeyboardFrame(final SettingsValues settingsValues) {
+        mMainKeyboardFrame.setVisibility(
+                settingsValues.mHasHardwareKeyboard ? View.GONE : View.VISIBLE);
         mEmojiPalettesView.setVisibility(View.GONE);
         mEmojiPalettesView.stopEmojiPalettes();
     }
 
-    // TODO: Move this boolean to a member of {@link SettingsValues} and reset it
-    // at {@link LatinIME#onConfigurationChanged(Configuration)}.
-    public boolean hasHardwareKeyboard() {
-        // Copied from {@link InputMethodServce#onEvaluateInputViewShown()}.
-        final Configuration config = mLatinIME.getResources().getConfiguration();
-        final boolean noHardwareKeyboard = config.keyboard == Configuration.KEYBOARD_NOKEYS
-                || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
-        return !noHardwareKeyboard;
-    }
-
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setEmojiKeyboard() {
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
index 9192853..cf58d6a 100644
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -274,8 +274,8 @@
             }
             final int composingTextStart = info.getComposingTextStart();
             final int lastCharRectIndex = composingTextStart + composingText.length() - 1;
-            final RectF lastCharRect = info.getCharacterRect(lastCharRectIndex);
-            final int lastCharRectFlag = info.getCharacterRectFlags(lastCharRectIndex);
+            final RectF lastCharRect = info.getCharacterBounds(lastCharRectIndex);
+            final int lastCharRectFlag = info.getCharacterBoundsFlags(lastCharRectIndex);
             final boolean hasInvisibleRegionInLastCharRect =
                     (lastCharRectFlag & CursorAnchorInfoCompatWrapper.FLAG_HAS_INVISIBLE_REGION)
                             != 0;
@@ -285,7 +285,7 @@
             }
             final RectF segmentStartCharRect = new RectF(lastCharRect);
             for (int i = composingText.length() - 2; i >= 0; --i) {
-                final RectF charRect = info.getCharacterRect(composingTextStart + i);
+                final RectF charRect = info.getCharacterBounds(composingTextStart + i);
                 if (charRect == null) {
                     break;
                 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index c348e6c..e4f39bb 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1074,12 +1074,13 @@
     @Override
     public void onComputeInsets(final InputMethodService.Insets outInsets) {
         super.onComputeInsets(outInsets);
+        final SettingsValues settingsValues = mSettings.getCurrent();
         final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView();
         if (visibleKeyboardView == null || !hasSuggestionStripView()) {
             return;
         }
         final int inputHeight = mInputView.getHeight();
-        final boolean hasHardwareKeyboard = mKeyboardSwitcher.hasHardwareKeyboard();
+        final boolean hasHardwareKeyboard = settingsValues.mHasHardwareKeyboard;
         if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
             // If there is a hardware keyboard and a visible software keyboard view has been hidden,
             // no visual element will be shown on the screen.
@@ -1115,7 +1116,8 @@
 
     @Override
     public boolean onShowInputRequested(final int flags, final boolean configChange) {
-        if ((flags & InputMethod.SHOW_EXPLICIT) == 0 && mKeyboardSwitcher.hasHardwareKeyboard()) {
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if ((flags & InputMethod.SHOW_EXPLICIT) == 0 && settingsValues.mHasHardwareKeyboard) {
             // Even when IME is implicitly shown and physical keyboard is connected, we should
             // show {@link InputView}.
             // See {@link InputMethodService#onShowInputRequested(int,boolean)}.
@@ -1126,7 +1128,8 @@
 
     @Override
     public boolean onEvaluateFullscreenMode() {
-        if (mKeyboardSwitcher.hasHardwareKeyboard()) {
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if (settingsValues.mHasHardwareKeyboard) {
             // If there is a hardware keyboard, disable full screen mode.
             return false;
         }
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 9d3c27b..3c7a991 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Build;
 import android.preference.PreferenceManager;
@@ -368,6 +369,15 @@
         return prefs.getBoolean(PREF_SHOW_SETUP_WIZARD_ICON, false);
     }
 
+    public static boolean readHasHardwareKeyboard(final Configuration conf) {
+        // The standard way of finding out whether we have a hardware keyboard. This code is taken
+        // from InputMethodService#onEvaluateInputShown, which canonically determines this.
+        // In a nutshell, we have a keyboard if the configuration says the type of hardware keyboard
+        // is NOKEYS and if it's not hidden (e.g. folded inside the device).
+        return conf.keyboard != Configuration.KEYBOARD_NOKEYS
+                && conf.hardKeyboardHidden != Configuration.HARDKEYBOARDHIDDEN_YES;
+    }
+
     public static boolean isInternal(final SharedPreferences prefs) {
         return prefs.getBoolean(PREF_KEY_IS_INTERNAL, false);
     }
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 1da112b..308f3b4 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -52,7 +52,10 @@
     public final SpacingAndPunctuations mSpacingAndPunctuations;
     public final int mDelayInMillisecondsToUpdateOldSuggestions;
     public final long mDoubleSpacePeriodTimeout;
-
+    // From configuration:
+    public final Locale mLocale;
+    public final boolean mHasHardwareKeyboard;
+    public final int mDisplayOrientation;
     // From preferences, in the same order as xml/prefs.xml:
     public final boolean mAutoCap;
     public final boolean mVibrateOn;
@@ -73,7 +76,6 @@
     public final boolean mSlidingKeyInputPreviewEnabled;
     public final boolean mPhraseGestureEnabled;
     public final int mKeyLongpressTimeout;
-    public final Locale mLocale;
     public final boolean mEnableMetricsLogging;
     public final boolean mShouldShowUiToAcceptTypedWord;
 
@@ -88,7 +90,6 @@
     public final float mAutoCorrectionThreshold;
     public final boolean mAutoCorrectionEnabledPerUserSettings;
     private final boolean mSuggestionsEnabledPerUserSettings;
-    public final int mDisplayOrientation;
     private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds;
 
     // Setting values for additional features
@@ -152,6 +153,7 @@
         mAutoCorrectEnabled = Settings.readAutoCorrectEnabled(autoCorrectionThresholdRawValue, res);
         mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
         mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
+        mHasHardwareKeyboard = Settings.readHasHardwareKeyboard(res.getConfiguration());
         mEnableMetricsLogging = prefs.getBoolean(Settings.PREF_ENABLE_METRICS_LOGGING, true);
         mShouldShowUiToAcceptTypedWord = Settings.HAS_UI_TO_ACCEPT_TYPED_WORD
                 && prefs.getBoolean(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD, true);