Merge "[ML7] Have multiple DictionaryGroup instances in facilitator"
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-hdpi/keyboard_key_feedback_background_lxx_dark.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_dark.9.png
index 306e455..93f300a 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_dark.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_light.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_light.9.png
index 867f551..e7c516a 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_light.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_dark.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
index b3e6ee7..b56fcf9 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_light.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_light.9.png
index 827f80f..32005c3 100644
--- a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_light.9.png
+++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_lxx_light.9.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-mdpi/keyboard_key_feedback_background_lxx_dark.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_dark.9.png
index 4f6731f..1a7dd34 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_dark.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_light.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_light.9.png
index 14da5f9..268863e 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_light.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_dark.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
index 9bca991..08d67ef 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_light.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_light.9.png
index 14f4b5f..d0e46b1 100644
--- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_light.9.png
+++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_lxx_light.9.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-xhdpi/keyboard_key_feedback_background_lxx_dark.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_dark.9.png
index 654ccd1..f934e33 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_dark.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_light.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_light.9.png
index c566e3d..f70599e 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_light.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
index f5f613c..fa5ddf2 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_light.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_light.9.png
index 35aaa7d..0da8919 100644
--- a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_light.9.png
+++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_lxx_light.9.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-xxhdpi/keyboard_key_feedback_background_lxx_dark.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_dark.9.png
index f5215bc..1b92455 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_dark.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_light.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_light.9.png
index b565ff0..3effde3 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_light.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
index 6d931ed..55d6330 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_light.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_light.9.png
index 2c5ced9..4523be9 100644
--- a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_light.9.png
+++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_lxx_light.9.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..0e08b6b
--- /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..fb10523
--- /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..fd88668
--- /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..ab1bfad
--- /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-land/config.xml b/java/res/values-land/config.xml
index 34d6d4e..d36f6a0 100644
--- a/java/res/values-land/config.xml
+++ b/java/res/values-land/config.xml
@@ -40,16 +40,22 @@
     <!-- config_more_keys_keyboard_key_height x -0.5 -->
     <dimen name="config_more_keys_keyboard_vertical_correction_holo">-22.4dp</dimen>
     <dimen name="config_key_preview_offset_holo">1.6dp</dimen>
-
+    <dimen name="config_key_preview_height_holo">80dp</dimen>
+    <dimen name="config_key_preview_offset_lxx">43.6dp</dimen>
+    <dimen name="config_key_preview_height_lxx">122dp</dimen>
     <fraction name="config_key_preview_text_ratio">90%</fraction>
-    <fraction name="config_key_letter_ratio">65%</fraction>
+    <fraction name="config_key_letter_ratio_holo">65%</fraction>
+    <fraction name="config_key_letter_ratio_lxx">65%</fraction>
     <fraction name="config_key_large_letter_ratio_holo">74%</fraction>
     <fraction name="config_key_large_letter_ratio_lxx">90%</fraction>
-    <fraction name="config_key_label_ratio">40%</fraction>
-    <fraction name="config_key_hint_letter_ratio">30%</fraction>
+    <fraction name="config_key_label_ratio_holo">40%</fraction>
+    <fraction name="config_key_label_ratio_lxx">40%</fraction>
+    <fraction name="config_key_hint_letter_ratio_holo">30%</fraction>
+    <fraction name="config_key_hint_letter_ratio_lxx">30%</fraction>
     <fraction name="config_key_hint_label_ratio_holo">52%</fraction>
     <fraction name="config_key_hint_label_ratio_lxx">30%</fraction>
-    <fraction name="config_key_shifted_letter_hint_ratio">40%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_holo">40%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_lxx">40%</fraction>
     <fraction name="config_language_on_spacebar_text_ratio">40.000%</fraction>
 
     <!-- For 5-row keyboard -->
diff --git a/java/res/values-land/keyboard-heights.xml b/java/res/values-land/keyboard-heights.xml
index d57f96b..02d8b14 100644
--- a/java/res/values-land/keyboard-heights.xml
+++ b/java/res/values-land/keyboard-heights.xml
@@ -33,5 +33,7 @@
     <!-- Preferable keyboard height in absolute scale: 45.0mm -->
         <!-- Xoom -->
         <item>HARDWARE=stingray,265.4378</item>
+        <!-- Volantis -->
+        <item>HARDWARE=flounder,272.0</item>
     </string-array>
 </resources>
diff --git a/java/res/values-sw600dp-land/config.xml b/java/res/values-sw600dp-land/config.xml
index c238b2c..d33af2e 100644
--- a/java/res/values-sw600dp-land/config.xml
+++ b/java/res/values-sw600dp-land/config.xml
@@ -23,7 +23,7 @@
     <!-- Preferable keyboard height in absolute scale: 45.0mm -->
     <!-- This config_default_keyboard_height value should match with keyboard-heights.xml -->
     <dimen name="config_default_keyboard_height">283.5dp</dimen>
-    <fraction name="config_min_keyboard_height">45%p</fraction>
+    <fraction name="config_min_keyboard_height">40%p</fraction>
 
     <dimen name="config_more_keys_keyboard_key_height">81.9dp</dimen>
 
@@ -32,14 +32,18 @@
     <fraction name="config_key_vertical_gap_holo">4.5%p</fraction>
     <fraction name="config_key_horizontal_gap_holo">0.9%p</fraction>
 
-    <fraction name="config_key_letter_ratio">50%</fraction>
+    <fraction name="config_key_letter_ratio_holo">50%</fraction>
+    <fraction name="config_key_letter_ratio_lxx">50%</fraction>
     <fraction name="config_key_large_letter_ratio_holo">48%</fraction>
     <fraction name="config_key_large_letter_ratio_lxx">60%</fraction>
-    <fraction name="config_key_label_ratio">32%</fraction>
-    <fraction name="config_key_hint_letter_ratio">23%</fraction>
+    <fraction name="config_key_label_ratio_holo">32%</fraction>
+    <fraction name="config_key_label_ratio_lxx">32%</fraction>
+    <fraction name="config_key_hint_letter_ratio_holo">23%</fraction>
+    <fraction name="config_key_hint_letter_ratio_lxx">23%</fraction>
     <fraction name="config_key_hint_label_ratio_holo">34%</fraction>
     <fraction name="config_key_hint_label_ratio_lxx">20%</fraction>
-    <fraction name="config_key_shifted_letter_hint_ratio">29%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_holo">29%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_lxx">29%</fraction>
     <fraction name="config_language_on_spacebar_text_ratio">30.0%</fraction>
     <dimen name="config_key_shifted_letter_hint_padding">4dp</dimen>
 
diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml
index 3c489bb..44e0d06 100644
--- a/java/res/values-sw600dp/config.xml
+++ b/java/res/values-sw600dp/config.xml
@@ -40,18 +40,20 @@
     <fraction name="config_key_horizontal_gap_holo">1.565%p</fraction>
     <!-- config_more_keys_keyboard_key_height x -0.5 -->
     <dimen name="config_more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen>
-    <dimen name="config_key_preview_offset_holo">8.0dp</dimen>
 
-    <dimen name="config_key_preview_height">94.5dp</dimen>
     <fraction name="config_key_preview_text_ratio">50%</fraction>
-    <fraction name="config_key_letter_ratio">42%</fraction>
+    <fraction name="config_key_letter_ratio_holo">42%</fraction>
+    <fraction name="config_key_letter_ratio_lxx">50%</fraction>
     <fraction name="config_key_large_letter_ratio_holo">45%</fraction>
     <fraction name="config_key_large_letter_ratio_lxx">60%</fraction>
-    <fraction name="config_key_label_ratio">25%</fraction>
-    <fraction name="config_key_hint_letter_ratio">23%</fraction>
+    <fraction name="config_key_label_ratio_holo">25%</fraction>
+    <fraction name="config_key_label_ratio_lxx">32%</fraction>
+    <fraction name="config_key_hint_letter_ratio_holo">23%</fraction>
+    <fraction name="config_key_hint_letter_ratio_lxx">23%</fraction>
     <fraction name="config_key_hint_label_ratio_holo">28%</fraction>
     <fraction name="config_key_hint_label_ratio_lxx">20%</fraction>
-    <fraction name="config_key_shifted_letter_hint_ratio">22%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_holo">22%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_lxx">22%</fraction>
     <fraction name="config_language_on_spacebar_text_ratio">28.0%</fraction>
     <dimen name="config_key_hint_letter_padding">3dp</dimen>
     <dimen name="config_key_shifted_letter_hint_padding">3dp</dimen>
diff --git a/java/res/values-sw768dp-land/config.xml b/java/res/values-sw768dp-land/config.xml
index 587a3c1..fdb95c6 100644
--- a/java/res/values-sw768dp-land/config.xml
+++ b/java/res/values-sw768dp-land/config.xml
@@ -23,25 +23,27 @@
     <!-- Preferable keyboard height in absolute scale: 58.0mm -->
     <!-- This config_default_keyboard_height value should match with keyboard-heights.xml -->
     <dimen name="config_default_keyboard_height">365.4dp</dimen>
-    <fraction name="config_min_keyboard_height">45%p</fraction>
+    <fraction name="config_min_keyboard_height">35%p</fraction>
 
     <fraction name="config_keyboard_top_padding_holo">1.896%p</fraction>
     <fraction name="config_keyboard_bottom_padding_holo">0.0%p</fraction>
     <fraction name="config_key_vertical_gap_holo">3.690%p</fraction>
     <fraction name="config_key_horizontal_gap_holo">1.030%p</fraction>
-    <dimen name="config_key_preview_offset_holo">8.0dp</dimen>
 
     <dimen name="config_more_keys_keyboard_key_height">81.9dp</dimen>
 
-    <dimen name="config_key_preview_height">107.1dp</dimen>
-    <fraction name="config_key_letter_ratio">43%</fraction>
+    <fraction name="config_key_letter_ratio_holo">43%</fraction>
+    <fraction name="config_key_letter_ratio_lxx">50%</fraction>
     <fraction name="config_key_large_letter_ratio_holo">42%</fraction>
     <fraction name="config_key_large_letter_ratio_lxx">60%</fraction>
-    <fraction name="config_key_label_ratio">28%</fraction>
-    <fraction name="config_key_hint_letter_ratio">23%</fraction>
+    <fraction name="config_key_label_ratio_holo">28%</fraction>
+    <fraction name="config_key_label_ratio_lxx">32%</fraction>
+    <fraction name="config_key_hint_letter_ratio_holo">23%</fraction>
+    <fraction name="config_key_hint_letter_ratio_lxx">23%</fraction>
     <fraction name="config_key_hint_label_ratio_holo">28%</fraction>
     <fraction name="config_key_hint_label_ratio_lxx">20%</fraction>
-    <fraction name="config_key_shifted_letter_hint_ratio">24%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_holo">24%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_lxx">24%</fraction>
     <fraction name="config_language_on_spacebar_text_ratio">24.00%</fraction>
 
     <!-- For 5-row keyboard -->
diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml
index f573c40..13be6be 100644
--- a/java/res/values-sw768dp/config.xml
+++ b/java/res/values-sw768dp/config.xml
@@ -32,7 +32,6 @@
     <fraction name="config_key_horizontal_gap_holo">1.066%p</fraction>
     <!-- config_more_keys_keyboard_key_height x -0.5 -->
     <dimen name="config_more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen>
-    <dimen name="config_key_preview_offset_holo">8.0dp</dimen>
 
     <dimen name="config_more_keys_keyboard_key_height">63.0dp</dimen>
     <dimen name="config_more_keys_keyboard_key_horizontal_padding">12dp</dimen>
@@ -40,16 +39,19 @@
     <!-- config_more_keys_keyboard_key_height x 1.2 -->
     <dimen name="config_more_keys_keyboard_slide_allowance">98.3dp</dimen>
 
-    <dimen name="config_key_preview_height">94.5dp</dimen>
     <fraction name="config_key_preview_text_ratio">50%</fraction>
-    <fraction name="config_key_letter_ratio">40%</fraction>
+    <fraction name="config_key_letter_ratio_holo">40%</fraction>
+    <fraction name="config_key_letter_ratio_lxx">50%</fraction>
     <fraction name="config_key_large_letter_ratio_holo">42%</fraction>
     <fraction name="config_key_large_letter_ratio_lxx">60%</fraction>
-    <fraction name="config_key_label_ratio">28%</fraction>
-    <fraction name="config_key_hint_letter_ratio">23%</fraction>
+    <fraction name="config_key_label_ratio_holo">28%</fraction>
+    <fraction name="config_key_label_ratio_lxx">32%</fraction>
+    <fraction name="config_key_hint_letter_ratio_holo">23%</fraction>
+    <fraction name="config_key_hint_letter_ratio_lxx">23%</fraction>
     <fraction name="config_key_hint_label_ratio_holo">28%</fraction>
     <fraction name="config_key_hint_label_ratio_lxx">20%</fraction>
-    <fraction name="config_key_shifted_letter_hint_ratio">26%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_holo">26%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_lxx">26%</fraction>
     <fraction name="config_language_on_spacebar_text_ratio">29.03%</fraction>
     <dimen name="config_key_hint_letter_padding">3dp</dimen>
     <dimen name="config_key_shifted_letter_hint_padding">3dp</dimen>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index f1253b4..8ee859b 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -483,6 +483,8 @@
         <attr name="localeCode" format="string" />
         <attr name="languageCode" format="string" />
         <attr name="countryCode" format="string" />
+        <!-- Enable split keyboard layout. Disabled by default. -->
+        <attr name="isSplitLayout" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="Keyboard_KeyStyle">
@@ -514,6 +516,8 @@
         <attr name="elementKeyboard" format="reference"/>
         <!-- Enable proximity characters correction. Disabled by default. -->
         <attr name="enableProximityCharsCorrection" format="boolean" />
+        <!-- Indicates if the keyboard layout supports being split or not. false by default -->
+        <attr name="supportsSplitLayout" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="KeyboardLayoutSet_Feature">
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index af3b589..40760f6 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -43,17 +43,22 @@
     <!-- config_more_keys_keyboard_key_height x -0.5 -->
     <dimen name="config_more_keys_keyboard_vertical_correction_holo">-26.4dp</dimen>
     <dimen name="config_key_preview_offset_holo">8.0dp</dimen>
-
-    <dimen name="config_key_preview_height">80dp</dimen>
+    <dimen name="config_key_preview_height_holo">80dp</dimen>
+    <dimen name="config_key_preview_offset_lxx">50.0dp</dimen>
+    <dimen name="config_key_preview_height_lxx">122dp</dimen>
     <fraction name="config_key_preview_text_ratio">82%</fraction>
-    <fraction name="config_key_letter_ratio">55%</fraction>
+    <fraction name="config_key_letter_ratio_holo">55%</fraction>
+    <fraction name="config_key_letter_ratio_lxx">55%</fraction>
     <fraction name="config_key_large_letter_ratio_holo">65%</fraction>
     <fraction name="config_key_large_letter_ratio_lxx">90%</fraction>
-    <fraction name="config_key_label_ratio">34%</fraction>
-    <fraction name="config_key_hint_letter_ratio">25%</fraction>
+    <fraction name="config_key_label_ratio_holo">34%</fraction>
+    <fraction name="config_key_label_ratio_lxx">34%</fraction>
+    <fraction name="config_key_hint_letter_ratio_holo">25%</fraction>
+    <fraction name="config_key_hint_letter_ratio_lxx">25%</fraction>
     <fraction name="config_key_hint_label_ratio_holo">44%</fraction>
     <fraction name="config_key_hint_label_ratio_lxx">30%</fraction>
-    <fraction name="config_key_shifted_letter_hint_ratio">35%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_holo">35%</fraction>
+    <fraction name="config_key_shifted_letter_hint_ratio_lxx">35%</fraction>
     <fraction name="config_language_on_spacebar_text_ratio">33.735%</fraction>
     <dimen name="config_key_hint_letter_padding">1dp</dimen>
     <dimen name="config_key_shifted_letter_hint_padding">2dp</dimen>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 8b8b28f..e5341f6 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -36,18 +36,20 @@
     <!-- Option to control whether or not to show a popup with a larger font on each key press. -->
     <string name="popup_on_keypress">Popup on keypress</string>
 
-    <!-- Settings screen title for input preferences [CHAR LIMIT=33]-->
-    <string name="settings_screen_input">Input preferences</string>
-    <!-- Settings screen title for appearance preferences [CHAR LIMIT=33] -->
-    <string name="settings_screen_appearances">Appearance</string>
-    <!-- Settings screen title for multi lingual options [CHAR_LIMIT=33] -->
-    <string name="settings_screen_multi_lingual">Multi lingual options</string>
+    <!-- Settings screen title for preferences [CHAR LIMIT=33]-->
+    <string name="settings_screen_preferences">Preferences</string>
+    <!-- Settings screen title for appearance & layouts preferences [CHAR LIMIT=33] -->
+    <string name="settings_screen_appearance">Appearance &amp; layouts</string>
+    <!-- Settings screen title for multilingual options [CHAR_LIMIT=33] -->
+    <string name="settings_screen_multilingual">Multilingual options</string>
     <!-- Settings screen title for gesture typing preferences [CHAR_LIMIT=33] -->
-    <string name="settings_screen_gesture">Gesture typing preferences</string>
+    <string name="settings_screen_gesture">Gesture Typing</string>
     <!-- Settings screen title for text correction options [CHAR_LIMIT=33] -->
     <string name="settings_screen_correction">Text correction</string>
     <!-- Settings screen title for advanced settings [CHAR LIMIT=33] -->
     <string name="settings_screen_advanced">Advanced</string>
+    <!-- Settings screen title for keyboard theme settings [CHAR LIMIT=33] -->
+    <string name="settings_screen_theme">Theme</string>
 
     <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
     <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
@@ -152,14 +154,14 @@
     <string name="configure_input_method">Configure input methods</string>
 
     <!-- Title for input language selection screen -->
-    <string name="language_selection_title">Input languages</string>
+    <string name="language_selection_title">Languages</string>
 
     <!-- Title for the 'Help & feedback' settings fragment which shows a help page and has a button
          for submitting feedback. [CHAR LIMIT=35] -->
     <string name="help_and_feedback">Help &amp; feedback</string>
 
     <!-- Preference for input language selection -->
-    <string name="select_language">Input languages</string>
+    <string name="select_language">Languages</string>
 
     <!-- Add to dictionary hint -->
     <string name="hint_add_to_dictionary">Touch again to save</string>
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index becaddd..110f6b7 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -37,12 +37,6 @@
         <!-- This keyBackground is needed to run unit tests based on {@link InputTestBase}. -->
         <!-- TODO: Apply default {@link KeyboardTheme} to {@link InputTestBase} and remove this. -->
         <item name="keyBackground">@drawable/btn_keyboard_key_klp</item>
-        <item name="keyLetterSize">@fraction/config_key_letter_ratio</item>
-        <item name="keyLargeLetterRatio">@fraction/config_key_large_letter_ratio_holo</item>
-        <item name="keyLabelSize">@fraction/config_key_label_ratio</item>
-        <item name="keyHintLetterRatio">@fraction/config_key_hint_letter_ratio</item>
-        <item name="keyHintLabelRatio">@fraction/config_key_hint_label_ratio_holo</item>
-        <item name="keyShiftedLetterHintRatio">@fraction/config_key_shifted_letter_hint_ratio</item>
         <item name="keyTypeface">normal</item>
         <!-- A negative value to disable key text shadow layer. -->
         <item name="keyTextShadowRadius">-1.0</item>
@@ -81,7 +75,6 @@
         <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
         <item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item>
         <item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item>
-        <item name="keyPreviewHeight">@dimen/config_key_preview_height</item>
         <!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. -->
         <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
         <item name="moreKeysKeyboardLayout">@layout/more_keys_keyboard</item>
diff --git a/java/res/values/themes-holo.xml b/java/res/values/themes-holo.xml
index cb3ad7a..9f1bd2f 100644
--- a/java/res/values/themes-holo.xml
+++ b/java/res/values/themes-holo.xml
@@ -25,6 +25,10 @@
         parent="KeyboardView"
     >
         <item name="keyTypeface">bold</item>
+        <item name="keyLetterSize">@fraction/config_key_letter_ratio_holo</item>
+        <item name="keyLabelSize">@fraction/config_key_label_ratio_holo</item>
+        <item name="keyHintLetterRatio">@fraction/config_key_hint_letter_ratio_holo</item>
+        <item name="keyShiftedLetterHintRatio">@fraction/config_key_shifted_letter_hint_ratio_holo</item>
         <item name="keyLargeLetterRatio">@fraction/config_key_large_letter_ratio_holo</item>
         <item name="keyLabelOffCenterRatio">-175%</item>
         <item name="keyHintLabelRatio">@fraction/config_key_hint_label_ratio_holo</item>
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 9e656dd..bfbac0a 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -60,6 +60,7 @@
         parent="KeyboardView.ICS"
     >
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
+        <item name="keyPreviewHeight">@dimen/config_key_preview_height_holo</item>
         <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
         <item name="keyPreviewShowUpAnimator">@anim/key_preview_show_up_holo</item>
         <item name="keyPreviewDismissAnimator">@anim/key_preview_dismiss_holo</item>
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index c6319bc..36b1fc1 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -60,6 +60,7 @@
         parent="KeyboardView.KLP"
     >
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_klp</item>
+        <item name="keyPreviewHeight">@dimen/config_key_preview_height_holo</item>
         <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
         <item name="keyPreviewShowUpAnimator">@anim/key_preview_show_up_holo</item>
         <item name="keyPreviewDismissAnimator">@anim/key_preview_dismiss_holo</item>
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index 5b26813..67f94f3 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -60,7 +60,8 @@
     >
         <item name="moreKeysKeyboardForActionLayout">@layout/more_keys_keyboard_for_action_lxx</item>
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_lxx_dark</item>
-        <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
+        <item name="keyPreviewHeight">@dimen/config_key_preview_height_lxx</item>
+        <item name="keyPreviewOffset">@dimen/config_key_preview_offset_lxx</item>
         <item name="keyPreviewShowUpAnimator">@anim/key_preview_show_up_lxx</item>
         <item name="keyPreviewDismissAnimator">@anim/key_preview_dismiss_lxx</item>
         <item name="gestureFloatingPreviewTextColor">@color/auto_correct_color_lxx_dark</item>
diff --git a/java/res/values/themes-lxx-light.xml b/java/res/values/themes-lxx-light.xml
index f607807..be817f4 100644
--- a/java/res/values/themes-lxx-light.xml
+++ b/java/res/values/themes-lxx-light.xml
@@ -60,7 +60,8 @@
     >
         <item name="moreKeysKeyboardForActionLayout">@layout/more_keys_keyboard_for_action_lxx</item>
         <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_lxx_light</item>
-        <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
+        <item name="keyPreviewHeight">@dimen/config_key_preview_height_lxx</item>
+        <item name="keyPreviewOffset">@dimen/config_key_preview_offset_lxx</item>
         <item name="keyPreviewShowUpAnimator">@anim/key_preview_show_up_lxx</item>
         <item name="keyPreviewDismissAnimator">@anim/key_preview_dismiss_lxx</item>
         <item name="gestureFloatingPreviewTextColor">@color/auto_correct_color_lxx_light</item>
diff --git a/java/res/values/themes-lxx.xml b/java/res/values/themes-lxx.xml
index 1c33cd6..c721888 100644
--- a/java/res/values/themes-lxx.xml
+++ b/java/res/values/themes-lxx.xml
@@ -25,6 +25,10 @@
         parent="KeyboardView"
     >
         <item name="keyTypeface">normal</item>
+        <item name="keyLetterSize">@fraction/config_key_letter_ratio_lxx</item>
+        <item name="keyLabelSize">@fraction/config_key_label_ratio_lxx</item>
+        <item name="keyHintLetterRatio">@fraction/config_key_hint_letter_ratio_lxx</item>
+        <item name="keyShiftedLetterHintRatio">@fraction/config_key_shifted_letter_hint_ratio_lxx</item>
         <item name="keyLargeLetterRatio">@fraction/config_key_large_letter_ratio_lxx</item>
         <item name="keyLabelOffCenterRatio">-80%</item>
         <item name="keyHintLabelRatio">@fraction/config_key_hint_label_ratio_lxx</item>
diff --git a/java/res/xml-sw600dp-land/key_space_3kw.xml b/java/res/xml-sw600dp-land/key_space_3kw.xml
new file mode 100644
index 0000000..47c4e48
--- /dev/null
+++ b/java/res/xml-sw600dp-land/key_space_3kw.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <!-- TODO: Consolidate the layout specification between protrait and landscape.
+         Ideally just the keyWidth should be different -->
+    <switch>
+        <!-- fa: Perisan
+             kn: Kannada
+             ne: Nepali
+             te: Telugu -->
+        <case
+            latin:languageCode="fa|kn|ne|te"
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="7.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageCode="fa|kn|ne|te"
+            latin:languageSwitchKeyEnabled="false"
+        >
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="14.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="14.0%p" />
+        </case>
+        <!-- languageSwitchKeyEnabled="false" -->
+        <default>
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="21.0%p" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml-sw600dp-land/row_qwerty4.xml b/java/res/xml-sw600dp-land/row_qwerty4.xml
new file mode 100644
index 0000000..0fdb5c6
--- /dev/null
+++ b/java/res/xml-sw600dp-land/row_qwerty4.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <switch>
+        <!-- Split the 4th row for split layouts -->
+        <case
+            latin:isSplitLayout="true"
+        >
+            <Row
+                latin:keyWidth="7.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyboardLayout="@xml/key_space_3kw"
+                    latin:backgroundType="normal" />
+                <Spacer
+                    latin:keyWidth="28.0%p" />
+                <Key
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="21.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </case>
+        <default>
+            <Row
+                latin:keyWidth="9.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyXPos="19.0%p"
+                    latin:keyboardLayout="@xml/key_space_7kw"
+                    latin:backgroundType="normal" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml-sw600dp-land/rows_qwerty.xml b/java/res/xml-sw600dp-land/rows_qwerty.xml
new file mode 100644
index 0000000..b580dcf
--- /dev/null
+++ b/java/res/xml-sw600dp-land/rows_qwerty.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <!-- First row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the first row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_left5"
+                    latin:keyWidth="7.0%p" />
+                <Spacer
+                    latin:keyWidth="20.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_right5"
+                    latin:keyWidth="7.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the first row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <!-- Second row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the second row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_left5"
+                    latin:keyXPos="4.0%p"
+                    latin:keyWidth="7.0%p" />
+                <Spacer
+                    latin:keyWidth="23.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_right4"
+                    latin:keyWidth="7.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the second row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2"
+                    latin:keyXPos="4.5%p"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <!-- Third row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the third row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_left4"
+                    latin:keyWidth="7.0%p" />
+                <Spacer
+                    latin:keyWidth="17.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_right3"
+                    latin:keyWidth="7.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="7.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the third row -->
+            <default>
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3"
+                    latin:keyWidth="9.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <!-- Fourth row -->
+    <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/key_space_3kw.xml b/java/res/xml-sw600dp/key_space_3kw.xml
new file mode 100644
index 0000000..9932d34
--- /dev/null
+++ b/java/res/xml-sw600dp/key_space_3kw.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <switch>
+        <!-- fa: Perisan
+             kn: Kannada
+             ne: Nepali
+             te: Telugu -->
+        <case
+            latin:languageCode="fa|kn|ne|te"
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="8.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageCode="fa|kn|ne|te"
+            latin:languageSwitchKeyEnabled="false"
+        >
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="16.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="16.0%p" />
+        </case>
+        <!-- languageSwitchKeyEnabled="false" -->
+        <default>
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="24.0%p" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml
index ed7150d..bcfd2cb 100644
--- a/java/res/xml-sw600dp/row_qwerty4.xml
+++ b/java/res/xml-sw600dp/row_qwerty4.xml
@@ -21,23 +21,54 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Row
-        latin:keyWidth="9.0%p"
-        latin:backgroundType="functional"
-    >
-        <Key
-            latin:keyStyle="toSymbolKeyStyle"
-            latin:keyWidth="10.0%p" />
-        <include
-            latin:keyboardLayout="@xml/key_comma" />
-        <!-- Space key. -->
-        <include
-            latin:keyXPos="19.0%p"
-            latin:keyboardLayout="@xml/key_space_7kw"
-            latin:backgroundType="normal" />
-        <include
-            latin:keyboardLayout="@xml/key_period" />
-        <include
-            latin:keyboardLayout="@xml/key_emoji" />
-    </Row>
+    <switch>
+        <!-- Split the 4th row for split layouts -->
+        <case
+            latin:isSplitLayout="true"
+        >
+            <Row
+                latin:keyWidth="8.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyboardLayout="@xml/key_space_3kw"
+                    latin:backgroundType="normal" />
+                <Spacer
+                    latin:keyWidth="20.0%p" />
+                <Key
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="24.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </case>
+        <default>
+            <Row
+                latin:keyWidth="9.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyXPos="19.0%p"
+                    latin:keyboardLayout="@xml/key_space_7kw"
+                    latin:backgroundType="normal" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </default>
+    </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/rows_qwerty.xml b/java/res/xml-sw600dp/rows_qwerty.xml
index 58ba1d7..51df4b0 100644
--- a/java/res/xml-sw600dp/rows_qwerty.xml
+++ b/java/res/xml-sw600dp/rows_qwerty.xml
@@ -23,39 +23,114 @@
 >
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
-    <Row
-        latin:keyWidth="9.0%p"
-    >
-        <include
-            latin:keyboardLayout="@xml/rowkeys_qwerty1" />
-        <Key
-            latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillRight" />
+    <!-- TODO: Consolidate the layout specification between protrait and landscape.
+         Ideally just the keyWidth should be different and the spacer should adjust to fill
+         the available space. -->
+    <!-- First row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the first row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_left5"
+                    latin:keyWidth="8.0%p" />
+                <Spacer
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_right5"
+                    latin:keyWidth="8.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the first row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
     </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-    >
-        <include
-            latin:keyboardLayout="@xml/rowkeys_qwerty2"
-            latin:keyXPos="4.5%p" />
-        <Key
-            latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillRight" />
+    <!-- Second row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the second row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_left5"
+                    latin:keyXPos="4.0%p"
+                    latin:keyWidth="8.0%p" />
+                <Spacer
+                    latin:keyWidth="14.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_right4"
+                    latin:keyWidth="8.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the second row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2"
+                    latin:keyXPos="4.5%p"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
     </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-    >
-        <Key
-            latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="10.0%p" />
-        <include
-            latin:keyboardLayout="@xml/rowkeys_qwerty3" />
-        <include
-            latin:keyboardLayout="@xml/keys_exclamation_question" />
-        <Key
-            latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillRight" />
+    <!-- Third row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the third row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_left4"
+                    latin:keyWidth="8.0%p" />
+                <Spacer
+                    latin:keyWidth="8.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_right3"
+                    latin:keyWidth="8.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="8.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the third row -->
+            <default>
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3"
+                    latin:keyWidth="9.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
     </Row>
+    <!-- Fourth row -->
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
 </merge>
diff --git a/java/res/xml/keyboard_layout_set_qwerty.xml b/java/res/xml/keyboard_layout_set_qwerty.xml
index 8215170..1aa6f01 100644
--- a/java/res/xml/keyboard_layout_set_qwerty.xml
+++ b/java/res/xml/keyboard_layout_set_qwerty.xml
@@ -23,7 +23,8 @@
     <Element
         latin:elementName="alphabet"
         latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:enableProximityCharsCorrection="true" />
+        latin:enableProximityCharsCorrection="true"
+        latin:supportsSplitLayout="false" />
     <Element
         latin:elementName="symbols"
         latin:elementKeyboard="@xml/kbd_symbols" />
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index ba285de..c14cd64 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -19,17 +19,17 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
     android:key="english_ime_settings">
     <PreferenceScreen
-        android:fragment="com.android.inputmethod.latin.settings.InputSettingsFragment"
-        android:title="@string/settings_screen_input"
-        android:key="screen_input" />
+        android:fragment="com.android.inputmethod.latin.settings.PreferencesSettingsFragment"
+        android:title="@string/settings_screen_preferences"
+        android:key="screen_preferences" />
     <PreferenceScreen
-        android:fragment="com.android.inputmethod.latin.settings.ThemeSettingsFragment"
-        android:title="@string/keyboard_theme"
-        android:key="screen_theme" />
+        android:fragment="com.android.inputmethod.latin.settings.AppearanceSettingsFragment"
+        android:title="@string/settings_screen_appearance"
+        android:key="screen_appearance" />
     <PreferenceScreen
         android:fragment="com.android.inputmethod.latin.settings.MultiLingualSettingsFragment"
-        android:title="@string/settings_screen_multi_lingual"
-        android:key="screen_multi_lingual" />
+        android:title="@string/settings_screen_multilingual"
+        android:key="screen_multilingual" />
     <PreferenceScreen
         android:fragment="com.android.inputmethod.latin.settings.GestureSettingsFragment"
         android:title="@string/settings_screen_gesture"
diff --git a/java/res/xml/prefs_screen_appearance.xml b/java/res/xml/prefs_screen_appearance.xml
new file mode 100644
index 0000000..7719c05
--- /dev/null
+++ b/java/res/xml/prefs_screen_appearance.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:key="screen_appearance"
+    android:title="@string/settings_screen_appearance">
+    <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.ThemeSettingsFragment"
+        android:key="screen_theme"
+        android:title="@string/settings_screen_theme" />
+    <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.CustomInputStyleSettingsFragment"
+        android:key="custom_input_styles"
+        android:title="@string/custom_input_styles_title" />
+</PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_multi_lingual.xml b/java/res/xml/prefs_screen_multilingual.xml
similarity index 81%
rename from java/res/xml/prefs_screen_multi_lingual.xml
rename to java/res/xml/prefs_screen_multilingual.xml
index 937d439..07a4b70 100644
--- a/java/res/xml/prefs_screen_multi_lingual.xml
+++ b/java/res/xml/prefs_screen_multilingual.xml
@@ -16,8 +16,8 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:title="@string/settings_screen_multi_lingual"
-    android:key="screen_multi_lingual">
+    android:title="@string/settings_screen_multilingual"
+    android:key="screen_multilingual">
     <CheckBoxPreference
         android:key="pref_show_language_switch_key"
         android:title="@string/show_language_switch_key"
@@ -31,8 +31,4 @@
         android:summary="@string/include_other_imes_in_language_switch_list_summary"
         android:defaultValue="false"
         android:persistent="true" />
-    <PreferenceScreen
-        android:fragment="com.android.inputmethod.latin.settings.CustomInputStyleSettingsFragment"
-        android:key="custom_input_styles"
-        android:title="@string/custom_input_styles_title" />
 </PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_input.xml b/java/res/xml/prefs_screen_preferences.xml
similarity index 97%
rename from java/res/xml/prefs_screen_input.xml
rename to java/res/xml/prefs_screen_preferences.xml
index 7704e3f..101edc8 100644
--- a/java/res/xml/prefs_screen_input.xml
+++ b/java/res/xml/prefs_screen_preferences.xml
@@ -17,7 +17,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
-    android:title="@string/settings_screen_input">
+    android:title="@string/settings_screen_preferences">
     <CheckBoxPreference
         android:key="auto_cap"
         android:title="@string/auto_cap"
diff --git a/java/res/xml/prefs_screen_theme.xml b/java/res/xml/prefs_screen_theme.xml
index b49f0be..677a6ea 100644
--- a/java/res/xml/prefs_screen_theme.xml
+++ b/java/res/xml/prefs_screen_theme.xml
@@ -17,7 +17,7 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
-    android:title="@string/keyboard_theme"
+    android:title="@string/settings_screen_theme"
     android:key="screen_theme">
     <!-- Keyboard theme list will be populated programmatically here. -->
 </PreferenceScreen>
diff --git a/java/res/xml/rowkeys_qwerty1.xml b/java/res/xml/rowkeys_qwerty1.xml
index 8f3b160..b8e4a4c 100644
--- a/java/res/xml/rowkeys_qwerty1.xml
+++ b/java/res/xml/rowkeys_qwerty1.xml
@@ -21,53 +21,10 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Key
-        latin:keySpec="!text/keyspec_q"
-        latin:keyHintLabel="1"
-        latin:additionalMoreKeys="1"
-        latin:moreKeys="!text/morekeys_q" />
-    <Key
-        latin:keySpec="!text/keyspec_w"
-        latin:keyHintLabel="2"
-        latin:additionalMoreKeys="2"
-        latin:moreKeys="!text/morekeys_w" />
-    <Key
-        latin:keySpec="e"
-        latin:keyHintLabel="3"
-        latin:additionalMoreKeys="3"
-        latin:moreKeys="!text/morekeys_e" />
-    <Key
-        latin:keySpec="r"
-        latin:keyHintLabel="4"
-        latin:additionalMoreKeys="4"
-        latin:moreKeys="!text/morekeys_r" />
-    <Key
-        latin:keySpec="t"
-        latin:keyHintLabel="5"
-        latin:additionalMoreKeys="5"
-        latin:moreKeys="!text/morekeys_t" />
-    <Key
-        latin:keySpec="!text/keyspec_y"
-        latin:keyHintLabel="6"
-        latin:additionalMoreKeys="6"
-        latin:moreKeys="!text/morekeys_y" />
-    <Key
-        latin:keySpec="u"
-        latin:keyHintLabel="7"
-        latin:additionalMoreKeys="7"
-        latin:moreKeys="!text/morekeys_u" />
-    <Key
-        latin:keySpec="i"
-        latin:keyHintLabel="8"
-        latin:additionalMoreKeys="8"
-        latin:moreKeys="!text/morekeys_i" />
-    <Key
-        latin:keySpec="o"
-        latin:keyHintLabel="9"
-        latin:additionalMoreKeys="9"
-        latin:moreKeys="!text/morekeys_o" />
-    <Key
-        latin:keySpec="p"
-        latin:keyHintLabel="0"
-        latin:additionalMoreKeys="0" />
+    <!-- q,w,e,r,t -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty1_left5" />
+    <!-- y,u,i,o,p -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty1_right5" />
 </merge>
diff --git a/java/res/xml/rowkeys_qwerty1_left5.xml b/java/res/xml/rowkeys_qwerty1_left5.xml
new file mode 100644
index 0000000..ff9f1b2
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty1_left5.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="!text/keyspec_q"
+        latin:keyHintLabel="1"
+        latin:additionalMoreKeys="1"
+        latin:moreKeys="!text/morekeys_q" />
+    <Key
+        latin:keySpec="!text/keyspec_w"
+        latin:keyHintLabel="2"
+        latin:additionalMoreKeys="2"
+        latin:moreKeys="!text/morekeys_w" />
+    <Key
+        latin:keySpec="e"
+        latin:keyHintLabel="3"
+        latin:additionalMoreKeys="3"
+        latin:moreKeys="!text/morekeys_e" />
+    <Key
+        latin:keySpec="r"
+        latin:keyHintLabel="4"
+        latin:additionalMoreKeys="4"
+        latin:moreKeys="!text/morekeys_r" />
+    <Key
+        latin:keySpec="t"
+        latin:keyHintLabel="5"
+        latin:additionalMoreKeys="5"
+        latin:moreKeys="!text/morekeys_t" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty1_right5.xml b/java/res/xml/rowkeys_qwerty1_right5.xml
new file mode 100644
index 0000000..2b3cae2
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty1_right5.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="!text/keyspec_y"
+        latin:keyHintLabel="6"
+        latin:additionalMoreKeys="6"
+        latin:moreKeys="!text/morekeys_y" />
+    <Key
+        latin:keySpec="u"
+        latin:keyHintLabel="7"
+        latin:additionalMoreKeys="7"
+        latin:moreKeys="!text/morekeys_u" />
+    <Key
+        latin:keySpec="i"
+        latin:keyHintLabel="8"
+        latin:additionalMoreKeys="8"
+        latin:moreKeys="!text/morekeys_i" />
+    <Key
+        latin:keySpec="o"
+        latin:keyHintLabel="9"
+        latin:additionalMoreKeys="9"
+        latin:moreKeys="!text/morekeys_o" />
+    <Key
+        latin:keySpec="p"
+        latin:keyHintLabel="0"
+        latin:additionalMoreKeys="0" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty2.xml b/java/res/xml/rowkeys_qwerty2.xml
index 4077bea..550db3b 100644
--- a/java/res/xml/rowkeys_qwerty2.xml
+++ b/java/res/xml/rowkeys_qwerty2.xml
@@ -21,30 +21,10 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Key
-        latin:keySpec="a"
-        latin:moreKeys="!text/morekeys_a" />
-    <Key
-        latin:keySpec="s"
-        latin:moreKeys="!text/morekeys_s" />
-    <Key
-        latin:keySpec="d"
-        latin:moreKeys="!text/morekeys_d" />
-    <Key
-        latin:keySpec="f" />
-    <Key
-        latin:keySpec="g"
-        latin:moreKeys="!text/morekeys_g" />
-    <Key
-        latin:keySpec="h"
-        latin:moreKeys="!text/morekeys_h" />
-    <Key
-        latin:keySpec="j"
-        latin:moreKeys="!text/morekeys_j" />
-    <Key
-        latin:keySpec="k"
-        latin:moreKeys="!text/morekeys_k" />
-    <Key
-        latin:keySpec="l"
-        latin:moreKeys="!text/morekeys_l" />
+    <!-- a,s,d,f,g -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty2_left5" />
+    <!-- h,j,k,l -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty2_right4" />
 </merge>
diff --git a/java/res/xml/rowkeys_qwerty2_left5.xml b/java/res/xml/rowkeys_qwerty2_left5.xml
new file mode 100644
index 0000000..1803bf2
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty2_left5.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="a"
+        latin:moreKeys="!text/morekeys_a" />
+    <Key
+        latin:keySpec="s"
+        latin:moreKeys="!text/morekeys_s" />
+    <Key
+        latin:keySpec="d"
+        latin:moreKeys="!text/morekeys_d" />
+    <Key
+        latin:keySpec="f" />
+    <Key
+        latin:keySpec="g"
+        latin:moreKeys="!text/morekeys_g" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty2_right4.xml b/java/res/xml/rowkeys_qwerty2_right4.xml
new file mode 100644
index 0000000..99936b7
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty2_right4.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="h"
+        latin:moreKeys="!text/morekeys_h" />
+    <Key
+        latin:keySpec="j"
+        latin:moreKeys="!text/morekeys_j" />
+    <Key
+        latin:keySpec="k"
+        latin:moreKeys="!text/morekeys_k" />
+    <Key
+        latin:keySpec="l"
+        latin:moreKeys="!text/morekeys_l" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty3.xml b/java/res/xml/rowkeys_qwerty3.xml
index 8562003..7a523f1 100644
--- a/java/res/xml/rowkeys_qwerty3.xml
+++ b/java/res/xml/rowkeys_qwerty3.xml
@@ -21,23 +21,10 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Key
-        latin:keySpec="z"
-        latin:moreKeys="!text/morekeys_z" />
-    <Key
-        latin:keySpec="!text/keyspec_x"
-        latin:moreKeys="!text/morekeys_x" />
-    <Key
-        latin:keySpec="c"
-        latin:moreKeys="!text/morekeys_c" />
-    <Key
-        latin:keySpec="v"
-        latin:moreKeys="!text/morekeys_v" />
-    <Key
-        latin:keySpec="b" />
-    <Key
-        latin:keySpec="n"
-        latin:moreKeys="!text/morekeys_n" />
-    <Key
-        latin:keySpec="m" />
+    <!-- z,x,c,v -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty3_left4" />
+    <!-- b,n,m -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty3_right3" />
 </merge>
diff --git a/java/res/xml/rowkeys_qwerty3_left4.xml b/java/res/xml/rowkeys_qwerty3_left4.xml
new file mode 100644
index 0000000..6043c3b
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty3_left4.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="z"
+        latin:moreKeys="!text/morekeys_z" />
+    <Key
+        latin:keySpec="!text/keyspec_x"
+        latin:moreKeys="!text/morekeys_x" />
+    <Key
+        latin:keySpec="c"
+        latin:moreKeys="!text/morekeys_c" />
+    <Key
+        latin:keySpec="v"
+        latin:moreKeys="!text/morekeys_v" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty3_right3.xml b/java/res/xml/rowkeys_qwerty3_right3.xml
new file mode 100644
index 0000000..f699103
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty3_right3.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="b" />
+    <Key
+        latin:keySpec="n"
+        latin:moreKeys="!text/morekeys_n" />
+    <Key
+        latin:keySpec="m" />
+</merge>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 538e515..43c6144 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -73,10 +73,12 @@
     public final boolean mLanguageSwitchKeyEnabled;
     public final String mCustomActionLabel;
     public final boolean mHasShortcutKey;
+    public final boolean mIsSplitLayout;
 
     private final int mHashCode;
 
-    public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params) {
+    public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params,
+        boolean isSplitLayout) {
         mSubtype = params.mSubtype;
         mLocale = SubtypeLocaleUtils.getSubtypeLocale(mSubtype);
         mWidth = params.mKeyboardWidth;
@@ -89,6 +91,7 @@
         mCustomActionLabel = (mEditorInfo.actionLabel != null)
                 ? mEditorInfo.actionLabel.toString() : null;
         mHasShortcutKey = params.mVoiceInputKeyEnabled;
+        mIsSplitLayout = isSplitLayout;
 
         mHashCode = computeHashCode(this);
     }
@@ -108,7 +111,8 @@
                 id.mCustomActionLabel,
                 id.navigateNext(),
                 id.navigatePrevious(),
-                id.mSubtype
+                id.mSubtype,
+                id.mIsSplitLayout
         });
     }
 
@@ -128,7 +132,8 @@
                 && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)
                 && other.navigateNext() == navigateNext()
                 && other.navigatePrevious() == navigatePrevious()
-                && other.mSubtype.equals(mSubtype);
+                && other.mSubtype.equals(mSubtype)
+                && other.mIsSplitLayout == mIsSplitLayout;
     }
 
     private static boolean isAlphabetKeyboard(final int elementId) {
@@ -175,7 +180,7 @@
 
     @Override
     public String toString() {
-        return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s]",
+        return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]",
                 elementIdToName(mElementId),
                 mLocale, mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
                 mWidth, mHeight,
@@ -187,7 +192,8 @@
                 (passwordInput() ? " passwordInput" : ""),
                 (mHasShortcutKey ? " hasShortcutKey" : ""),
                 (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
-                (isMultiLine() ? " isMultiLine" : "")
+                (isMultiLine() ? " isMultiLine" : ""),
+                (mIsSplitLayout ? " isSplitLayout" : "")
         );
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 3f43673..1dbecdc 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -96,6 +96,7 @@
     private static final class ElementParams {
         int mKeyboardXmlId;
         boolean mProximityCharsCorrectionEnabled;
+        boolean mSupportsSplitLayout;
         public ElementParams() {}
     }
 
@@ -168,7 +169,10 @@
         // attribute in a keyboard_layout_set XML file.  Also each keyboard layout XML resource is
         // specified as an elementKeyboard attribute in the file.
         // The KeyboardId is an internal key for a Keyboard object.
-        final KeyboardId id = new KeyboardId(keyboardLayoutSetElementId, mParams);
+
+        // TODO: AND mSupportsSplitLayout with the user preference that forces a split.
+        final KeyboardId id = new KeyboardId(keyboardLayoutSetElementId, mParams,
+                elementParams.mSupportsSplitLayout);
         try {
             return getKeyboard(elementParams, id);
         } catch (final RuntimeException e) {
@@ -376,6 +380,8 @@
                 elementParams.mProximityCharsCorrectionEnabled = a.getBoolean(
                         R.styleable.KeyboardLayoutSet_Element_enableProximityCharsCorrection,
                         false);
+                elementParams.mSupportsSplitLayout = a.getBoolean(
+                        R.styleable.KeyboardLayoutSet_Element_supportsSplitLayout, false);
                 mParams.mKeyboardLayoutSetElementIdToParamsMap.put(elementName, elementParams);
             } finally {
                 a.recycle();
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 28f2dcf..d36c199 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.preference.PreferenceManager;
 import android.util.Log;
@@ -257,13 +256,12 @@
     }
 
     public void onToggleEmojiKeyboard() {
-        if (mKeyboardLayoutSet == null) {
-            return;
-        }
-        if (isShowingEmojiPalettes()) {
-            setAlphabetKeyboard();
-        } else {
+        if (mKeyboardLayoutSet == null || !isShowingEmojiPalettes()) {
+            mLatinIME.startShowingInputView();
             setEmojiKeyboard();
+        } else {
+            mLatinIME.stopShowingInputView();
+            setAlphabetKeyboard();
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index 782e182..50a6e48 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -49,6 +49,7 @@
      * {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled}
      */
     final public boolean mDisableGestureFloatingPreviewText;
+    final public boolean mIsGeneralTextInput;
     final private int mInputType;
     final private EditorInfo mEditorInfo;
     final private String mPackageNameForPrivateImeOptions;
@@ -84,6 +85,7 @@
             mShouldInsertSpacesAutomatically = false;
             mShouldShowVoiceInputKey = false;
             mDisableGestureFloatingPreviewText = false;
+            mIsGeneralTextInput = false;
             return;
         }
         // inputClass == InputType.TYPE_CLASS_TEXT
@@ -128,6 +130,15 @@
                 || (!flagAutoCorrect && !flagMultiLine);
 
         mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
+
+        // If we come here, inputClass is always TYPE_CLASS_TEXT
+        mIsGeneralTextInput = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS != variation
+                && InputType.TYPE_TEXT_VARIATION_PASSWORD != variation
+                && InputType.TYPE_TEXT_VARIATION_PHONETIC != variation
+                && InputType.TYPE_TEXT_VARIATION_URI != variation
+                && InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD != variation
+                && InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != variation
+                && InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD != variation;
     }
 
     public boolean isTypeNull() {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 66396d0..4757820 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -52,7 +52,6 @@
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethod;
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.TextView;
 
@@ -87,8 +86,8 @@
 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.CursorAnchorInfoUtils;
 import com.android.inputmethod.latin.utils.DialogUtils;
 import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
 import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
@@ -163,6 +162,9 @@
     private final SubtypeState mSubtypeState = new SubtypeState();
     private final SpecialKeyDetector mSpecialKeyDetector;
     private StatsUtilsManager mStatsUtilsManager;
+    // Working variable for {@link #startShowingInputView()} and
+    // {@link #onEvaluateInputViewShown()}.
+    private boolean mIsExecutingStartShowingInputView;
 
     // Object for reacting to adding/removing a dictionary pack.
     private final BroadcastReceiver mDictionaryPackInstallReceiver =
@@ -1192,22 +1194,24 @@
         outInsets.visibleTopInsets = visibleTopY;
     }
 
-    @Override
-    public boolean onEvaluateInputViewShown() {
-        // Always show {@link InputView}.
-        return true;
+    public void startShowingInputView() {
+        mIsExecutingStartShowingInputView = true;
+        // This {@link #showWindow(boolean)} will eventually call back
+        // {@link #onEvaluateInputViewShown()}.
+        showWindow(true /* showInput */);
+        mIsExecutingStartShowingInputView = false;
+    }
+
+    public void stopShowingInputView() {
+        showWindow(false /* showInput */);
     }
 
     @Override
-    public boolean onShowInputRequested(final int flags, final boolean configChange) {
-        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)}.
+    public boolean onEvaluateInputViewShown() {
+        if (mIsExecutingStartShowingInputView) {
             return true;
         }
-        return super.onShowInputRequested(flags, configChange);
+        return super.onEvaluateInputViewShown();
     }
 
     @Override
@@ -1226,9 +1230,8 @@
             // hack for now.  Let's get rid of this once the framework gets fixed.
             final EditorInfo ei = getCurrentInputEditorInfo();
             return !(ei != null && ((ei.imeOptions & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0));
-        } else {
-            return false;
         }
+        return false;
     }
 
     @Override
@@ -1274,9 +1277,8 @@
         if (null == keyboard) {
             return CoordinateUtils.newCoordinateArray(codePoints.length,
                     Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
-        } else {
-            return keyboard.getCoordinates(codePoints);
         }
+        return keyboard.getCoordinates(codePoints);
     }
 
     // Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is
diff --git a/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java
new file mode 100644
index 0000000..f5e4d33
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java
@@ -0,0 +1,41 @@
+/*
+ * 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.settings;
+
+import android.os.Bundle;
+
+import com.android.inputmethod.latin.R;
+
+
+/**
+ * "Appearance" settings sub screen.
+ */
+public final class AppearanceSettingsFragment extends SubScreenFragment {
+    @Override
+    public void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_appearance);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        CustomInputStyleSettingsFragment.updateCustomInputStylesSummary(
+                findPreference(Settings.PREF_CUSTOM_INPUT_STYLES));
+        ThemeSettingsFragment.updateKeyboardThemeSummary(findPreference(Settings.SCREEN_THEME));
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
index d53a616..9bc3986 100644
--- a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
@@ -31,6 +31,7 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.support.v4.view.ViewCompat;
+import android.text.TextUtils;
 import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -396,6 +397,25 @@
         // Empty constructor for fragment generation.
     }
 
+    static void updateCustomInputStylesSummary(final Preference pref) {
+        // When we are called from the Settings application but we are not already running, some
+        // singleton and utility classes may not have been initialized.  We have to call
+        // initialization method of these classes here. See {@link LatinIME#onCreate()}.
+        SubtypeLocaleUtils.init(pref.getContext());
+
+        final Resources res = pref.getContext().getResources();
+        final SharedPreferences prefs = pref.getSharedPreferences();
+        final String prefSubtype = Settings.readPrefAdditionalSubtypes(prefs, res);
+        final InputMethodSubtype[] subtypes =
+                AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype);
+        final ArrayList<String> subtypeNames = new ArrayList<>();
+        for (final InputMethodSubtype subtype : subtypes) {
+            subtypeNames.add(SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype));
+        }
+        // TODO: A delimiter of custom input styles should be localized.
+        pref.setSummary(TextUtils.join(", ", subtypeNames));
+    }
+
     @Override
     public void onCreate(final Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
index fcdd393..b073c50 100644
--- a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
@@ -16,66 +16,27 @@
 
 package com.android.inputmethod.latin.settings;
 
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
 import android.os.Bundle;
-import android.preference.PreferenceScreen;
-import android.text.TextUtils;
-import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.ArrayList;
 
 /**
- * "Multi lingual options" settings sub screen.
+ * "Multilingual options" settings sub screen.
  *
  * This settings sub screen handles the following input preferences.
  * - Language switch key
  * - Switch to other input methods
- * - Custom input styles
  */
 public final class MultiLingualSettingsFragment extends SubScreenFragment {
     @Override
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.prefs_screen_multi_lingual);
-
-        final Context context = getActivity();
-
-        // When we are called from the Settings application but we are not already running, some
-        // singleton and utility classes may not have been initialized.  We have to call
-        // initialization method of these classes here. See {@link LatinIME#onCreate()}.
-        SubtypeLocaleUtils.init(context);
-
+        addPreferencesFromResource(R.xml.prefs_screen_multilingual);
         if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) {
             removePreference(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY);
             removePreference(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST);
         }
     }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        updateCustomInputStylesSummary();
-    }
-
-    private void updateCustomInputStylesSummary() {
-        final SharedPreferences prefs = getSharedPreferences();
-        final Resources res = getResources();
-        final PreferenceScreen customInputStyles =
-                (PreferenceScreen)findPreference(Settings.PREF_CUSTOM_INPUT_STYLES);
-        final String prefSubtype = Settings.readPrefAdditionalSubtypes(prefs, res);
-        final InputMethodSubtype[] subtypes =
-                AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype);
-        final ArrayList<String> subtypeNames = new ArrayList<>();
-        for (final InputMethodSubtype subtype : subtypes) {
-            subtypeNames.add(SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype));
-        }
-        // TODO: A delimiter of custom input styles should be localized.
-        customInputStyles.setSummary(TextUtils.join(", ", subtypeNames));
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
similarity index 95%
rename from java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java
rename to java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
index f459d68..49db2bd 100644
--- a/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
@@ -27,7 +27,7 @@
 import com.android.inputmethod.latin.SubtypeSwitcher;
 
 /**
- * "Input preferences" settings sub screen.
+ * "Preferences" settings sub screen.
  *
  * This settings sub screen handles the following input preferences.
  * - Auto-capitalization
@@ -37,11 +37,11 @@
  * - Popup on keypress
  * - Voice input key
  */
-public final class InputSettingsFragment extends SubScreenFragment {
+public final class PreferencesSettingsFragment extends SubScreenFragment {
     @Override
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.prefs_screen_input);
+        addPreferencesFromResource(R.xml.prefs_screen_preferences);
 
         final Resources res = getResources();
         final Context context = getActivity();
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 3c7a991..0de2d88 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -42,9 +42,10 @@
 public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = Settings.class.getSimpleName();
     // Settings screens
-    public static final String SCREEN_INPUT = "screen_input";
+    public static final String SCREEN_PREFERENCES = "screen_preferences";
+    public static final String SCREEN_APPEARANCE = "screen_appearance";
     public static final String SCREEN_THEME = "screen_theme";
-    public static final String SCREEN_MULTI_LINGUAL = "screen_multi_lingual";
+    public static final String SCREEN_MULTILINGUAL = "screen_multilingual";
     public static final String SCREEN_GESTURE = "screen_gesture";
     public static final String SCREEN_CORRECTION = "screen_correction";
     public static final String SCREEN_ADVANCED = "screen_advanced";
@@ -69,6 +70,9 @@
             "pref_key_use_double_space_period";
     public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE =
             "pref_key_block_potentially_offensive";
+    // No multilingual options in Android L and above for now.
+    public static final boolean SHOW_MULTILINGUAL_SETTINGS =
+            BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
     public static final boolean ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS =
             BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
     public static final boolean HAS_UI_TO_ACCEPT_TYPED_WORD =
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index ff74958..4fc1738 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.preference.Preference;
 import android.preference.PreferenceScreen;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -46,12 +47,10 @@
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
         preferenceScreen.setTitle(
                 ApplicationUtils.getActivityTitleResId(getActivity(), SettingsActivity.class));
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        ThemeSettingsFragment.updateKeyboardThemeSummary(findPreference(Settings.SCREEN_THEME));
+        if (!Settings.SHOW_MULTILINGUAL_SETTINGS) {
+            final Preference multilingualOptions = findPreference(Settings.SCREEN_MULTILINGUAL);
+            preferenceScreen.removePreference(multilingualOptions);
+        }
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index c891a2e..270b22a 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -149,7 +149,8 @@
                 ? Settings.readShowsLanguageSwitchKey(prefs) : true /* forcibly */;
         mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
         mUsePersonalizedDicts = prefs.getBoolean(Settings.PREF_KEY_USE_PERSONALIZED_DICTS, true);
-        mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true);
+        mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true)
+                && inputAttributes.mIsGeneralTextInput;
         mBlockPotentiallyOffensive = Settings.readBlockPotentiallyOffensive(prefs, res);
         mAutoCorrectEnabled = Settings.readAutoCorrectEnabled(autoCorrectionThresholdRawValue, res);
         mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
diff --git a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
index 08f5b0b..c2167a7 100644
--- a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
@@ -19,12 +19,13 @@
 import com.android.inputmethod.dictionarypack.DictionarySettingsFragment;
 import com.android.inputmethod.latin.about.AboutPreferences;
 import com.android.inputmethod.latin.settings.AdvancedSettingsFragment;
+import com.android.inputmethod.latin.settings.AppearanceSettingsFragment;
 import com.android.inputmethod.latin.settings.CorrectionSettingsFragment;
 import com.android.inputmethod.latin.settings.CustomInputStyleSettingsFragment;
 import com.android.inputmethod.latin.settings.DebugSettingsFragment;
 import com.android.inputmethod.latin.settings.GestureSettingsFragment;
-import com.android.inputmethod.latin.settings.InputSettingsFragment;
 import com.android.inputmethod.latin.settings.MultiLingualSettingsFragment;
+import com.android.inputmethod.latin.settings.PreferencesSettingsFragment;
 import com.android.inputmethod.latin.settings.SettingsFragment;
 import com.android.inputmethod.latin.settings.ThemeSettingsFragment;
 import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
@@ -40,7 +41,8 @@
     static {
         sLatinImeFragments.add(DictionarySettingsFragment.class.getName());
         sLatinImeFragments.add(AboutPreferences.class.getName());
-        sLatinImeFragments.add(InputSettingsFragment.class.getName());
+        sLatinImeFragments.add(PreferencesSettingsFragment.class.getName());
+        sLatinImeFragments.add(AppearanceSettingsFragment.class.getName());
         sLatinImeFragments.add(ThemeSettingsFragment.class.getName());
         sLatinImeFragments.add(MultiLingualSettingsFragment.class.getName());
         sLatinImeFragments.add(CustomInputStyleSettingsFragment.class.getName());
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 3970963..ec61783 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -105,7 +105,7 @@
     }
 
     // Init for root with prevWordIds which is used for n-gram
-    void initAsRoot(const int rootPtNodeArrayPos, const int *const prevWordIds) {
+    void initAsRoot(const int rootPtNodeArrayPos, const WordIdArrayView prevWordIds) {
         mIsCachedForNextSuggestion = false;
         mDicNodeProperties.init(rootPtNodeArrayPos, prevWordIds);
         mDicNodeState.init();
@@ -115,12 +115,11 @@
     // Init for root with previous word
     void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
         mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
-        int newPrevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+        WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> newPrevWordIds;
         newPrevWordIds[0] = dicNode->mDicNodeProperties.getWordId();
-        for (size_t i = 1; i < NELEMS(newPrevWordIds); ++i) {
-            newPrevWordIds[i] = dicNode->getPrevWordIds()[i - 1];
-        }
-        mDicNodeProperties.init(rootPtNodeArrayPos, newPrevWordIds);
+        dicNode->getPrevWordIds().limit(newPrevWordIds.size() - 1)
+                .copyToArray(&newPrevWordIds, 1 /* offset */);
+        mDicNodeProperties.init(rootPtNodeArrayPos, WordIdArrayView::fromArray(newPrevWordIds));
         mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
                 dicNode->mDicNodeProperties.getDepth());
         PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
@@ -203,8 +202,7 @@
         return mDicNodeProperties.getWordId();
     }
 
-    // TODO: Use view class to return word id array.
-    const int *getPrevWordIds() const {
+    const WordIdArrayView getPrevWordIds() const {
         return mDicNodeProperties.getPrevWordIds();
     }
 
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index fe5fe84..7d2898b 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -28,7 +28,7 @@
 
 /* static */ void DicNodeUtils::initAsRoot(
         const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-        const int *const prevWordIds, DicNode *const newRootDicNode) {
+        const WordIdArrayView prevWordIds, DicNode *const newRootDicNode) {
     newRootDicNode->initAsRoot(dictionaryStructurePolicy->getRootPosition(), prevWordIds);
 }
 
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.h b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
index 961a1c2..b891a84 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
@@ -18,6 +18,7 @@
 #define LATINIME_DIC_NODE_UTILS_H
 
 #include "defines.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -30,7 +31,7 @@
  public:
     static void initAsRoot(
             const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-            const int *const prevWordIds, DicNode *const newRootDicNode);
+            const WordIdArrayView prevWordIds, DicNode *const newRootDicNode);
     static void initAsRootWithPreviousWord(
             const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
             const DicNode *const prevWordLastDicNode, DicNode *const newRootDicNode);
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
index 6a1b842..cecfc7a 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
@@ -18,8 +18,10 @@
 #define LATINIME_DIC_NODE_PROPERTIES_H
 
 #include <cstdint>
+#include <cstdlib>
 
 #include "defines.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -36,23 +38,23 @@
 
     // Should be called only once per DicNode is initialized.
     void init(const int childrenPos, const int nodeCodePoint, const int wordId,
-            const uint16_t depth, const uint16_t leavingDepth, const int *const prevWordIds) {
+            const uint16_t depth, const uint16_t leavingDepth, const WordIdArrayView prevWordIds) {
         mChildrenPtNodeArrayPos = childrenPos;
         mDicNodeCodePoint = nodeCodePoint;
         mWordId = wordId;
         mDepth = depth;
         mLeavingDepth = leavingDepth;
-        memmove(mPrevWordIds, prevWordIds, sizeof(mPrevWordIds));
+        prevWordIds.copyToArray(&mPrevWordIds, 0 /* offset */);
     }
 
     // Init for root with prevWordsPtNodePos which is used for n-gram
-    void init(const int rootPtNodeArrayPos, const int *const prevWordIds) {
+    void init(const int rootPtNodeArrayPos, const WordIdArrayView prevWordIds) {
         mChildrenPtNodeArrayPos = rootPtNodeArrayPos;
         mDicNodeCodePoint = NOT_A_CODE_POINT;
         mWordId = NOT_A_WORD_ID;
         mDepth = 0;
         mLeavingDepth = 0;
-        memmove(mPrevWordIds, prevWordIds, sizeof(mPrevWordIds));
+        prevWordIds.copyToArray(&mPrevWordIds, 0 /* offset */);
     }
 
     void initByCopy(const DicNodeProperties *const dicNodeProp) {
@@ -61,7 +63,8 @@
         mWordId = dicNodeProp->mWordId;
         mDepth = dicNodeProp->mDepth;
         mLeavingDepth = dicNodeProp->mLeavingDepth;
-        memmove(mPrevWordIds, dicNodeProp->mPrevWordIds, sizeof(mPrevWordIds));
+        WordIdArrayView::fromArray(dicNodeProp->mPrevWordIds)
+                .copyToArray(&mPrevWordIds, 0 /* offset */);
     }
 
     // Init as passing child
@@ -71,7 +74,8 @@
         mWordId = dicNodeProp->mWordId;
         mDepth = dicNodeProp->mDepth + 1; // Increment the depth of a passing child
         mLeavingDepth = dicNodeProp->mLeavingDepth;
-        memmove(mPrevWordIds, dicNodeProp->mPrevWordIds, sizeof(mPrevWordIds));
+        WordIdArrayView::fromArray(dicNodeProp->mPrevWordIds)
+                .copyToArray(&mPrevWordIds, 0 /* offset */);
     }
 
     int getChildrenPtNodeArrayPos() const {
@@ -99,8 +103,8 @@
         return (mChildrenPtNodeArrayPos != NOT_A_DICT_POS) || mDepth != mLeavingDepth;
     }
 
-    const int *getPrevWordIds() const {
-        return mPrevWordIds;
+    const WordIdArrayView getPrevWordIds() const {
+        return WordIdArrayView::fromArray(mPrevWordIds);
     }
 
     int getWordId() const {
@@ -116,7 +120,7 @@
     int mWordId;
     uint16_t mDepth;
     uint16_t mLeavingDepth;
-    int mPrevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> mPrevWordIds;
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_PROPERTIES_H
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index 1de4051..b843791 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -85,7 +85,7 @@
         return;
     }
     const WordAttributes wordAttributes = mDictStructurePolicy->getWordAttributesInContext(
-            mPrevWordIds.data(), targetWordId, nullptr /* multiBigramMap */);
+            mPrevWordIds, targetWordId, nullptr /* multiBigramMap */);
     mSuggestionResults->addPrediction(targetWordCodePoints, codePointCount,
             wordAttributes.getProbability());
 }
@@ -93,11 +93,11 @@
 void Dictionary::getPredictions(const PrevWordsInfo *const prevWordsInfo,
         SuggestionResults *const outSuggestionResults) const {
     TimeKeeper::setCurrentTime();
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordIds(mDictionaryStructureWithBufferPolicy.get(), prevWordIds,
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = prevWordsInfo->getPrevWordIds(
+            mDictionaryStructureWithBufferPolicy.get(), &prevWordIdArray,
             true /* tryLowerCaseSearch */);
-    NgramListenerForPrediction listener(prevWordsInfo,
-            WordIdArrayView::fromFixedSizeArray(prevWordIds), outSuggestionResults,
+    NgramListenerForPrediction listener(prevWordsInfo, prevWordIds, outSuggestionResults,
             mDictionaryStructureWithBufferPolicy.get());
     mDictionaryStructureWithBufferPolicy->iterateNgramEntries(prevWordIds, &listener);
 }
@@ -119,11 +119,11 @@
             CodePointArrayView(word, length), false /* forceLowerCaseSearch */);
     if (wordId == NOT_A_WORD_ID) return NOT_A_PROBABILITY;
     if (!prevWordsInfo) {
-        return getDictionaryStructurePolicy()->getProbabilityOfWord(
-                nullptr /* prevWordsPtNodePos */, wordId);
+        return getDictionaryStructurePolicy()->getProbabilityOfWord(WordIdArrayView(), wordId);
     }
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordIds(mDictionaryStructureWithBufferPolicy.get(), prevWordIds,
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = prevWordsInfo->getPrevWordIds
+            (mDictionaryStructureWithBufferPolicy.get(), &prevWordIdArray,
             true /* tryLowerCaseSearch */);
     return getDictionaryStructurePolicy()->getProbabilityOfWord(prevWordIds, wordId);
 }
diff --git a/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp b/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp
index f71d4c5..d09266e 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp
@@ -23,6 +23,7 @@
 #include "suggest/core/dictionary/digraph_utils.h"
 #include "suggest/core/session/prev_words_info.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -34,9 +35,9 @@
 
     // No prev words information.
     PrevWordsInfo emptyPrevWordsInfo;
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    emptyPrevWordsInfo.getPrevWordIds(dictionaryStructurePolicy, prevWordIds,
-            false /* tryLowerCaseSearch */);
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = emptyPrevWordsInfo.getPrevWordIds(
+            dictionaryStructurePolicy, &prevWordIdArray, false /* tryLowerCaseSearch */);
     current.emplace_back();
     DicNodeUtils::initAsRoot(dictionaryStructurePolicy, prevWordIds, &current.front());
     for (int i = 0; i < codePointCount; ++i) {
diff --git a/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp b/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
index 979d61e..761f51e 100644
--- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
+++ b/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
@@ -35,9 +35,9 @@
 // Also caches the bigrams if there is space remaining and they have not been cached already.
 int MultiBigramMap::getBigramProbability(
         const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordIds, const int nextWordId,
+        const WordIdArrayView prevWordIds, const int nextWordId,
         const int unigramProbability) {
-    if (!prevWordIds || prevWordIds[0] == NOT_A_WORD_ID) {
+    if (prevWordIds.empty() || prevWordIds[0] == NOT_A_WORD_ID) {
         return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
     }
     const auto mapPosition = mBigramMaps.find(prevWordIds[0]);
@@ -56,7 +56,7 @@
 
 void MultiBigramMap::BigramMap::init(
         const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordIds) {
+        const WordIdArrayView prevWordIds) {
     structurePolicy->iterateNgramEntries(prevWordIds, this /* listener */);
 }
 
@@ -83,16 +83,13 @@
 
 void MultiBigramMap::addBigramsForWord(
         const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordIds) {
-    if (prevWordIds) {
-        mBigramMaps[prevWordIds[0]].init(structurePolicy, prevWordIds);
-    }
+        const WordIdArrayView prevWordIds) {
+    mBigramMaps[prevWordIds[0]].init(structurePolicy, prevWordIds);
 }
 
 int MultiBigramMap::readBigramProbabilityFromBinaryDictionary(
         const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordIds, const int nextWordId,
-        const int unigramProbability) {
+        const WordIdArrayView prevWordIds, const int nextWordId, const int unigramProbability) {
     const int bigramProbability = structurePolicy->getProbabilityOfWord(prevWordIds, nextWordId);
     if (bigramProbability != NOT_A_PROBABILITY) {
         return bigramProbability;
diff --git a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
index a8c4ded..d2eb5cc 100644
--- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
+++ b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
@@ -25,6 +25,7 @@
 #include "suggest/core/dictionary/bloom_filter.h"
 #include "suggest/core/dictionary/ngram_listener.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -39,7 +40,7 @@
     // Look up the bigram probability for the given word pair from the cached bigram maps.
     // Also caches the bigrams if there is space remaining and they have not been cached already.
     int getBigramProbability(const DictionaryStructureWithBufferPolicy *const structurePolicy,
-            const int *const prevWordIds, const int nextWordId, const int unigramProbability);
+            const WordIdArrayView prevWordIds, const int nextWordId, const int unigramProbability);
 
     void clear() {
         mBigramMaps.clear();
@@ -57,7 +58,7 @@
         virtual ~BigramMap() {}
 
         void init(const DictionaryStructureWithBufferPolicy *const structurePolicy,
-                const int *const prevWordIds);
+                const WordIdArrayView prevWordIds);
         int getBigramProbability(
                 const DictionaryStructureWithBufferPolicy *const structurePolicy,
                 const int nextWordId, const int unigramProbability) const;
@@ -70,11 +71,11 @@
     };
 
     void addBigramsForWord(const DictionaryStructureWithBufferPolicy *const structurePolicy,
-            const int *const prevWordIds);
+            const WordIdArrayView prevWordIds);
 
     int readBigramProbabilityFromBinaryDictionary(
             const DictionaryStructureWithBufferPolicy *const structurePolicy,
-            const int *const prevWordIds, const int nextWordId, const int unigramProbability);
+            const WordIdArrayView prevWordIds, const int nextWordId, const int unigramProbability);
 
     static const size_t MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP;
     std::unordered_map<int, BigramMap> mBigramMaps;
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index 7414f69..a498b6f 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -58,15 +58,15 @@
     virtual int getWordId(const CodePointArrayView wordCodePoints,
             const bool forceLowerCaseSearch) const = 0;
 
-    virtual const WordAttributes getWordAttributesInContext(const int *const prevWordIds,
+    virtual const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
             const int wordId, MultiBigramMap *const multiBigramMap) const = 0;
 
     // TODO: Remove
     virtual int getProbability(const int unigramProbability, const int bigramProbability) const = 0;
 
-    virtual int getProbabilityOfWord(const int *const prevWordIds, const int wordId) const = 0;
+    virtual int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const = 0;
 
-    virtual void iterateNgramEntries(const int *const prevWordIds,
+    virtual void iterateNgramEntries(const WordIdArrayView prevWordIds,
             NgramListener *const listener) const = 0;
 
     virtual BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const = 0;
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index d4d4d1e..4d7505a 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -35,8 +35,8 @@
     mMultiWordCostMultiplier = getDictionaryStructurePolicy()->getHeaderStructurePolicy()
             ->getMultiWordCostMultiplier();
     mSuggestOptions = suggestOptions;
-    prevWordsInfo->getPrevWordIds(getDictionaryStructurePolicy(), mPrevWordsIds,
-            true /* tryLowerCaseSearch */);
+    mPrevWordIdCount = prevWordsInfo->getPrevWordIds(getDictionaryStructurePolicy(),
+            &mPrevWordIdArray, true /* tryLowerCaseSearch */).size();
 }
 
 void DicTraverseSession::setupForGetSuggestions(const ProximityInfo *pInfo,
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index 0e676d8..9f841aa 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -24,6 +24,7 @@
 #include "suggest/core/dicnode/dic_nodes_cache.h"
 #include "suggest/core/dictionary/multi_bigram_map.h"
 #include "suggest/core/layout/proximity_info_state.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -50,14 +51,11 @@
     }
 
     AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
-            : mProximityInfo(nullptr), mDictionary(nullptr), mSuggestOptions(nullptr),
-              mDicNodesCache(usesLargeCache), mMultiBigramMap(), mInputSize(0), mMaxPointerCount(1),
-              mMultiWordCostMultiplier(1.0f) {
+            : mPrevWordIdCount(0), mProximityInfo(nullptr), mDictionary(nullptr),
+              mSuggestOptions(nullptr), mDicNodesCache(usesLargeCache), mMultiBigramMap(),
+              mInputSize(0), mMaxPointerCount(1), mMultiWordCostMultiplier(1.0f) {
         // NOTE: mProximityInfoStates is an array of instances.
         // No need to initialize it explicitly here.
-        for (size_t i = 0; i < NELEMS(mPrevWordsIds); ++i) {
-            mPrevWordsIds[i] = NOT_A_DICT_POS;
-        }
     }
 
     // Non virtual inline destructor -- never inherit this class
@@ -79,7 +77,9 @@
     //--------------------
     const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
     const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
-    const int *getPrevWordIds() const { return mPrevWordsIds; }
+    const WordIdArrayView getPrevWordIds() const {
+        return WordIdArrayView::fromArray(mPrevWordIdArray).limit(mPrevWordIdCount);
+    }
     DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
     MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
     const ProximityInfoState *getProximityInfoState(int id) const {
@@ -166,7 +166,8 @@
             const int *const inputYs, const int *const times, const int *const pointerIds,
             const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
 
-    int mPrevWordsIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> mPrevWordIdArray;
+    size_t mPrevWordIdCount;
     const ProximityInfo *mProximityInfo;
     const Dictionary *mDictionary;
     const SuggestOptions *mSuggestOptions;
diff --git a/native/jni/src/suggest/core/session/prev_words_info.h b/native/jni/src/suggest/core/session/prev_words_info.h
index fc9a359..02e82a8 100644
--- a/native/jni/src/suggest/core/session/prev_words_info.h
+++ b/native/jni/src/suggest/core/session/prev_words_info.h
@@ -17,6 +17,8 @@
 #ifndef LATINIME_PREV_WORDS_INFO_H
 #define LATINIME_PREV_WORDS_INFO_H
 
+#include <array>
+
 #include "defines.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 #include "utils/char_utils.h"
@@ -27,12 +29,13 @@
 class PrevWordsInfo {
  public:
     // No prev word information.
-    PrevWordsInfo() {
+    PrevWordsInfo() : mPrevWordCount(0) {
         clear();
     }
 
-    PrevWordsInfo(PrevWordsInfo &&prevWordsInfo) {
-        for (size_t i = 0; i < NELEMS(mPrevWordCodePoints); ++i) {
+    PrevWordsInfo(PrevWordsInfo &&prevWordsInfo)
+            : mPrevWordCount(prevWordsInfo.mPrevWordCount) {
+        for (size_t i = 0; i < mPrevWordCount; ++i) {
             mPrevWordCodePointCount[i] = prevWordsInfo.mPrevWordCodePointCount[i];
             memmove(mPrevWordCodePoints[i], prevWordsInfo.mPrevWordCodePoints[i],
                     sizeof(mPrevWordCodePoints[i][0]) * mPrevWordCodePointCount[i]);
@@ -43,9 +46,10 @@
     // Construct from previous words.
     PrevWordsInfo(const int prevWordCodePoints[][MAX_WORD_LENGTH],
             const int *const prevWordCodePointCount, const bool *const isBeginningOfSentence,
-            const size_t prevWordCount) {
+            const size_t prevWordCount)
+            : mPrevWordCount(std::min(NELEMS(mPrevWordCodePoints), prevWordCount)) {
         clear();
-        for (size_t i = 0; i < std::min(NELEMS(mPrevWordCodePoints), prevWordCount); ++i) {
+        for (size_t i = 0; i < mPrevWordCount; ++i) {
             if (prevWordCodePointCount[i] < 0 || prevWordCodePointCount[i] > MAX_WORD_LENGTH) {
                 continue;
             }
@@ -58,7 +62,7 @@
 
     // Construct from a previous word.
     PrevWordsInfo(const int *const prevWordCodePoints, const int prevWordCodePointCount,
-            const bool isBeginningOfSentence) {
+            const bool isBeginningOfSentence) : mPrevWordCount(1) {
         clear();
         if (prevWordCodePointCount > MAX_WORD_LENGTH || !prevWordCodePoints) {
             return;
@@ -79,26 +83,29 @@
         return false;
     }
 
-    void getPrevWordIds(const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
-            int *const outPrevWordIds, const bool tryLowerCaseSearch) const {
-        for (size_t i = 0; i < NELEMS(mPrevWordCodePoints); ++i) {
-            outPrevWordIds[i] = getWordId(dictStructurePolicy,
+    template<size_t N>
+    const WordIdArrayView getPrevWordIds(
+            const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
+            std::array<int, N> *const prevWordIdBuffer, const bool tryLowerCaseSearch) const {
+        for (size_t i = 0; i < std::min(mPrevWordCount, N); ++i) {
+            prevWordIdBuffer->at(i) = getWordId(dictStructurePolicy,
                     mPrevWordCodePoints[i], mPrevWordCodePointCount[i],
                     mIsBeginningOfSentence[i], tryLowerCaseSearch);
         }
+        return WordIdArrayView::fromArray(*prevWordIdBuffer).limit(mPrevWordCount);
     }
 
     // n is 1-indexed.
-    const CodePointArrayView getNthPrevWordCodePoints(const int n) const {
-        if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
+    const CodePointArrayView getNthPrevWordCodePoints(const size_t n) const {
+        if (n <= 0 || n > mPrevWordCount) {
             return CodePointArrayView();
         }
         return CodePointArrayView(mPrevWordCodePoints[n - 1], mPrevWordCodePointCount[n - 1]);
     }
 
     // n is 1-indexed.
-    bool isNthPrevWordBeginningOfSentence(const int n) const {
-        if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
+    bool isNthPrevWordBeginningOfSentence(const size_t n) const {
+        if (n <= 0 || n > mPrevWordCount) {
             return false;
         }
         return mIsBeginningOfSentence[n - 1];
@@ -142,6 +149,7 @@
         }
     }
 
+    const size_t mPrevWordCount;
     int mPrevWordCodePoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH];
     int mPrevWordCodePointCount[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
     bool mIsBeginningOfSentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
index 9b8a50b..41b9a11 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
@@ -116,7 +116,7 @@
 }
 
 const WordAttributes Ver4PatriciaTriePolicy::getWordAttributesInContext(
-        const int *const prevWordIds, const int wordId,
+        const WordIdArrayView prevWordIds, const int wordId,
         MultiBigramMap *const multiBigramMap) const {
     if (wordId == NOT_A_WORD_ID) {
         return WordAttributes();
@@ -128,7 +128,7 @@
                 prevWordIds, wordId, ptNodeParams.getProbability());
         return getWordAttributes(probability, ptNodeParams);
     }
-    if (prevWordIds) {
+    if (!prevWordIds.empty()) {
         const int probability = getProbabilityOfWord(prevWordIds, wordId);
         if (probability != NOT_A_PROBABILITY) {
             return getWordAttributes(probability, ptNodeParams);
@@ -160,7 +160,7 @@
     }
 }
 
-int Ver4PatriciaTriePolicy::getProbabilityOfWord(const int *const prevWordIds,
+int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds,
         const int wordId) const {
     if (wordId == NOT_A_WORD_ID) {
         return NOT_A_PROBABILITY;
@@ -170,7 +170,7 @@
     if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
         return NOT_A_PROBABILITY;
     }
-    if (prevWordIds) {
+    if (!prevWordIds.empty()) {
         const int bigramsPosition = getBigramsPositionOfPtNode(
                 getTerminalPtNodePosFromWordId(prevWordIds[0]));
         BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
@@ -186,9 +186,9 @@
     return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
 }
 
-void Ver4PatriciaTriePolicy::iterateNgramEntries(const int *const prevWordIds,
+void Ver4PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordIds,
         NgramListener *const listener) const {
-    if (!prevWordIds) {
+    if (prevWordIds.empty()) {
         return;
     }
     const int bigramsPosition = getBigramsPositionOfPtNode(
@@ -332,8 +332,12 @@
                 "length: %zd", bigramProperty->getTargetCodePoints()->size());
         return false;
     }
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordIds(this, prevWordIds, false /* tryLowerCaseSearch */);
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = prevWordsInfo->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSearch */);
+    if (prevWordIds.empty()) {
+        return false;
+    }
     if (prevWordIds[0] == NOT_A_WORD_ID) {
         if (prevWordsInfo->isNthPrevWordBeginningOfSentence(1 /* n */)) {
             const std::vector<UnigramProperty::ShortcutProperty> shortcuts;
@@ -347,7 +351,7 @@
                 return false;
             }
             // Refresh word ids.
-            prevWordsInfo->getPrevWordIds(this, prevWordIds, false /* tryLowerCaseSearch */);
+            prevWordsInfo->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */);
         } else {
             return false;
         }
@@ -390,9 +394,10 @@
         AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %zd",
                 wordCodePoints.size());
     }
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordIds(this, prevWordIds, false /* tryLowerCaseSerch */);
-    if (prevWordIds[0] == NOT_A_WORD_ID) {
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = prevWordsInfo->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSerch */);
+    if (prevWordIds.empty() || prevWordIds[0] == NOT_A_WORD_ID) {
         return false;
     }
     const int wordPos = getTerminalPtNodePosFromWordId(getWordId(wordCodePoints,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
index 871b556..576d2ab 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
@@ -91,14 +91,15 @@
 
     int getWordId(const CodePointArrayView wordCodePoints, const bool forceLowerCaseSearch) const;
 
-    const WordAttributes getWordAttributesInContext(const int *const prevWordIds, const int wordId,
-            MultiBigramMap *const multiBigramMap) const;
+    const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const;
 
     int getProbability(const int unigramProbability, const int bigramProbability) const;
 
-    int getProbabilityOfWord(const int *const prevWordIds, const int wordId) const;
+    int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const;
 
-    void iterateNgramEntries(const int *const prevWordIds, NgramListener *const listener) const;
+    void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const;
 
     BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const;
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index e76bae9..aae61af 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -282,8 +282,9 @@
     return getWordIdFromTerminalPtNodePos(ptNodePos);
 }
 
-const WordAttributes PatriciaTriePolicy::getWordAttributesInContext(const int *const prevWordIds,
-        const int wordId, MultiBigramMap *const multiBigramMap) const {
+const WordAttributes PatriciaTriePolicy::getWordAttributesInContext(
+        const WordIdArrayView prevWordIds, const int wordId,
+        MultiBigramMap *const multiBigramMap) const {
     if (wordId == NOT_A_WORD_ID) {
         return WordAttributes();
     }
@@ -295,7 +296,7 @@
                 prevWordIds, wordId, ptNodeParams.getProbability());
         return getWordAttributes(probability, ptNodeParams);
     }
-    if (prevWordIds) {
+    if (!prevWordIds.empty()) {
         const int bigramProbability = getProbabilityOfWord(prevWordIds, wordId);
         if (bigramProbability != NOT_A_PROBABILITY) {
             return getWordAttributes(bigramProbability, ptNodeParams);
@@ -327,7 +328,8 @@
     }
 }
 
-int PatriciaTriePolicy::getProbabilityOfWord(const int *const prevWordIds, const int wordId) const {
+int PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds,
+        const int wordId) const {
     if (wordId == NOT_A_WORD_ID) {
         return NOT_A_PROBABILITY;
     }
@@ -340,7 +342,7 @@
         // for shortcuts).
         return NOT_A_PROBABILITY;
     }
-    if (prevWordIds) {
+    if (!prevWordIds.empty()) {
         const int bigramsPosition = getBigramsPositionOfPtNode(
                 getTerminalPtNodePosFromWordId(prevWordIds[0]));
         BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramsPosition);
@@ -356,9 +358,9 @@
     return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
 }
 
-void PatriciaTriePolicy::iterateNgramEntries(const int *const prevWordIds,
+void PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordIds,
         NgramListener *const listener) const {
-    if (!prevWordIds) {
+    if (prevWordIds.empty()) {
         return;
     }
     const int bigramsPosition = getBigramsPositionOfPtNode(
@@ -371,8 +373,7 @@
     }
 }
 
-BinaryDictionaryShortcutIterator PatriciaTriePolicy::getShortcutIterator(
-        const int wordId) const {
+BinaryDictionaryShortcutIterator PatriciaTriePolicy::getShortcutIterator(const int wordId) const {
     const int shortcutPos = getShortcutPositionOfPtNode(getTerminalPtNodePosFromWordId(wordId));
     return BinaryDictionaryShortcutIterator(&mShortcutListPolicy, shortcutPos);
 }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
index 8c1665d..fc65de5 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
@@ -66,14 +66,15 @@
 
     int getWordId(const CodePointArrayView wordCodePoints, const bool forceLowerCaseSearch) const;
 
-    const WordAttributes getWordAttributesInContext(const int *const prevWordIds, const int wordId,
-            MultiBigramMap *const multiBigramMap) const;
+    const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const;
 
     int getProbability(const int unigramProbability, const int bigramProbability) const;
 
-    int getProbabilityOfWord(const int *const prevWordIds, const int wordId) const;
+    int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const;
 
-    void iterateNgramEntries(const int *const prevWordIds, NgramListener *const listener) const;
+    void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const;
 
     BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const;
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 0472a45..e624bf3 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -16,6 +16,7 @@
 
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h"
 
+#include <array>
 #include <vector>
 
 #include "suggest/core/dicnode/dic_node.h"
@@ -111,7 +112,7 @@
 }
 
 const WordAttributes Ver4PatriciaTriePolicy::getWordAttributesInContext(
-        const int *const prevWordIds, const int wordId,
+        const WordIdArrayView prevWordIds, const int wordId,
         MultiBigramMap *const multiBigramMap) const {
     if (wordId == NOT_A_WORD_ID) {
         return WordAttributes();
@@ -121,27 +122,11 @@
     const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
     // TODO: Support n-gram.
     return WordAttributes(mBuffers->getLanguageModelDictContent()->getWordProbability(
-            WordIdArrayView::singleElementView(prevWordIds), wordId), ptNodeParams.isBlacklisted(),
+            prevWordIds.limit(1 /* maxSize */), wordId), ptNodeParams.isBlacklisted(),
             ptNodeParams.isNotAWord(), ptNodeParams.getProbability() == 0);
 }
 
-int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability,
-        const int bigramProbability) const {
-    if (mHeaderPolicy->isDecayingDict()) {
-        // Both probabilities are encoded. Decode them and get probability.
-        return ForgettingCurveUtils::getProbability(unigramProbability, bigramProbability);
-    } else {
-        if (unigramProbability == NOT_A_PROBABILITY) {
-            return NOT_A_PROBABILITY;
-        } else if (bigramProbability == NOT_A_PROBABILITY) {
-            return ProbabilityUtils::backoff(unigramProbability);
-        } else {
-            return bigramProbability;
-        }
-    }
-}
-
-int Ver4PatriciaTriePolicy::getProbabilityOfWord(const int *const prevWordIds,
+int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds,
         const int wordId) const {
     if (wordId == NOT_A_WORD_ID) {
         return NOT_A_PROBABILITY;
@@ -152,22 +137,19 @@
     if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
         return NOT_A_PROBABILITY;
     }
-    if (prevWordIds) {
-        // TODO: Support n-gram.
-        const ProbabilityEntry probabilityEntry =
-                mBuffers->getLanguageModelDictContent()->getNgramProbabilityEntry(
-                        IntArrayView::singleElementView(prevWordIds), wordId);
-        if (!probabilityEntry.isValid()) {
-            return NOT_A_PROBABILITY;
-        }
-        if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-            return ForgettingCurveUtils::decodeProbability(probabilityEntry.getHistoricalInfo(),
-                    mHeaderPolicy);
-        } else {
-            return probabilityEntry.getProbability();
-        }
+    // TODO: Support n-gram.
+    const ProbabilityEntry probabilityEntry =
+            mBuffers->getLanguageModelDictContent()->getNgramProbabilityEntry(
+                    prevWordIds.limit(1 /* maxSize */), wordId);
+    if (!probabilityEntry.isValid()) {
+        return NOT_A_PROBABILITY;
     }
-    return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
+    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
+        return ForgettingCurveUtils::decodeProbability(probabilityEntry.getHistoricalInfo(),
+                mHeaderPolicy);
+    } else {
+        return probabilityEntry.getProbability();
+    }
 }
 
 BinaryDictionaryShortcutIterator Ver4PatriciaTriePolicy::getShortcutIterator(
@@ -176,15 +158,15 @@
     return BinaryDictionaryShortcutIterator(&mShortcutPolicy, shortcutPos);
 }
 
-void Ver4PatriciaTriePolicy::iterateNgramEntries(const int *const prevWordIds,
+void Ver4PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordIds,
         NgramListener *const listener) const {
-    if (!prevWordIds) {
+    if (prevWordIds.empty()) {
         return;
     }
     // TODO: Support n-gram.
     const auto languageModelDictContent = mBuffers->getLanguageModelDictContent();
     for (const auto entry : languageModelDictContent->getProbabilityEntries(
-            WordIdArrayView::singleElementView(prevWordIds))) {
+            prevWordIds.limit(1 /* maxSize */))) {
         const ProbabilityEntry &probabilityEntry = entry.getProbabilityEntry();
         const int probability = probabilityEntry.hasHistoricalInfo() ?
                 ForgettingCurveUtils::decodeProbability(
@@ -321,8 +303,12 @@
                 "length: %zd", bigramProperty->getTargetCodePoints()->size());
         return false;
     }
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordIds(this, prevWordIds, false /* tryLowerCaseSearch */);
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = prevWordsInfo->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSearch */);
+    if (prevWordIds.empty()) {
+        return false;
+    }
     // TODO: Support N-gram.
     if (prevWordIds[0] == NOT_A_WORD_ID) {
         if (prevWordsInfo->isNthPrevWordBeginningOfSentence(1 /* n */)) {
@@ -337,7 +323,7 @@
                 return false;
             }
             // Refresh word ids.
-            prevWordsInfo->getPrevWordIds(this, prevWordIds, false /* tryLowerCaseSearch */);
+            prevWordsInfo->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */);
         } else {
             return false;
         }
@@ -348,14 +334,14 @@
         return false;
     }
     bool addedNewEntry = false;
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    for (size_t i = 0; i < NELEMS(prevWordIds); ++i) {
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordsPtNodePos;
+    for (size_t i = 0; i < prevWordsPtNodePos.size(); ++i) {
         prevWordsPtNodePos[i] = mBuffers->getTerminalPositionLookupTable()
                 ->getTerminalPtNodePosition(prevWordIds[i]);
     }
     const int wordPtNodePos = mBuffers->getTerminalPositionLookupTable()
             ->getTerminalPtNodePosition(wordId);
-    if (mUpdatingHelper.addNgramEntry(WordIdArrayView::fromFixedSizeArray(prevWordsPtNodePos),
+    if (mUpdatingHelper.addNgramEntry(WordIdArrayView::fromArray(prevWordsPtNodePos),
             wordPtNodePos, bigramProperty, &addedNewEntry)) {
         if (addedNewEntry) {
             mBigramCount++;
@@ -385,24 +371,25 @@
         AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %zd",
                 wordCodePoints.size());
     }
-    int prevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordIds(this, prevWordIds, false /* tryLowerCaseSerch */);
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = prevWordsInfo->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSerch */);
     // TODO: Support N-gram.
-    if (prevWordIds[0] == NOT_A_WORD_ID) {
+    if (prevWordIds.empty() || prevWordIds[0] == NOT_A_WORD_ID) {
         return false;
     }
     const int wordId = getWordId(wordCodePoints, false /* forceLowerCaseSearch */);
     if (wordId == NOT_A_WORD_ID) {
         return false;
     }
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    for (size_t i = 0; i < NELEMS(prevWordIds); ++i) {
+    std::array<int, MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordsPtNodePos;
+    for (size_t i = 0; i < prevWordsPtNodePos.size(); ++i) {
         prevWordsPtNodePos[i] = mBuffers->getTerminalPositionLookupTable()
                 ->getTerminalPtNodePosition(prevWordIds[i]);
     }
     const int wordPtNodePos = mBuffers->getTerminalPositionLookupTable()
             ->getTerminalPtNodePosition(wordId);
-    if (mUpdatingHelper.removeNgramEntry(WordIdArrayView::fromFixedSizeArray(prevWordsPtNodePos),
+    if (mUpdatingHelper.removeNgramEntry(WordIdArrayView::fromArray(prevWordsPtNodePos),
             wordPtNodePos)) {
         mBigramCount--;
         return true;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
index 980c16e..a117a36 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -68,14 +68,19 @@
 
     int getWordId(const CodePointArrayView wordCodePoints, const bool forceLowerCaseSearch) const;
 
-    const WordAttributes getWordAttributesInContext(const int *const prevWordIds, const int wordId,
-            MultiBigramMap *const multiBigramMap) const;
+    const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const;
 
-    int getProbability(const int unigramProbability, const int bigramProbability) const;
+    // TODO: Remove
+    int getProbability(const int unigramProbability, const int bigramProbability) const {
+        // Not used.
+        return NOT_A_PROBABILITY;
+    }
 
-    int getProbabilityOfWord(const int *const prevWordIds, const int wordId) const;
+    int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const;
 
-    void iterateNgramEntries(const int *const prevWordIds, NgramListener *const listener) const;
+    void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const;
 
     BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const;
 
diff --git a/native/jni/src/utils/int_array_view.h b/native/jni/src/utils/int_array_view.h
index c39add9..caa13d9 100644
--- a/native/jni/src/utils/int_array_view.h
+++ b/native/jni/src/utils/int_array_view.h
@@ -57,9 +57,9 @@
     explicit IntArrayView(const std::vector<int> &vector)
             : mPtr(vector.data()), mSize(vector.size()) {}
 
-    template <int N>
-    AK_FORCE_INLINE static IntArrayView fromFixedSizeArray(const int (&array)[N]) {
-        return IntArrayView(array, N);
+    template <size_t N>
+    AK_FORCE_INLINE static IntArrayView fromArray(const std::array<int, N> &array) {
+        return IntArrayView(array.data(), array.size());
     }
 
     // Returns a view that points one int object.
@@ -120,6 +120,8 @@
 using WordIdArrayView = IntArrayView;
 using PtNodePosArrayView = IntArrayView;
 using CodePointArrayView = IntArrayView;
+template <size_t size>
+using WordIdArray = std::array<int, size>;
 
 } // namespace latinime
 #endif // LATINIME_MEMORY_VIEW_H
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
index e6f0353..7608b45 100644
--- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
+++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest.h>
 
+#include <array>
 #include <unordered_set>
 
 #include "utils/int_array_view.h"
@@ -97,8 +98,8 @@
     const int bigramProbability = 20;
     const int trigramProbability = 30;
     const int wordId = 100;
-    const int prevWordIdArray[] = { 1, 2 };
-    const WordIdArrayView prevWordIds = WordIdArrayView::fromFixedSizeArray(prevWordIdArray);
+    const std::array<int, 2> prevWordIdArray = {{ 1, 2 }};
+    const WordIdArrayView prevWordIds = WordIdArrayView::fromArray(prevWordIdArray);
 
     const ProbabilityEntry probabilityEntry(flag, probability);
     languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
diff --git a/native/jni/tests/utils/int_array_view_test.cpp b/native/jni/tests/utils/int_array_view_test.cpp
index ec57cf5..3bc294c 100644
--- a/native/jni/tests/utils/int_array_view_test.cpp
+++ b/native/jni/tests/utils/int_array_view_test.cpp
@@ -46,8 +46,8 @@
 
 TEST(IntArrayViewTest, TestConstructFromArray) {
     const size_t ARRAY_SIZE = 100;
-    int intArray[ARRAY_SIZE];
-    const auto intArrayView = IntArrayView::fromFixedSizeArray(intArray);
+    std::array<int, ARRAY_SIZE> intArray;
+    const auto intArrayView = IntArrayView::fromArray(intArray);
     EXPECT_EQ(ARRAY_SIZE, intArrayView.size());
 }