am 1708ff6e: am 914078fd: Fix a bug where recorrection would stop on connectors

* commit '1708ff6e5416d4333d3f52f62cd71b64ea580cd7':
diff --git a/java/res/drawable-hdpi/ic_launcher_keyboard.png b/java/res/drawable-hdpi/ic_launcher_keyboard.png
index 7ae00ed..3a01e61 100644
--- a/java/res/drawable-hdpi/ic_launcher_keyboard.png
+++ b/java/res/drawable-hdpi/ic_launcher_keyboard.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_launcher_keyboard.png b/java/res/drawable-mdpi/ic_launcher_keyboard.png
index cc73f3b..574da25 100644
--- a/java/res/drawable-mdpi/ic_launcher_keyboard.png
+++ b/java/res/drawable-mdpi/ic_launcher_keyboard.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_launcher_keyboard.png b/java/res/drawable-xhdpi/ic_launcher_keyboard.png
index f2ac50d..1769501 100644
--- a/java/res/drawable-xhdpi/ic_launcher_keyboard.png
+++ b/java/res/drawable-xhdpi/ic_launcher_keyboard.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_launcher_keyboard.png b/java/res/drawable-xxhdpi/ic_launcher_keyboard.png
index df386e8..624c82e 100644
--- a/java/res/drawable-xxhdpi/ic_launcher_keyboard.png
+++ b/java/res/drawable-xxhdpi/ic_launcher_keyboard.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_active_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_lxx_dark.9.png
new file mode 100644
index 0000000..eac4475
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_active_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_lxx_light.9.png
new file mode 100644
index 0000000..16d1f68
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_active_pressed_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_pressed_lxx_dark.9.png
new file mode 100644
index 0000000..78923a8
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_pressed_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_active_pressed_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_pressed_lxx_light.9.png
new file mode 100644
index 0000000..e57e80d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_active_pressed_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
new file mode 100644
index 0000000..0b3d796
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_off_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_off_lxx_light.9.png
new file mode 100644
index 0000000..6edd4e3
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_off_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
new file mode 100644
index 0000000..61a5efc
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_on_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_on_lxx_light.9.png
new file mode 100644
index 0000000..c60a235
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_normal_on_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_popup_selected_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_popup_selected_lxx_dark.9.png
new file mode 100644
index 0000000..842c685
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_popup_selected_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_popup_selected_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_popup_selected_lxx_light.9.png
new file mode 100644
index 0000000..6b03306
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_popup_selected_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
new file mode 100644
index 0000000..276065e
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_off_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_off_lxx_light.9.png
new file mode 100644
index 0000000..e64147f
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_off_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
new file mode 100644
index 0000000..c130014
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_on_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_on_lxx_light.9.png
new file mode 100644
index 0000000..e433f56
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_key_pressed_on_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_normal_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_normal_lxx_dark.9.png
new file mode 100644
index 0000000..ee4d16b
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_normal_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_normal_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_normal_lxx_light.9.png
new file mode 100644
index 0000000..14cba3c
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_normal_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_pressed_lxx_dark.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_pressed_lxx_dark.9.png
new file mode 100644
index 0000000..671c31f
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_pressed_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_pressed_lxx_light.9.png b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_pressed_lxx_light.9.png
new file mode 100644
index 0000000..8a6f32a
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/btn_keyboard_spacebar_pressed_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_add_circle_white_24dp.png b/java/res/drawable-xxxhdpi/ic_add_circle_white_24dp.png
new file mode 100644
index 0000000..a0116fa
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_add_circle_white_24dp.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_emoticons_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_activated_lxx_dark.png
new file mode 100644
index 0000000..0198bce
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_emoticons_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_activated_lxx_light.png
new file mode 100644
index 0000000..f530ba1
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_emoticons_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_normal_lxx_dark.png
new file mode 100644
index 0000000..d9022bb
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_emoticons_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_normal_lxx_light.png
new file mode 100644
index 0000000..89dc4cd
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_emoticons_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_nature_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_nature_activated_lxx_dark.png
new file mode 100644
index 0000000..efbf51c
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_nature_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_nature_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_nature_activated_lxx_light.png
new file mode 100644
index 0000000..95355c6
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_nature_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_nature_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_nature_normal_lxx_dark.png
new file mode 100644
index 0000000..f5531ea
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_nature_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_nature_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_nature_normal_lxx_light.png
new file mode 100644
index 0000000..b5085cb
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_nature_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_objects_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_objects_activated_lxx_dark.png
new file mode 100644
index 0000000..730f75d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_objects_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_objects_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_objects_activated_lxx_light.png
new file mode 100644
index 0000000..f4a250d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_objects_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_objects_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_objects_normal_lxx_dark.png
new file mode 100644
index 0000000..4658cea
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_objects_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_objects_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_objects_normal_lxx_light.png
new file mode 100644
index 0000000..7b27829
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_objects_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_people_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_people_activated_lxx_dark.png
new file mode 100644
index 0000000..b70f07a
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_people_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_people_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_people_activated_lxx_light.png
new file mode 100644
index 0000000..7e05208
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_people_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_people_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_people_normal_lxx_dark.png
new file mode 100644
index 0000000..c960d15
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_people_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_people_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_people_normal_lxx_light.png
new file mode 100644
index 0000000..44325cf
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_people_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_places_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_places_activated_lxx_dark.png
new file mode 100644
index 0000000..bca6bba
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_places_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_places_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_places_activated_lxx_light.png
new file mode 100644
index 0000000..8f340d2
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_places_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_places_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_places_normal_lxx_dark.png
new file mode 100644
index 0000000..a06e1d8
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_places_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_places_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_places_normal_lxx_light.png
new file mode 100644
index 0000000..b247768
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_places_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_recents_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_recents_activated_lxx_dark.png
new file mode 100644
index 0000000..3508374
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_recents_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_recents_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_recents_activated_lxx_light.png
new file mode 100644
index 0000000..82a029e
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_recents_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_recents_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_recents_normal_lxx_dark.png
new file mode 100644
index 0000000..6797d7b
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_recents_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_recents_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_recents_normal_lxx_light.png
new file mode 100644
index 0000000..6b622ac
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_recents_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_symbols_activated_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_symbols_activated_lxx_dark.png
new file mode 100644
index 0000000..51336e9
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_symbols_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_symbols_activated_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_symbols_activated_lxx_light.png
new file mode 100644
index 0000000..2ab8fa6
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_symbols_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_symbols_normal_lxx_dark.png b/java/res/drawable-xxxhdpi/ic_emoji_symbols_normal_lxx_dark.png
new file mode 100644
index 0000000..e02ad61
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_symbols_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_emoji_symbols_normal_lxx_light.png b/java/res/drawable-xxxhdpi/ic_emoji_symbols_normal_lxx_light.png
new file mode 100644
index 0000000..b17f066
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_emoji_symbols_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/ic_launcher_keyboard.png b/java/res/drawable-xxxhdpi/ic_launcher_keyboard.png
new file mode 100644
index 0000000..39636a1
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/ic_launcher_keyboard.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_background_lxx_dark.9.png b/java/res/drawable-xxxhdpi/keyboard_background_lxx_dark.9.png
new file mode 100644
index 0000000..a7dd537
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_background_lxx_light.9.png b/java/res/drawable-xxxhdpi/keyboard_background_lxx_light.9.png
new file mode 100644
index 0000000..ef7ab20
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_key_feedback_background_lxx_dark.9.png b/java/res/drawable-xxxhdpi/keyboard_key_feedback_background_lxx_dark.9.png
new file mode 100644
index 0000000..b68d3e8
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_key_feedback_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_key_feedback_background_lxx_light.9.png b/java/res/drawable-xxxhdpi/keyboard_key_feedback_background_lxx_light.9.png
new file mode 100644
index 0000000..0da475b
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_key_feedback_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png b/java/res/drawable-xxxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
new file mode 100644
index 0000000..fa86340
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_key_feedback_more_background_lxx_light.9.png b/java/res/drawable-xxxhdpi/keyboard_key_feedback_more_background_lxx_light.9.png
new file mode 100644
index 0000000..e3ff4d4
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_key_feedback_more_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_popup_panel_background_lxx_dark.9.png b/java/res/drawable-xxxhdpi/keyboard_popup_panel_background_lxx_dark.9.png
new file mode 100644
index 0000000..3489a9c
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_popup_panel_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_popup_panel_background_lxx_light.9.png b/java/res/drawable-xxxhdpi/keyboard_popup_panel_background_lxx_light.9.png
new file mode 100644
index 0000000..2e37972
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_popup_panel_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_suggest_strip_lxx_dark.9.png b/java/res/drawable-xxxhdpi/keyboard_suggest_strip_lxx_dark.9.png
new file mode 100644
index 0000000..098fa06
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_suggest_strip_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/keyboard_suggest_strip_lxx_light.9.png b/java/res/drawable-xxxhdpi/keyboard_suggest_strip_lxx_light.9.png
new file mode 100644
index 0000000..c1c48c9
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/keyboard_suggest_strip_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/suggestions_strip_divider_lxx_dark.png b/java/res/drawable-xxxhdpi/suggestions_strip_divider_lxx_dark.png
new file mode 100644
index 0000000..0dc783d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/suggestions_strip_divider_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/suggestions_strip_divider_lxx_light.png b/java/res/drawable-xxxhdpi/suggestions_strip_divider_lxx_light.png
new file mode 100644
index 0000000..f3162e4
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/suggestions_strip_divider_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_delete_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_delete_lxx_dark.png
new file mode 100644
index 0000000..c8a064d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_delete_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_delete_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_delete_lxx_light.png
new file mode 100644
index 0000000..2d2e6e1
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_delete_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_done_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_done_lxx_dark.png
new file mode 100644
index 0000000..27426da
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_done_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_done_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_done_lxx_light.png
new file mode 100644
index 0000000..4b1a69f
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_done_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_go_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_go_lxx_dark.png
new file mode 100644
index 0000000..79d3eef
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_go_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_go_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_go_lxx_light.png
new file mode 100644
index 0000000..a87e240
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_go_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_language_switch_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_language_switch_lxx_dark.png
new file mode 100644
index 0000000..26f3615
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_language_switch_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_language_switch_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_language_switch_lxx_light.png
new file mode 100644
index 0000000..93efb37
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_language_switch_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_next_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_next_lxx_dark.png
new file mode 100644
index 0000000..27bf689
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_next_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_next_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_next_lxx_light.png
new file mode 100644
index 0000000..c624104
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_next_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_previous_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_previous_lxx_dark.png
new file mode 100644
index 0000000..50e0a31
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_previous_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_previous_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_previous_lxx_light.png
new file mode 100644
index 0000000..3f44249
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_previous_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_return_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_return_lxx_dark.png
new file mode 100644
index 0000000..c101071
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_return_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_return_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_return_lxx_light.png
new file mode 100644
index 0000000..54e7fb0
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_return_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_search_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_search_lxx_dark.png
new file mode 100644
index 0000000..8f7dfce
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_search_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_search_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_search_lxx_light.png
new file mode 100644
index 0000000..07d5551
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_search_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_send_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_send_lxx_dark.png
new file mode 100644
index 0000000..9c12ec2
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_send_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_send_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_send_lxx_light.png
new file mode 100644
index 0000000..fc68828
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_send_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_settings_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_settings_lxx_dark.png
new file mode 100644
index 0000000..d728b83
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_settings_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_settings_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_settings_lxx_light.png
new file mode 100644
index 0000000..1351710
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_settings_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_shift_locked_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_shift_locked_lxx_dark.png
new file mode 100644
index 0000000..e75d556
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_shift_locked_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_shift_locked_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_shift_locked_lxx_light.png
new file mode 100644
index 0000000..00521bf
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_shift_locked_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_shift_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_shift_lxx_dark.png
new file mode 100644
index 0000000..f47bf66
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_shift_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_shift_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_shift_lxx_light.png
new file mode 100644
index 0000000..fdb6cd7
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_shift_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_smiley_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_smiley_lxx_dark.png
new file mode 100644
index 0000000..26fd4e7
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_smiley_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_smiley_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_smiley_lxx_light.png
new file mode 100644
index 0000000..7b0467a
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_smiley_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_space_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_space_lxx_dark.png
new file mode 100644
index 0000000..1f6c92d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_space_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_space_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_space_lxx_light.png
new file mode 100644
index 0000000..656cf99
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_space_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_tab_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_tab_lxx_dark.png
new file mode 100644
index 0000000..8988469
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_tab_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_tab_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_tab_lxx_light.png
new file mode 100644
index 0000000..aeedba6
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_tab_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_voice_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_voice_lxx_dark.png
new file mode 100644
index 0000000..9d5b733
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_voice_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_voice_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_voice_lxx_light.png
new file mode 100644
index 0000000..9db910d
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_voice_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_voice_off_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_voice_off_lxx_dark.png
new file mode 100644
index 0000000..e233d09
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_voice_off_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_voice_off_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_voice_off_lxx_light.png
new file mode 100644
index 0000000..7e0a964
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_voice_off_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_zwj_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_zwj_lxx_dark.png
new file mode 100644
index 0000000..94de916
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_zwj_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_zwj_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_zwj_lxx_light.png
new file mode 100644
index 0000000..2b13ba7
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_zwj_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_zwnj_lxx_dark.png b/java/res/drawable-xxxhdpi/sym_keyboard_zwnj_lxx_dark.png
new file mode 100644
index 0000000..134bca6
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_zwnj_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxxhdpi/sym_keyboard_zwnj_lxx_light.png b/java/res/drawable-xxxhdpi/sym_keyboard_zwnj_lxx_light.png
new file mode 100644
index 0000000..31cf75b
--- /dev/null
+++ b/java/res/drawable-xxxhdpi/sym_keyboard_zwnj_lxx_light.png
Binary files differ
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 2e81bdf..f1253b4 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -338,6 +338,8 @@
             <!-- If true, use functionalTextColor instead of ketTextColor to drawing the label on
                  the key -->
             <flag name="followFunctionalTextColor" value="0x80000" />
+            <!-- Keep aspect ratio of key background. -->
+            <flag name="keepBackgroundAspectRatio" value="0x100000" />
             <!-- If true, disable keyHintLabel. -->
             <flag name="disableKeyHintLabel" value="0x40000000" />
             <!-- If true, disable additionalMoreKeys. -->
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index 76e9d33..5b26813 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -114,6 +114,7 @@
         <item name="android:background">@android:color/transparent</item>
         <item name="keyBackground">@drawable/btn_keyboard_key_popup_action_lxx_dark</item>
         <item name="divider">@null</item>
+        <item name="keyLabelFlags">keepBackgroundAspectRatio</item>
     </style>
     <style
         name="SuggestionStripView.LXX_Dark"
diff --git a/java/res/values/themes-lxx-light.xml b/java/res/values/themes-lxx-light.xml
index 5cd8417..f607807 100644
--- a/java/res/values/themes-lxx-light.xml
+++ b/java/res/values/themes-lxx-light.xml
@@ -114,6 +114,7 @@
         <item name="android:background">@android:color/transparent</item>
         <item name="keyBackground">@drawable/btn_keyboard_key_popup_action_lxx_light</item>
         <item name="divider">@null</item>
+        <item name="keyLabelFlags">keepBackgroundAspectRatio</item>
     </style>
     <style
         name="SuggestionStripView.LXX_Light"
diff --git a/java/res/xml-sw600dp/key_styles_enter.xml b/java/res/xml-sw600dp/key_styles_enter.xml
index d066d2d..63ef2f8 100644
--- a/java/res/xml-sw600dp/key_styles_enter.xml
+++ b/java/res/xml-sw600dp/key_styles_enter.xml
@@ -80,13 +80,27 @@
         </default>
     </switch>
     <!-- Enter key style -->
-    <key-style
-        latin:styleName="defaultEnterKeyStyle"
-        latin:keySpec="!icon/enter_key|!code/key_enter"
-        latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="action"
-        latin:parentStyle="navigateMoreKeysStyle" />
+    <switch>
+        <case latin:keyboardTheme="ICS|KLP">
+            <key-style
+                latin:styleName="defaultEnterKeyStyle"
+                latin:keySpec="!icon/enter_key|!code/key_enter"
+                latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="action"
+                latin:parentStyle="navigateMoreKeysStyle" />
+        </case>
+        <!-- keyboardTheme="LXXLight|LXXDark" -->
+        <default>
+            <key-style
+                latin:styleName="defaultEnterKeyStyle"
+                latin:keySpec="!icon/enter_key|!code/key_enter"
+                latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor|keepBackgroundAspectRatio"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="action"
+                latin:parentStyle="navigateMoreKeysStyle" />
+        </default>
+    </switch>
     <include latin:keyboardLayout="@xml/key_styles_actions" />
     <switch>
         <!-- Shift + Enter in textMultiLine field. -->
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index 43ee26b..b36ddf2 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -80,11 +80,24 @@
         latin:keyActionFlags="isRepeatable|noKeyPreview"
         latin:backgroundType="functional" />
     <!-- emojiKeyStyle must be defined before including @xml/key_syles_enter. -->
-    <key-style
-        latin:styleName="emojiKeyStyle"
-        latin:keySpec="!icon/emoji_action_key|!code/key_emoji"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="action" />
+    <switch>
+        <case latin:keyboardTheme="ICS|KLP">
+            <key-style
+                latin:styleName="emojiKeyStyle"
+                latin:keySpec="!icon/emoji_action_key|!code/key_emoji"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="action" />
+        </case>
+        <!-- keyboardTheme="LXXLight|LXXDark" -->
+        <default>
+            <key-style
+                latin:styleName="emojiKeyStyle"
+                latin:keySpec="!icon/emoji_action_key|!code/key_emoji"
+                latin:keyLabelFlags="keepBackgroundAspectRatio"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="action" />
+        </default>
+    </switch>
     <include
         latin:keyboardLayout="@xml/key_styles_enter" />
     <!-- TODO: Currently there is no way to specify icon alignment per theme. -->
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
index d6d01b8..564f465 100644
--- a/java/res/xml/key_styles_enter.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -212,13 +212,27 @@
         </default>
     </switch>
     <!-- Enter key style -->
-    <key-style
-        latin:styleName="defaultEnterKeyStyle"
-        latin:keySpec="!icon/enter_key|!code/key_enter"
-        latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="action"
-        latin:parentStyle="navigateMoreKeysStyle" />
+    <switch>
+        <case latin:keyboardTheme="ICS|KLP">
+            <key-style
+                latin:styleName="defaultEnterKeyStyle"
+                latin:keySpec="!icon/enter_key|!code/key_enter"
+                latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="action"
+                latin:parentStyle="navigateMoreKeysStyle" />
+        </case>
+        <!-- keyboardTheme="LXXLight|LXXDark" -->
+        <default>
+            <key-style
+                latin:styleName="defaultEnterKeyStyle"
+                latin:keySpec="!icon/enter_key|!code/key_enter"
+                latin:keyLabelFlags="preserveCase|autoXScale|followKeyLabelRatio|followFunctionalTextColor|keepBackgroundAspectRatio"
+                latin:keyActionFlags="noKeyPreview"
+                latin:backgroundType="action"
+                latin:parentStyle="navigateMoreKeysStyle" />
+        </default>
+    </switch>
     <include latin:keyboardLayout="@xml/key_styles_actions" />
     <switch>
         <!-- Shift + Enter in textMultiLine field. -->
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 8548544..86ea4c5 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -87,6 +87,7 @@
     private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x20000;
     private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x40000;
     private static final int LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR = 0x80000;
+    private static final int LABEL_FLAGS_KEEP_BACKGROUND_ASPECT_RATIO = 0x100000;
     private static final int LABEL_FLAGS_DISABLE_HINT_LABEL = 0x40000000;
     private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000;
 
@@ -697,6 +698,10 @@
         return (mLabelFlags & LABEL_FLAGS_AUTO_SCALE) == LABEL_FLAGS_AUTO_SCALE;
     }
 
+    public final boolean needsToKeepBackgroundAspectRatio(final int defaultFlags) {
+        return ((mLabelFlags | defaultFlags) & LABEL_FLAGS_KEEP_BACKGROUND_ASPECT_RATIO) != 0;
+    }
+
     private final boolean isShiftedLetterActivated() {
         return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0
                 && !TextUtils.isEmpty(mHintLabel);
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 075cd90..bb3cbb0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -340,11 +340,25 @@
     // Draw key background.
     protected void onDrawKeyBackground(final Key key, final Canvas canvas,
             final Drawable background) {
-        final Rect padding = mKeyBackgroundPadding;
-        final int bgWidth = key.getDrawWidth() + padding.left + padding.right;
-        final int bgHeight = key.getHeight() + padding.top + padding.bottom;
-        final int bgX = -padding.left;
-        final int bgY = -padding.top;
+        final int keyWidth = key.getDrawWidth();
+        final int keyHeight = key.getHeight();
+        final int bgWidth, bgHeight, bgX, bgY;
+        if (key.needsToKeepBackgroundAspectRatio(mDefaultKeyLabelFlags)) {
+            final int intrinsicWidth = background.getIntrinsicWidth();
+            final int intrinsicHeight = background.getIntrinsicHeight();
+            final float minScale = Math.min(
+                    keyWidth / (float)intrinsicWidth, keyHeight / (float)intrinsicHeight);
+            bgWidth = (int)(intrinsicWidth * minScale);
+            bgHeight = (int)(intrinsicHeight * minScale);
+            bgX = (keyWidth - bgWidth) / 2;
+            bgY = (keyHeight - bgHeight) / 2;
+        } else {
+            final Rect padding = mKeyBackgroundPadding;
+            bgWidth = keyWidth + padding.left + padding.right;
+            bgHeight = keyHeight + padding.top + padding.bottom;
+            bgX = -padding.left;
+            bgY = -padding.top;
+        }
         final Rect bounds = background.getBounds();
         if (bgWidth != bounds.right || bgHeight != bounds.bottom) {
             background.setBounds(0, 0, bgWidth, bgHeight);
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index 73c84cd..abcfff8 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -308,8 +308,8 @@
                 dividerWidth = 0;
             }
             final MoreKeySpec[] moreKeys = key.getMoreKeys();
-            mParams.setParameters(moreKeys.length, key.getMoreKeysColumnNumber(), keyWidth, rowHeight,
-                    key.getX() + key.getWidth() / 2, keyboard.mId.mWidth,
+            mParams.setParameters(moreKeys.length, key.getMoreKeysColumnNumber(), keyWidth,
+                    rowHeight, key.getX() + key.getWidth() / 2, keyboard.mId.mWidth,
                     key.isMoreKeysFixedColumn(), key.isMoreKeysFixedOrder(), dividerWidth);
         }
 
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
index cf58d6a..f614b22 100644
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
@@ -24,7 +24,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
-import android.view.inputmethod.CursorAnchorInfo;
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
@@ -154,13 +153,11 @@
      * {@code false} is the input method is finishing the full screen mode.
      */
     public void notifyFullScreenMode(final boolean fullScreenMode) {
-        final boolean currentFullScreenMode = mIsFullScreenMode;
-        if (!currentFullScreenMode && fullScreenMode) {
-            // Currently full screen mode is not supported.
-            // TODO: Support full screen mode.
-            mUiOperator.hideUi();
-        }
+        final boolean fullScreenModeChanged = (mIsFullScreenMode != fullScreenMode);
         mIsFullScreenMode = fullScreenMode;
+        if (fullScreenModeChanged) {
+            layoutLater();
+        }
     }
 
     /**
@@ -183,11 +180,6 @@
      * @param info the compatibility wrapper object for the received {@link CursorAnchorInfo}.
      */
     public void onUpdateCursorAnchorInfo(final CursorAnchorInfoCompatWrapper info) {
-        if (mIsFullScreenMode) {
-            // TODO: Consider to call InputConnection#requestCursorAnchorInfo to disable the
-            // event callback to suppress unnecessary event callbacks.
-            return;
-        }
         mCursorAnchorInfoWrapper = info;
         // Do not use layoutLater() to minimize the latency.
         layoutImmediately();
@@ -240,11 +232,6 @@
     }
 
     private void layoutMain() {
-        if (mIsFullScreenMode) {
-            cancelLayoutInternalUnexpectedly("Full screen mode isn't yet supported.");
-            return;
-        }
-
         if (mMode != MODE_COMMIT && mMode != MODE_ADD_TO_DICTIONARY) {
             if (mMode == MODE_NONE) {
                 cancelLayoutInternalExpectedly("Not ready for layouting.");
@@ -328,7 +315,7 @@
                 return;
             }
         } else {
-            if (!TextUtils.isEmpty(composingText)) {
+            if (!mIsFullScreenMode && !TextUtils.isEmpty(composingText)) {
                 // This is an unexpected case.
                 // TODO: Document this.
                 mUiOperator.hideUi();
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e4f39bb..86fe642 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -46,6 +46,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.CompletionInfo;
@@ -53,6 +54,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethod;
 import android.view.inputmethod.InputMethodSubtype;
+import android.widget.TextView;
 
 import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.annotations.UsedForTesting;
@@ -85,6 +87,7 @@
 import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.CapsModeUtils;
+import com.android.inputmethod.latin.utils.CursorAnchorInfoUtils;
 import com.android.inputmethod.latin.utils.CoordinateUtils;
 import com.android.inputmethod.latin.utils.DialogUtils;
 import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
@@ -152,6 +155,7 @@
     // TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
     private View mInputView;
     private SuggestionStripView mSuggestionStripView;
+    private TextView mExtractEditText;
 
     private RichInputMethodManager mRichImm;
     @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
@@ -713,11 +717,27 @@
 
     @Override
     public void onConfigurationChanged(final Configuration conf) {
-        final SettingsValues settingsValues = mSettings.getCurrent();
+        SettingsValues settingsValues = mSettings.getCurrent();
         if (settingsValues.mDisplayOrientation != conf.orientation) {
             mHandler.startOrientationChanging();
             mInputLogic.onOrientationChange(mSettings.getCurrent());
         }
+        if (settingsValues.mHasHardwareKeyboard != Settings.readHasHardwareKeyboard(conf)) {
+            // If the state of having a hardware keyboard changed, then we want to reload the
+            // settings to adjust for that.
+            // TODO: we should probably do this unconditionally here, rather than only when we
+            // have a change in hardware keyboard configuration.
+            loadSettings();
+            settingsValues = mSettings.getCurrent();
+            if (settingsValues.mHasHardwareKeyboard) {
+                // We call cleanupInternalStateForFinishInput() because it's the right thing to do;
+                // however, it seems at the moment the framework is passing us a seemingly valid
+                // but actually non-functional InputConnection object. So if this bug ever gets
+                // fixed we'll be able to remove the composition, but until it is this code is
+                // actually not doing much.
+                cleanupInternalStateForFinishInput();
+            }
+        }
         // TODO: Remove this test.
         if (!conf.locale.equals(mPersonalizationDictionaryUpdater.getLocale())) {
             refreshPersonalizationDictionarySession(settingsValues);
@@ -742,6 +762,49 @@
     }
 
     @Override
+    public void setExtractView(final View view) {
+        final TextView prevExtractEditText = mExtractEditText;
+        super.setExtractView(view);
+        TextView nextExtractEditText = null;
+        if (view != null) {
+            final View extractEditText = view.findViewById(android.R.id.inputExtractEditText);
+            if (extractEditText instanceof TextView) {
+                nextExtractEditText = (TextView)extractEditText;
+            }
+        }
+        if (prevExtractEditText == nextExtractEditText) {
+            return;
+        }
+        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK && prevExtractEditText != null) {
+            prevExtractEditText.getViewTreeObserver().removeOnPreDrawListener(
+                    mExtractTextViewPreDrawListener);
+        }
+        mExtractEditText = nextExtractEditText;
+        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK && mExtractEditText != null) {
+            mExtractEditText.getViewTreeObserver().addOnPreDrawListener(
+                    mExtractTextViewPreDrawListener);
+        }
+    }
+
+    private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
+            new ViewTreeObserver.OnPreDrawListener() {
+                @Override
+                public boolean onPreDraw() {
+                    onExtractTextViewPreDraw();
+                    return true;
+                }
+            };
+
+    private void onExtractTextViewPreDraw() {
+        if (!ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK || !isFullscreenMode()
+                || mExtractEditText == null) {
+            return;
+        }
+        final CursorAnchorInfo info = CursorAnchorInfoUtils.getCursorAnchorInfo(mExtractEditText);
+        mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
+    }
+
+    @Override
     public void setCandidatesView(final View view) {
         // To ensure that CandidatesView will never be set.
         return;
@@ -843,40 +906,52 @@
         // Note: This call should be done by InputMethodService?
         updateFullscreenMode();
 
-        // The app calling setText() has the effect of clearing the composing
-        // span, so we should reset our state unconditionally, even if restarting is true.
-        // We also tell the input logic about the combining rules for the current subtype, so
-        // it can adjust its combiners if needed.
-        mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
-                currentSettingsValues);
+        // ALERT: settings have not been reloaded and there is a chance they may be stale.
+        // In the practice, if it is, we should have gotten onConfigurationChanged so it should
+        // be fine, but this is horribly confusing and must be fixed AS SOON AS POSSIBLE.
 
-        // Note: the following does a round-trip IPC on the main thread: be careful
-        final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+        // In some cases the input connection has not been reset yet and we can't access it. In
+        // this case we will need to call loadKeyboard() later, when it's accessible, so that we
+        // can go into the correct mode, so we need to do some housekeeping here.
+        final boolean needToCallLoadKeyboardLater;
         final Suggest suggest = mInputLogic.mSuggest;
-        if (null != currentLocale && !currentLocale.equals(suggest.getLocale())) {
-            // TODO: Do this automatically.
-            resetSuggest();
-        }
+        if (!currentSettingsValues.mHasHardwareKeyboard) {
+            // The app calling setText() has the effect of clearing the composing
+            // span, so we should reset our state unconditionally, even if restarting is true.
+            // We also tell the input logic about the combining rules for the current subtype, so
+            // it can adjust its combiners if needed.
+            mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
+                    currentSettingsValues);
 
-        // TODO[IL]: Can the following be moved to InputLogic#startInput?
-        final boolean canReachInputConnection;
-        if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(
-                editorInfo.initialSelStart, editorInfo.initialSelEnd,
-                false /* shouldFinishComposition */)) {
-            // Sometimes, while rotating, for some reason the framework tells the app we are not
-            // connected to it and that means we can't refresh the cache. In this case, schedule a
-            // refresh later.
-            // We try resetting the caches up to 5 times before giving up.
-            mHandler.postResetCaches(isDifferentTextField, 5 /* remainingTries */);
-            // mLastSelection{Start,End} are reset later in this method, don't need to do it here
-            canReachInputConnection = false;
+            // Note: the following does a round-trip IPC on the main thread: be careful
+            final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+            if (null != currentLocale && !currentLocale.equals(suggest.getLocale())) {
+                // TODO: Do this automatically.
+                resetSuggest();
+            }
+
+            // TODO[IL]: Can the following be moved to InputLogic#startInput?
+            if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(
+                    editorInfo.initialSelStart, editorInfo.initialSelEnd,
+                    false /* shouldFinishComposition */)) {
+                // Sometimes, while rotating, for some reason the framework tells the app we are not
+                // connected to it and that means we can't refresh the cache. In this case, schedule
+                // a refresh later.
+                // We try resetting the caches up to 5 times before giving up.
+                mHandler.postResetCaches(isDifferentTextField, 5 /* remainingTries */);
+                // mLastSelection{Start,End} are reset later in this method, no need to do it here
+                needToCallLoadKeyboardLater = true;
+            } else {
+                // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
+                // effort to work around this bug.
+                mInputLogic.mConnection.tryFixLyingCursorPosition();
+                mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
+                        true /* shouldDelay */);
+                needToCallLoadKeyboardLater = false;
+            }
         } else {
-            // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
-            // effort to work around this bug.
-            mInputLogic.mConnection.tryFixLyingCursorPosition();
-            mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                    true /* shouldDelay */);
-            canReachInputConnection = true;
+            // If we have a hardware keyboard we don't need to call loadKeyboard later anyway.
+            needToCallLoadKeyboardLater = false;
         }
 
         if (isDifferentTextField ||
@@ -894,9 +969,9 @@
 
             switcher.loadKeyboard(editorInfo, currentSettingsValues, getCurrentAutoCapsState(),
                     getCurrentRecapitalizeState());
-            if (!canReachInputConnection) {
-                // If we can't reach the input connection, we will call loadKeyboard again later,
-                // so we need to save its state now. The call will be done in #retryResetCaches.
+            if (needToCallLoadKeyboardLater) {
+                // If we need to call loadKeyboard again later, we need to save its state now. The
+                // later call will be done in #retryResetCaches.
                 switcher.saveKeyboardState();
             }
         } else if (restarting) {
@@ -953,6 +1028,10 @@
 
     private void onFinishInputViewInternal(final boolean finishingInput) {
         super.onFinishInputView(finishingInput);
+        cleanupInternalStateForFinishInput();
+    }
+
+    private void cleanupInternalStateForFinishInput() {
         mKeyboardSwitcher.deallocateMemory();
         // Remove pending messages related to update suggestions
         mHandler.cancelUpdateSuggestionStrip();
@@ -972,13 +1051,12 @@
                     + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
         }
 
-        // If the keyboard is not visible, we don't need to do all the housekeeping work, as it
-        // will be reset when the keyboard shows up anyway.
-        // TODO: revisit this when LatinIME supports hardware keyboards.
-        // NOTE: the test harness subclasses LatinIME and overrides isInputViewShown().
-        // TODO: find a better way to simulate actual execution.
-        if (isInputViewShown() &&
-                mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd)) {
+        // This call happens when we have a hardware keyboard as well as when we don't. While we
+        // don't support hardware keyboards yet we should avoid doing the processing associated
+        // with cursor movement when we have a hardware keyboard since we are not in charge.
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if ((!settingsValues.mHasHardwareKeyboard || ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED)
+                && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd)) {
             mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
                     getCurrentRecapitalizeState());
         }
@@ -987,9 +1065,10 @@
     // We cannot mark this method as @Override until new SDK becomes publicly available.
     // @Override
     public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
-        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
-            mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
+        if (!ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK || isFullscreenMode()) {
+            return;
         }
+        mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
new file mode 100644
index 0000000..9dc0524
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.inputmethodservice.ExtractEditText;
+import android.inputmethodservice.InputMethodService;
+import android.text.Layout;
+import android.text.Spannable;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.widget.TextView;
+
+/**
+ * This class allows input methods to extract {@link CursorAnchorInfo} directly from the given
+ * {@link TextView}. This is useful and even necessary to support full-screen mode where the default
+ * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} event callback must be
+ * ignored because it reports the character locations of the target application rather than
+ * characters on {@link ExtractEditText}.
+ */
+public final class CursorAnchorInfoUtils {
+    private CursorAnchorInfoUtils() {
+        // This helper class is not instantiable.
+    }
+
+    private static boolean isPositionVisible(final View view, final float positionX,
+            final float positionY) {
+        final float[] position = new float[] { positionX, positionY };
+        View currentView = view;
+
+        while (currentView != null) {
+            if (currentView != view) {
+                // Local scroll is already taken into account in positionX/Y
+                position[0] -= currentView.getScrollX();
+                position[1] -= currentView.getScrollY();
+            }
+
+            if (position[0] < 0 || position[1] < 0 ||
+                    position[0] > currentView.getWidth() || position[1] > currentView.getHeight()) {
+                return false;
+            }
+
+            if (!currentView.getMatrix().isIdentity()) {
+                currentView.getMatrix().mapPoints(position);
+            }
+
+            position[0] += currentView.getLeft();
+            position[1] += currentView.getTop();
+
+            final ViewParent parent = currentView.getParent();
+            if (parent instanceof View) {
+                currentView = (View) parent;
+            } else {
+                // We've reached the ViewRoot, stop iterating
+                currentView = null;
+            }
+        }
+
+        // We've been able to walk up the view hierarchy and the position was never clipped
+        return true;
+    }
+
+    /**
+     * Returns {@link CursorAnchorInfo} from the given {@link TextView}.
+     * @param textView the target text view from which {@link CursorAnchorInfo} is to be extracted.
+     * @return the {@link CursorAnchorInfo} object based on the current layout. {@code null} if it
+     * is not feasible.
+     */
+    public static CursorAnchorInfo getCursorAnchorInfo(final TextView textView) {
+        Layout layout = textView.getLayout();
+        if (layout == null) {
+            return null;
+        }
+
+        final CursorAnchorInfo.Builder builder = new CursorAnchorInfo.Builder();
+
+        final int selectionStart = textView.getSelectionStart();
+        builder.setSelectionRange(selectionStart, textView.getSelectionEnd());
+
+        // Construct transformation matrix from view local coordinates to screen coordinates.
+        final Matrix viewToScreenMatrix = new Matrix(textView.getMatrix());
+        final int[] viewOriginInScreen = new int[2];
+        textView.getLocationOnScreen(viewOriginInScreen);
+        viewToScreenMatrix.postTranslate(viewOriginInScreen[0], viewOriginInScreen[1]);
+        builder.setMatrix(viewToScreenMatrix);
+
+        if (layout.getLineCount() == 0) {
+            return null;
+        }
+        final Rect lineBoundsWithoutOffset = new Rect();
+        final Rect lineBoundsWithOffset = new Rect();
+        layout.getLineBounds(0, lineBoundsWithoutOffset);
+        textView.getLineBounds(0, lineBoundsWithOffset);
+        final float viewportToContentHorizontalOffset = lineBoundsWithOffset.left
+                - lineBoundsWithoutOffset.left - textView.getScrollX();
+        final float viewportToContentVerticalOffset = lineBoundsWithOffset.top
+                - lineBoundsWithoutOffset.top - textView.getScrollY();
+
+        final CharSequence text = textView.getText();
+        if (text instanceof Spannable) {
+            // Here we assume that the composing text is marked as SPAN_COMPOSING flag. This is not
+            // necessarily true, but basically works.
+            int composingTextStart = text.length();
+            int composingTextEnd = 0;
+            final Spannable spannable = (Spannable) text;
+            final Object[] spans = spannable.getSpans(0, text.length(), Object.class);
+            for (Object span : spans) {
+                final int spanFlag = spannable.getSpanFlags(span);
+                if ((spanFlag & Spannable.SPAN_COMPOSING) != 0) {
+                    composingTextStart = Math.min(composingTextStart,
+                            spannable.getSpanStart(span));
+                    composingTextEnd = Math.max(composingTextEnd, spannable.getSpanEnd(span));
+                }
+            }
+
+            final boolean hasComposingText =
+                    (0 <= composingTextStart) && (composingTextStart < composingTextEnd);
+            if (hasComposingText) {
+                final CharSequence composingText = text.subSequence(composingTextStart,
+                        composingTextEnd);
+                builder.setComposingText(composingTextStart, composingText);
+
+                final int minLine = layout.getLineForOffset(composingTextStart);
+                final int maxLine = layout.getLineForOffset(composingTextEnd - 1);
+                for (int line = minLine; line <= maxLine; ++line) {
+                    final int lineStart = layout.getLineStart(line);
+                    final int lineEnd = layout.getLineEnd(line);
+                    final int offsetStart = Math.max(lineStart, composingTextStart);
+                    final int offsetEnd = Math.min(lineEnd, composingTextEnd);
+                    final boolean ltrLine =
+                            layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
+                    final float[] widths = new float[offsetEnd - offsetStart];
+                    layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths);
+                    final float top = layout.getLineTop(line);
+                    final float bottom = layout.getLineBottom(line);
+                    for (int offset = offsetStart; offset < offsetEnd; ++offset) {
+                        final float charWidth = widths[offset - offsetStart];
+                        final boolean isRtl = layout.isRtlCharAt(offset);
+                        final float primary = layout.getPrimaryHorizontal(offset);
+                        final float secondary = layout.getSecondaryHorizontal(offset);
+                        // TODO: This doesn't work perfectly for text with custom styles and TAB
+                        // chars.
+                        final float left;
+                        final float right;
+                        if (ltrLine) {
+                            if (isRtl) {
+                                left = secondary - charWidth;
+                                right = secondary;
+                            } else {
+                                left = primary;
+                                right = primary + charWidth;
+                            }
+                        } else {
+                            if (!isRtl) {
+                                left = secondary;
+                                right = secondary + charWidth;
+                            } else {
+                                left = primary - charWidth;
+                                right = primary;
+                            }
+                        }
+                        // TODO: Check top-right and bottom-left as well.
+                        final float localLeft = left + viewportToContentHorizontalOffset;
+                        final float localRight = right + viewportToContentHorizontalOffset;
+                        final float localTop = top + viewportToContentVerticalOffset;
+                        final float localBottom = bottom + viewportToContentVerticalOffset;
+                        final boolean isTopLeftVisible = isPositionVisible(textView,
+                                localLeft, localTop);
+                        final boolean isBottomRightVisible =
+                                isPositionVisible(textView, localRight, localBottom);
+                        int characterBoundsFlags = 0;
+                        if (isTopLeftVisible || isBottomRightVisible) {
+                            characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+                        }
+                        if (!isTopLeftVisible || !isTopLeftVisible) {
+                            characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+                        }
+                        if (isRtl) {
+                            characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+                        }
+                        // Here offset is the index in Java chars.
+                        builder.addCharacterBounds(offset, localLeft, localTop, localRight,
+                                localBottom, characterBoundsFlags);
+                    }
+                }
+            }
+        }
+
+        // Treat selectionStart as the insertion point.
+        if (0 <= selectionStart) {
+            final int offset = selectionStart;
+            final int line = layout.getLineForOffset(offset);
+            final float insertionMarkerX = layout.getPrimaryHorizontal(offset)
+                    + viewportToContentHorizontalOffset;
+            final float insertionMarkerTop = layout.getLineTop(line)
+                    + viewportToContentVerticalOffset;
+            final float insertionMarkerBaseline = layout.getLineBaseline(line)
+                    + viewportToContentVerticalOffset;
+            final float insertionMarkerBottom = layout.getLineBottom(line)
+                    + viewportToContentVerticalOffset;
+            final boolean isTopVisible =
+                    isPositionVisible(textView, insertionMarkerX, insertionMarkerTop);
+            final boolean isBottomVisible =
+                    isPositionVisible(textView, insertionMarkerX, insertionMarkerBottom);
+            int insertionMarkerFlags = 0;
+            if (isTopVisible || isBottomVisible) {
+                insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+            }
+            if (!isTopVisible || !isBottomVisible) {
+                insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+            }
+            if (layout.isRtlCharAt(offset)) {
+                insertionMarkerFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+            }
+            builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
+                    insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
+        }
+        return builder.build();
+    }
+}
diff --git a/tools/dicttool/NativeLib.mk b/tools/dicttool/NativeLib.mk
index 028025d..ffb32ed 100644
--- a/tools/dicttool/NativeLib.mk
+++ b/tools/dicttool/NativeLib.mk
@@ -34,7 +34,6 @@
 LOCAL_MULTILIB := 64
 endif #HOST_JDK_IS_64BIT_VERSION
 
-LOCAL_CLANG := true
 # For C++11
 LOCAL_CFLAGS += -std=c++11