Merge "Get n-gram probability in structure policy." into lmp-dev
diff --git a/dictionaries/ru_wordlist.combined.gz b/dictionaries/ru_wordlist.combined.gz
index acde9bc..7794f7b 100644
--- a/dictionaries/ru_wordlist.combined.gz
+++ b/dictionaries/ru_wordlist.combined.gz
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_dark.png b/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_dark.png
index 47e673a..e1c713a 100644
--- a/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_dark.png
+++ b/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_light.png b/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_light.png
index ad933ca..b1fe2c0 100644
--- a/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_light.png
+++ b/java/res/drawable-hdpi/ic_emoji_people_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_dark.png b/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_dark.png
index a894c60..6369ac9 100644
--- a/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_dark.png
+++ b/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_light.png b/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_light.png
index 2d8bdf8..dbb111f 100644
--- a/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_light.png
+++ b/java/res/drawable-hdpi/ic_emoji_people_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_dark.png b/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_dark.png
index c9b81e1..c4d2115 100644
--- a/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_dark.png
+++ b/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_light.png b/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_light.png
index 1c031c0..b2b0687 100644
--- a/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_light.png
+++ b/java/res/drawable-hdpi/ic_emoji_places_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_dark.png b/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_dark.png
index 36fbf91..53f13d9 100644
--- a/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_dark.png
+++ b/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_light.png b/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_light.png
index 3bd317c..90cc77d 100644
--- a/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_light.png
+++ b/java/res/drawable-hdpi/ic_emoji_places_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_dark.png b/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_dark.png
index 43d3f30..5f23ec2 100644
--- a/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_dark.png
+++ b/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_light.png b/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_light.png
index 3a6b3ac..6566ba8 100644
--- a/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_light.png
+++ b/java/res/drawable-hdpi/ic_emoji_recents_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_dark.png b/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_dark.png
index a07f606..6da194c 100644
--- a/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_dark.png
+++ b/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_light.png b/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_light.png
index d86c1b9..b50eba7 100644
--- a/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_light.png
+++ b/java/res/drawable-hdpi/ic_emoji_recents_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_background_lxx_dark.9.png b/java/res/drawable-hdpi/keyboard_background_lxx_dark.9.png
new file mode 100644
index 0000000..e34c566
--- /dev/null
+++ b/java/res/drawable-hdpi/keyboard_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_background_lxx_light.9.png b/java/res/drawable-hdpi/keyboard_background_lxx_light.9.png
new file mode 100644
index 0000000..bf5450c
--- /dev/null
+++ b/java/res/drawable-hdpi/keyboard_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_suggest_strip_lxx_dark.9.png b/java/res/drawable-hdpi/keyboard_suggest_strip_lxx_dark.9.png
new file mode 100644
index 0000000..3f6a943
--- /dev/null
+++ b/java/res/drawable-hdpi/keyboard_suggest_strip_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/keyboard_suggest_strip_lxx_light.9.png b/java/res/drawable-hdpi/keyboard_suggest_strip_lxx_light.9.png
new file mode 100644
index 0000000..107cfc7
--- /dev/null
+++ b/java/res/drawable-hdpi/keyboard_suggest_strip_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_space_lxx_dark.png b/java/res/drawable-hdpi/sym_keyboard_space_lxx_dark.png
new file mode 100644
index 0000000..9ff6402
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_space_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-hdpi/sym_keyboard_space_lxx_light.png b/java/res/drawable-hdpi/sym_keyboard_space_lxx_light.png
new file mode 100644
index 0000000..d43e4dd
--- /dev/null
+++ b/java/res/drawable-hdpi/sym_keyboard_space_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_dark.png b/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_dark.png
index 952b570..bb37a63 100644
--- a/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_dark.png
+++ b/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_light.png b/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_light.png
index d0d72db..e639416 100644
--- a/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_light.png
+++ b/java/res/drawable-mdpi/ic_emoji_people_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_dark.png b/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_dark.png
index 1f46b9b..a7f8160 100644
--- a/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_dark.png
+++ b/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_light.png b/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_light.png
index 8b7c1a3..d4b114c 100644
--- a/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_light.png
+++ b/java/res/drawable-mdpi/ic_emoji_people_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_dark.png b/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_dark.png
index fadb751..630836b 100644
--- a/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_dark.png
+++ b/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_light.png b/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_light.png
index 5c0e40d..2ba4301 100644
--- a/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_light.png
+++ b/java/res/drawable-mdpi/ic_emoji_places_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_dark.png b/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_dark.png
index 5eed3d9..8bc3503 100644
--- a/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_dark.png
+++ b/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_light.png b/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_light.png
index fff7998..b033c83 100644
--- a/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_light.png
+++ b/java/res/drawable-mdpi/ic_emoji_places_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_dark.png b/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_dark.png
index e6c8dc0..b0b683b 100644
--- a/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_dark.png
+++ b/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_light.png b/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_light.png
index 25ac3f5..39c22c4 100644
--- a/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_light.png
+++ b/java/res/drawable-mdpi/ic_emoji_recents_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_dark.png b/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_dark.png
index e660891..b0138f5 100644
--- a/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_dark.png
+++ b/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_light.png b/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_light.png
index 614d081..99e7884 100644
--- a/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_light.png
+++ b/java/res/drawable-mdpi/ic_emoji_recents_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_background_lxx_dark.9.png b/java/res/drawable-mdpi/keyboard_background_lxx_dark.9.png
new file mode 100644
index 0000000..012d914
--- /dev/null
+++ b/java/res/drawable-mdpi/keyboard_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_background_lxx_light.9.png b/java/res/drawable-mdpi/keyboard_background_lxx_light.9.png
new file mode 100644
index 0000000..91adfac
--- /dev/null
+++ b/java/res/drawable-mdpi/keyboard_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_suggest_strip_lxx_dark.9.png b/java/res/drawable-mdpi/keyboard_suggest_strip_lxx_dark.9.png
new file mode 100644
index 0000000..d85ca71
--- /dev/null
+++ b/java/res/drawable-mdpi/keyboard_suggest_strip_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_suggest_strip_lxx_light.9.png b/java/res/drawable-mdpi/keyboard_suggest_strip_lxx_light.9.png
new file mode 100644
index 0000000..983a695
--- /dev/null
+++ b/java/res/drawable-mdpi/keyboard_suggest_strip_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_space_lxx_dark.png b/java/res/drawable-mdpi/sym_keyboard_space_lxx_dark.png
new file mode 100644
index 0000000..9119a9d
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_space_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-mdpi/sym_keyboard_space_lxx_light.png b/java/res/drawable-mdpi/sym_keyboard_space_lxx_light.png
new file mode 100644
index 0000000..6c495be
--- /dev/null
+++ b/java/res/drawable-mdpi/sym_keyboard_space_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_dark.png b/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_dark.png
index cf2aeb5..538796e 100644
--- a/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_dark.png
+++ b/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_light.png b/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_light.png
index 3ecf9d0..0d8c33b 100644
--- a/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_light.png
+++ b/java/res/drawable-xhdpi/ic_emoji_people_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_dark.png b/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_dark.png
index b0a448a..dbde6b0 100644
--- a/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_dark.png
+++ b/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_light.png b/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_light.png
index d71bc1c..aeecdee 100644
--- a/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_light.png
+++ b/java/res/drawable-xhdpi/ic_emoji_people_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_dark.png b/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_dark.png
index 33f4e0a..607ad84 100644
--- a/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_dark.png
+++ b/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_light.png b/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_light.png
index 194f493..fe3f0ee 100644
--- a/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_light.png
+++ b/java/res/drawable-xhdpi/ic_emoji_places_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_dark.png b/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_dark.png
index 82d4ce6..bbec72f 100644
--- a/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_dark.png
+++ b/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_light.png b/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_light.png
index e1b90a9..e3f201d 100644
--- a/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_light.png
+++ b/java/res/drawable-xhdpi/ic_emoji_places_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_dark.png b/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_dark.png
index 3305737..66d9c8e 100644
--- a/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_dark.png
+++ b/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_light.png b/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_light.png
index 8c74847..2a97d59 100644
--- a/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_light.png
+++ b/java/res/drawable-xhdpi/ic_emoji_recents_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_dark.png b/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_dark.png
index b9c1a659..f60bba4 100644
--- a/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_dark.png
+++ b/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_light.png b/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_light.png
index 64e1c4d..a13db74 100644
--- a/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_light.png
+++ b/java/res/drawable-xhdpi/ic_emoji_recents_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_background_lxx_dark.9.png b/java/res/drawable-xhdpi/keyboard_background_lxx_dark.9.png
new file mode 100644
index 0000000..1c3a38e
--- /dev/null
+++ b/java/res/drawable-xhdpi/keyboard_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_background_lxx_light.9.png b/java/res/drawable-xhdpi/keyboard_background_lxx_light.9.png
new file mode 100644
index 0000000..a7f18b5
--- /dev/null
+++ b/java/res/drawable-xhdpi/keyboard_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_suggest_strip_lxx_dark.9.png b/java/res/drawable-xhdpi/keyboard_suggest_strip_lxx_dark.9.png
new file mode 100644
index 0000000..ac20faf
--- /dev/null
+++ b/java/res/drawable-xhdpi/keyboard_suggest_strip_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/keyboard_suggest_strip_lxx_light.9.png b/java/res/drawable-xhdpi/keyboard_suggest_strip_lxx_light.9.png
new file mode 100644
index 0000000..7ccd1ea
--- /dev/null
+++ b/java/res/drawable-xhdpi/keyboard_suggest_strip_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_space_lxx_dark.png b/java/res/drawable-xhdpi/sym_keyboard_space_lxx_dark.png
new file mode 100644
index 0000000..2cab2d2
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_space_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/sym_keyboard_space_lxx_light.png b/java/res/drawable-xhdpi/sym_keyboard_space_lxx_light.png
new file mode 100644
index 0000000..621eec6
--- /dev/null
+++ b/java/res/drawable-xhdpi/sym_keyboard_space_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_dark.png b/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_dark.png
index 9ca031a..47f6554 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_dark.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_light.png b/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_light.png
index 6faad5c..ef5bf5a 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_light.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_people_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_dark.png b/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_dark.png
index ed71326..8ebecb2 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_dark.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_light.png b/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_light.png
index a5516fa..d6369d9 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_light.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_people_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_dark.png b/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_dark.png
index 5131982..6ba4c3a 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_dark.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_light.png b/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_light.png
index 8a4614d..b753132 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_light.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_places_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_dark.png b/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_dark.png
index 0dfbadd..d645814 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_dark.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_light.png b/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_light.png
index 2f22dfb..95b111d 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_light.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_places_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_dark.png b/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_dark.png
index 28402b8..1501a07 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_dark.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_light.png b/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_light.png
index 92da7f2..dcf876a 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_light.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_recents_activated_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_dark.png b/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_dark.png
index 24561f9..5aeb79a 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_dark.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_light.png b/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_light.png
index 96ff801..7b8b003 100644
--- a/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_light.png
+++ b/java/res/drawable-xxhdpi/ic_emoji_recents_normal_lxx_light.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_background_lxx_dark.9.png b/java/res/drawable-xxhdpi/keyboard_background_lxx_dark.9.png
new file mode 100644
index 0000000..8b89170
--- /dev/null
+++ b/java/res/drawable-xxhdpi/keyboard_background_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_background_lxx_light.9.png b/java/res/drawable-xxhdpi/keyboard_background_lxx_light.9.png
new file mode 100644
index 0000000..847df8a
--- /dev/null
+++ b/java/res/drawable-xxhdpi/keyboard_background_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_suggest_strip_lxx_dark.9.png b/java/res/drawable-xxhdpi/keyboard_suggest_strip_lxx_dark.9.png
new file mode 100644
index 0000000..2de0c9c
--- /dev/null
+++ b/java/res/drawable-xxhdpi/keyboard_suggest_strip_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/keyboard_suggest_strip_lxx_light.9.png b/java/res/drawable-xxhdpi/keyboard_suggest_strip_lxx_light.9.png
new file mode 100644
index 0000000..8b495f3
--- /dev/null
+++ b/java/res/drawable-xxhdpi/keyboard_suggest_strip_lxx_light.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_space_lxx_dark.png b/java/res/drawable-xxhdpi/sym_keyboard_space_lxx_dark.png
new file mode 100644
index 0000000..f05d7d2
--- /dev/null
+++ b/java/res/drawable-xxhdpi/sym_keyboard_space_lxx_dark.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/sym_keyboard_space_lxx_light.png b/java/res/drawable-xxhdpi/sym_keyboard_space_lxx_light.png
new file mode 100644
index 0000000..94be906
--- /dev/null
+++ b/java/res/drawable-xxhdpi/sym_keyboard_space_lxx_light.png
Binary files differ
diff --git a/java/res/layout/suggestion_divider.xml b/java/res/layout/suggestion_divider.xml
index dfea017..a5bb6c5 100644
--- a/java/res/layout/suggestion_divider.xml
+++ b/java/res/layout/suggestion_divider.xml
@@ -31,4 +31,5 @@
     android:longClickable="false"
     android:hapticFeedbackEnabled="false"
     android:soundEffectsEnabled="false"
+    android:background="@null"
     style="?attr/suggestionStripViewStyle" />
diff --git a/java/res/raw/main_ru.dict b/java/res/raw/main_ru.dict
index 0f08f17..9fdaf31 100644
--- a/java/res/raw/main_ru.dict
+++ b/java/res/raw/main_ru.dict
Binary files differ
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index 783105d..d42b4e9 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -53,10 +53,8 @@
     <color name="suggested_word_color_lxx_light">#B337474F</color>
     <color name="gesture_trail_color_lxx_light">#4DB6AC</color>
     <color name="sliding_key_input_preview_color_lxx_light">#B34DB6AC</color>
-    <color name="keyboard_background_lxx_light">#ECEFF1</color>
     <color name="key_background_lxx_light">#ECEFF1</color>
     <color name="key_background_pressed_lxx_light">#2637474F</color>
-    <color name="suggestions_strip_background_lxx_light">#E4E7E9</color>
     <color name="suggested_word_background_selected_lxx_light">#2637474F</color>
     <color name="gesture_floating_preview_color_lxx_light">#E6ECEFF1</color>
     <color name="emoji_tab_page_indicator_background_lxx_light">#E4E7E9</color>
@@ -73,10 +71,8 @@
     <color name="suggested_word_color_lxx_dark">#B3FFFFFF</color>
     <color name="gesture_trail_color_lxx_dark">#80CBC4</color>
     <color name="sliding_key_input_preview_color_lxx_dark">#B380CBC4</color>
-    <color name="keyboard_background_lxx_dark">#263238</color>
     <color name="key_background_lxx_dark">#263238</color>
     <color name="key_background_pressed_lxx_dark">#19FFFFFF</color>
-    <color name="suggestions_strip_background_lxx_dark">#21272B</color>
     <color name="suggested_word_background_selected_lxx_dark">#19FFFFFF</color>
     <color name="gesture_floating_preview_color_lxx_dark">#E621272B</color>
     <color name="emoji_tab_page_indicator_background_lxx_dark">#21272B</color>
diff --git a/java/res/values/keyboard-icons-lxx-dark.xml b/java/res/values/keyboard-icons-lxx-dark.xml
index 15d267c..dfa585c 100644
--- a/java/res/values/keyboard-icons-lxx-dark.xml
+++ b/java/res/values/keyboard-icons-lxx-dark.xml
@@ -34,8 +34,7 @@
         <item name="iconPreviousKey">@drawable/sym_keyboard_previous_lxx_dark</item>
         <item name="iconTabKey">@drawable/sym_keyboard_tab_lxx_dark</item>
         <item name="iconShortcutKey">@drawable/sym_keyboard_voice_lxx_dark</item>
-        <!-- TODO: Update this icon for LXX_Dark theme. -->
-        <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo_dark</item>
+        <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_lxx_dark</item>
         <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_lxx_dark</item>
         <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_lxx_dark</item>
         <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_lxx_dark</item>
diff --git a/java/res/values/keyboard-icons-lxx-light.xml b/java/res/values/keyboard-icons-lxx-light.xml
index 60853ca..e8a3c56 100644
--- a/java/res/values/keyboard-icons-lxx-light.xml
+++ b/java/res/values/keyboard-icons-lxx-light.xml
@@ -34,8 +34,7 @@
         <item name="iconPreviousKey">@drawable/sym_keyboard_previous_lxx_light</item>
         <item name="iconTabKey">@drawable/sym_keyboard_tab_lxx_light</item>
         <item name="iconShortcutKey">@drawable/sym_keyboard_voice_lxx_light</item>
-        <!-- TODO: Update this icon for LXX_Light theme. -->
-        <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo_dark</item>
+        <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_lxx_light</item>
         <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_lxx_light</item>
         <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_lxx_light</item>
         <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_lxx_light</item>
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index f563010..0a13158 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -45,7 +45,7 @@
         name="KeyboardView.LXX_Dark"
         parent="KeyboardView"
     >
-        <item name="android:background">@color/keyboard_background_lxx_dark</item>
+        <item name="android:background">@drawable/keyboard_background_lxx_dark</item>
         <item name="keyBackground">@drawable/btn_keyboard_key_lxx_dark</item>
         <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_lxx_dark</item>
         <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_lxx_dark</item>
@@ -119,7 +119,7 @@
         <item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item>
         <item name="maxMoreSuggestionsRow">@integer/config_max_more_suggestions_row</item>
         <item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item>
-        <item name="android:background">@color/suggestions_strip_background_lxx_dark</item>
+        <item name="android:background">@drawable/keyboard_suggest_strip_lxx_dark</item>
         <item name="android:src">@drawable/suggestions_strip_divider_lxx_dark</item>
         <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item>
         <item name="colorValidTypedWord">@color/typed_word_color_lxx_dark</item>
diff --git a/java/res/values/themes-lxx-light.xml b/java/res/values/themes-lxx-light.xml
index 48bd313..eccecdd 100644
--- a/java/res/values/themes-lxx-light.xml
+++ b/java/res/values/themes-lxx-light.xml
@@ -45,7 +45,7 @@
         name="KeyboardView.LXX_Light"
         parent="KeyboardView"
     >
-        <item name="android:background">@color/keyboard_background_lxx_light</item>
+        <item name="android:background">@drawable/keyboard_background_lxx_light</item>
         <item name="keyBackground">@drawable/btn_keyboard_key_lxx_light</item>
         <item name="functionalKeyBackground">@drawable/btn_keyboard_key_functional_lxx_light</item>
         <item name="spacebarBackground">@drawable/btn_keyboard_spacebar_lxx_light</item>
@@ -120,7 +120,7 @@
         <item name="centerSuggestionPercentile">@fraction/config_center_suggestion_percentile</item>
         <item name="maxMoreSuggestionsRow">@integer/config_max_more_suggestions_row</item>
         <item name="minMoreSuggestionsWidth">@fraction/config_min_more_suggestions_width</item>
-        <item name="android:background">@color/suggestions_strip_background_lxx_light</item>
+        <item name="android:background">@drawable/keyboard_suggest_strip_lxx_light</item>
         <item name="android:src">@drawable/suggestions_strip_divider_lxx_light</item>
         <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item>
         <item name="colorValidTypedWord">@color/typed_word_color_lxx_light</item>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 7e4c284..66091a0 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -19,41 +19,9 @@
     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">
-        <CheckBoxPreference
-            android:key="auto_cap"
-            android:title="@string/auto_cap"
-            android:summary="@string/auto_cap_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_key_use_double_space_period"
-            android:title="@string/use_double_space_period"
-            android:summary="@string/use_double_space_period_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="vibrate_on"
-            android:title="@string/vibrate_on_keypress"
-            android:defaultValue="@bool/config_default_vibration_enabled"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="sound_on"
-            android:title="@string/sound_on_keypress"
-            android:defaultValue="@bool/config_default_sound_enabled"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="popup_on"
-            android:title="@string/popup_on_keypress"
-            android:defaultValue="@bool/config_default_key_preview_popup"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_voice_input_key"
-            android:title="@string/voice_input"
-            android:defaultValue="true"
-            android:persistent="true" />
-    </PreferenceScreen>
+        android:key="screen_input" />
     <ListPreference
         android:key="pref_keyboard_theme"
         android:title="@string/keyboard_theme"
@@ -61,146 +29,19 @@
         android:entries="@array/keyboard_theme_names"
         android:persistent="true" />
     <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.MultiLingualSettingsFragment"
         android:title="@string/settings_screen_multi_lingual"
-        android:key="screen_multi_lingual">
-        <CheckBoxPreference
-            android:key="pref_show_language_switch_key"
-            android:title="@string/show_language_switch_key"
-            android:summary="@string/show_language_switch_key_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_include_other_imes_in_language_switch_list"
-            android:dependency="pref_show_language_switch_key"
-            android:title="@string/include_other_imes_in_language_switch_list"
-            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.AdditionalSubtypeSettings"
-            android:key="custom_input_styles"
-            android:title="@string/custom_input_styles_title" />
-    </PreferenceScreen>
+        android:key="screen_multi_lingual" />
     <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.GestureSettingsFragment"
         android:title="@string/settings_screen_gesture"
-        android:key="screen_gesture">
-        <CheckBoxPreference
-            android:key="gesture_input"
-            android:title="@string/gesture_input"
-            android:summary="@string/gesture_input_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_gesture_floating_preview_text"
-            android:dependency="gesture_input"
-            android:title="@string/gesture_floating_preview_text"
-            android:summary="@string/gesture_floating_preview_text_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_gesture_preview_trail"
-            android:dependency="gesture_input"
-            android:title="@string/gesture_preview_trail"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_gesture_space_aware"
-            android:dependency="gesture_input"
-            android:title="@string/gesture_space_aware"
-            android:summary="@string/gesture_space_aware_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-    </PreferenceScreen>
+        android:key="screen_gesture" />
     <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.CorrectionSettingsFragment"
         android:title="@string/settings_screen_correction"
-        android:key="screen_correction">
-        <PreferenceScreen
-            android:key="edit_personal_dictionary"
-            android:title="@string/edit_personal_dictionary">
-            <intent android:action="android.settings.USER_DICTIONARY_SETTINGS" />
-        </PreferenceScreen>
-        <PreferenceScreen
-            android:key="configure_dictionaries_key"
-            android:title="@string/configure_dictionaries_title">
-           <intent
-              android:action="android.intent.action.MAIN"
-              android:targetClass="@string/dictionary_pack_settings_activity">
-             <extra
-                 android:name="clientId"
-                 android:value="@string/dictionary_pack_client_id" />
-           </intent>
-        </PreferenceScreen>
-        <CheckBoxPreference
-            android:key="pref_key_block_potentially_offensive"
-            android:title="@string/prefs_block_potentially_offensive_title"
-            android:summary="@string/prefs_block_potentially_offensive_summary"
-            android:defaultValue="@bool/config_block_potentially_offensive"
-            android:persistent="true" />
-        <ListPreference
-            android:key="auto_correction_threshold"
-            android:title="@string/auto_correction"
-            android:summary="@string/auto_correction_summary"
-            android:entryValues="@array/auto_correction_threshold_mode_indexes"
-            android:entries="@array/auto_correction_threshold_modes"
-            android:defaultValue="@string/auto_correction_threshold_mode_index_modest"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="show_suggestions"
-            android:summary="@string/prefs_show_suggestions_summary"
-            android:title="@string/prefs_show_suggestions"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_key_use_personalized_dicts"
-            android:title="@string/use_personalized_dicts"
-            android:summary="@string/use_personalized_dicts_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="pref_key_use_contacts_dict"
-            android:title="@string/use_contacts_dict"
-            android:summary="@string/use_contacts_dict_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <CheckBoxPreference
-            android:key="next_word_prediction"
-            android:title="@string/bigram_prediction"
-            android:summary="@string/bigram_prediction_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        </PreferenceScreen>
+        android:key="screen_correction" />
     <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.AdvancedSettingsFragment"
         android:title="@string/settings_screen_advanced"
-        android:key="screen_advanced">
-        <!-- TODO: consolidate key preview dismiss delay with the key preview animation parameters. -->
-        <ListPreference
-            android:key="pref_key_preview_popup_dismiss_delay"
-            android:title="@string/key_preview_popup_dismiss_delay" />
-        <com.android.inputmethod.latin.settings.SeekBarDialogPreference
-            android:key="pref_vibration_duration_settings"
-            android:title="@string/prefs_keypress_vibration_duration_settings"
-            latin:maxValue="@integer/config_max_vibration_duration" />
-        <com.android.inputmethod.latin.settings.SeekBarDialogPreference
-            android:key="pref_keypress_sound_volume"
-            android:title="@string/prefs_keypress_sound_volume_settings"
-            latin:maxValue="100" /> <!-- percent -->
-        <!-- The settigs for showing setup wizard application icon shouldn't be persistent and
-             the default value is added programmatically. -->
-        <CheckBoxPreference
-            android:key="pref_show_setup_wizard_icon"
-            android:title="@string/show_setup_wizard_icon"
-            android:summary="@string/show_setup_wizard_icon_summary" />
-        <!-- title will be set programmatically to embed application name -->
-        <CheckBoxPreference
-            android:key="pref_enable_metrics_logging"
-            android:summary="@string/enable_metrics_logging_summary"
-            android:defaultValue="true"
-            android:persistent="true" />
-        <PreferenceScreen
-            android:fragment="com.android.inputmethod.latin.settings.DebugSettings"
-            android:key="screen_debug"
-            android:title="Debug settings"
-            android:defaultValue="false"
-            android:persistent="true" />
-        </PreferenceScreen>
+        android:key="screen_advanced" />
 </PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_advanced.xml b/java/res/xml/prefs_screen_advanced.xml
new file mode 100644
index 0000000..5aefcc8
--- /dev/null
+++ b/java/res/xml/prefs_screen_advanced.xml
@@ -0,0 +1,52 @@
+<?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"
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    android:title="@string/settings_screen_advanced"
+    android:key="screen_advanced">
+    <!-- TODO: consolidate key preview dismiss delay with the key preview animation parameters. -->
+    <ListPreference
+        android:key="pref_key_preview_popup_dismiss_delay"
+        android:title="@string/key_preview_popup_dismiss_delay" />
+    <com.android.inputmethod.latin.settings.SeekBarDialogPreference
+        android:key="pref_vibration_duration_settings"
+        android:title="@string/prefs_keypress_vibration_duration_settings"
+        latin:maxValue="@integer/config_max_vibration_duration" />
+    <com.android.inputmethod.latin.settings.SeekBarDialogPreference
+        android:key="pref_keypress_sound_volume"
+        android:title="@string/prefs_keypress_sound_volume_settings"
+        latin:maxValue="100" /> <!-- percent -->
+    <!-- The settings for showing setup wizard application icon shouldn't be persistent and
+         the default value is added programmatically. -->
+    <CheckBoxPreference
+        android:key="pref_show_setup_wizard_icon"
+        android:title="@string/show_setup_wizard_icon"
+        android:summary="@string/show_setup_wizard_icon_summary" />
+    <!-- title will be set programmatically to embed application name -->
+    <CheckBoxPreference
+        android:key="pref_enable_metrics_logging"
+        android:summary="@string/enable_metrics_logging_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.DebugSettingsFragment"
+        android:key="screen_debug"
+        android:title="Debug settings"
+        android:defaultValue="false"
+        android:persistent="true" />
+</PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_correction.xml b/java/res/xml/prefs_screen_correction.xml
new file mode 100644
index 0000000..dd5ba54
--- /dev/null
+++ b/java/res/xml/prefs_screen_correction.xml
@@ -0,0 +1,76 @@
+<?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"
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    android:title="@string/settings_screen_correction"
+    android:key="screen_correction">
+    <PreferenceScreen
+        android:key="edit_personal_dictionary"
+        android:title="@string/edit_personal_dictionary">
+        <intent android:action="android.settings.USER_DICTIONARY_SETTINGS" />
+    </PreferenceScreen>
+    <PreferenceScreen
+        android:key="configure_dictionaries_key"
+        android:title="@string/configure_dictionaries_title">
+        <intent
+            android:action="android.intent.action.MAIN"
+            android:targetClass="@string/dictionary_pack_settings_activity">
+            <extra
+                android:name="clientId"
+                android:value="@string/dictionary_pack_client_id" />
+        </intent>
+    </PreferenceScreen>
+    <CheckBoxPreference
+        android:key="pref_key_block_potentially_offensive"
+        android:title="@string/prefs_block_potentially_offensive_title"
+        android:summary="@string/prefs_block_potentially_offensive_summary"
+        android:defaultValue="@bool/config_block_potentially_offensive"
+        android:persistent="true" />
+    <ListPreference
+        android:key="auto_correction_threshold"
+        android:title="@string/auto_correction"
+        android:summary="@string/auto_correction_summary"
+        android:entryValues="@array/auto_correction_threshold_mode_indexes"
+        android:entries="@array/auto_correction_threshold_modes"
+        android:defaultValue="@string/auto_correction_threshold_mode_index_modest"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="show_suggestions"
+        android:summary="@string/prefs_show_suggestions_summary"
+        android:title="@string/prefs_show_suggestions"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_key_use_personalized_dicts"
+        android:title="@string/use_personalized_dicts"
+        android:summary="@string/use_personalized_dicts_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_key_use_contacts_dict"
+        android:title="@string/use_contacts_dict"
+        android:summary="@string/use_contacts_dict_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="next_word_prediction"
+        android:title="@string/bigram_prediction"
+        android:summary="@string/bigram_prediction_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+</PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_gesture.xml b/java/res/xml/prefs_screen_gesture.xml
new file mode 100644
index 0000000..c87316d
--- /dev/null
+++ b/java/res/xml/prefs_screen_gesture.xml
@@ -0,0 +1,47 @@
+<?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:title="@string/settings_screen_gesture"
+    android:key="screen_gesture">
+    <CheckBoxPreference
+        android:key="gesture_input"
+        android:title="@string/gesture_input"
+        android:summary="@string/gesture_input_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_gesture_floating_preview_text"
+        android:dependency="gesture_input"
+        android:title="@string/gesture_floating_preview_text"
+        android:summary="@string/gesture_floating_preview_text_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_gesture_preview_trail"
+        android:dependency="gesture_input"
+        android:title="@string/gesture_preview_trail"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_gesture_space_aware"
+        android:dependency="gesture_input"
+        android:title="@string/gesture_space_aware"
+        android:summary="@string/gesture_space_aware_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+</PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_input.xml b/java/res/xml/prefs_screen_input.xml
new file mode 100644
index 0000000..7704e3f
--- /dev/null
+++ b/java/res/xml/prefs_screen_input.xml
@@ -0,0 +1,53 @@
+<?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"
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    android:title="@string/settings_screen_input">
+    <CheckBoxPreference
+        android:key="auto_cap"
+        android:title="@string/auto_cap"
+        android:summary="@string/auto_cap_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_key_use_double_space_period"
+        android:title="@string/use_double_space_period"
+        android:summary="@string/use_double_space_period_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="vibrate_on"
+        android:title="@string/vibrate_on_keypress"
+        android:defaultValue="@bool/config_default_vibration_enabled"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="sound_on"
+        android:title="@string/sound_on_keypress"
+        android:defaultValue="@bool/config_default_sound_enabled"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="popup_on"
+        android:title="@string/popup_on_keypress"
+        android:defaultValue="@bool/config_default_key_preview_popup"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_voice_input_key"
+        android:title="@string/voice_input"
+        android:defaultValue="true"
+        android:persistent="true" />
+</PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_multi_lingual.xml b/java/res/xml/prefs_screen_multi_lingual.xml
new file mode 100644
index 0000000..937d439
--- /dev/null
+++ b/java/res/xml/prefs_screen_multi_lingual.xml
@@ -0,0 +1,38 @@
+<?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:title="@string/settings_screen_multi_lingual"
+    android:key="screen_multi_lingual">
+    <CheckBoxPreference
+        android:key="pref_show_language_switch_key"
+        android:title="@string/show_language_switch_key"
+        android:summary="@string/show_language_switch_key_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+    <CheckBoxPreference
+        android:key="pref_include_other_imes_in_language_switch_list"
+        android:dependency="pref_show_language_switch_key"
+        android:title="@string/include_other_imes_in_language_switch_list"
+        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/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index ad14c06..162a209 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -231,7 +231,7 @@
                 // Don't add single letter words, possibly confuses
                 // capitalization of i.
                 final int wordLen = StringUtils.codePointCount(word);
-                if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
+                if (wordLen <= MAX_WORD_LENGTH && wordLen > 1) {
                     if (DEBUG) {
                         Log.d(TAG, "addName " + name + ", " + word + ", "  + prevWordsInfo);
                     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d2a2fbd..719aeac 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -20,7 +20,6 @@
 import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
 import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -237,10 +236,10 @@
                         latinIme.mKeyboardSwitcher.getCurrentKeyboardScriptId());
                 break;
             case MSG_REOPEN_DICTIONARIES:
-                latinIme.resetSuggest();
                 // We need to re-evaluate the currently composing word in case the script has
                 // changed.
                 postWaitForDictionaryLoad();
+                latinIme.resetSuggest();
                 break;
             case MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED:
                 latinIme.mInputLogic.onUpdateTailBatchInputCompleted(
@@ -1621,24 +1620,22 @@
         if (mainKeyboardView != null) {
             mainKeyboardView.closing();
         }
-        launchSubActivity(SettingsActivity.class);
-    }
-
-    private void launchSubActivity(final Class<? extends Activity> activityClass) {
-        Intent intent = new Intent();
-        intent.setClass(LatinIME.this, activityClass);
+        final Intent intent = new Intent();
+        intent.setClass(LatinIME.this, SettingsActivity.class);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        intent.putExtra(SettingsActivity.EXTRA_SHOW_HOME_AS_UP, false);
         startActivity(intent);
     }
 
     private void showSubtypeSelectorAndSettings() {
         final CharSequence title = getString(R.string.english_ime_input_options);
+        // TODO: Should use new string "Select active input modes".
+        final CharSequence languageSelectionTitle = getString(R.string.language_selection_title);
         final CharSequence[] items = new CharSequence[] {
-                // TODO: Should use new string "Select active input modes".
-                getString(R.string.language_selection_title),
-                getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class)),
+                languageSelectionTitle,
+                getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
         };
         final OnClickListener listener = new OnClickListener() {
             @Override
@@ -1651,6 +1648,7 @@
                             Intent.FLAG_ACTIVITY_NEW_TASK
                                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                    intent.putExtra(Intent.EXTRA_TITLE, languageSelectionTitle);
                     startActivity(intent);
                     break;
                 case 1:
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index debaad1..21014b3 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -253,12 +253,12 @@
                 final int frequency = cursor.getInt(indexFrequency);
                 final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
                 // Safeguard against adding really long words.
-                if (word.length() < MAX_WORD_LENGTH) {
+                if (word.length() <= MAX_WORD_LENGTH) {
                     runGCIfRequiredLocked(true /* mindsBlockByGC */);
                     addUnigramLocked(word, adjustedFrequency, null /* shortcutTarget */,
                             0 /* shortcutFreq */, false /* isNotAWord */,
                             false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                    if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) {
+                    if (null != shortcut && shortcut.length() <= MAX_WORD_LENGTH) {
                         runGCIfRequiredLocked(true /* mindsBlockByGC */);
                         addUnigramLocked(shortcut, adjustedFrequency, word,
                                 USER_DICT_SHORTCUT_FREQUENCY, true /* isNotAWord */,
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index aac4094..331f85e 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -138,6 +138,7 @@
             final File filesDir = context.getFilesDir();
             if (filesDir == null) {
                 Log.e(TAG, "context.getFilesDir() returned null.");
+                return;
             }
             if (!FileUtils.deleteFilteredFiles(filesDir, new DictFilter(dictNamePrefix))) {
                 Log.e(TAG, "Cannot remove all existing dictionary files. filesDir: "
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 8e027e4..34d4d4e 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -62,8 +62,8 @@
             final PrevWordsInfo prevWordsInfo, final String word, final boolean isValid,
             final int timestamp, final DistracterFilter distracterFilter) {
         final CharSequence prevWord = prevWordsInfo.mPrevWordsInfo[0].mWord;
-        if (word.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH ||
-                (prevWord != null && prevWord.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH)) {
+        if (word.length() > Constants.DICTIONARY_MAX_WORD_LENGTH ||
+                (prevWord != null && prevWord.length() > Constants.DICTIONARY_MAX_WORD_LENGTH)) {
             return;
         }
         final int frequency = isValid ?
diff --git a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java
new file mode 100644
index 0000000..00f2c73
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java
@@ -0,0 +1,248 @@
+/*
+ * 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.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.TwoStatePreference;
+
+import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.define.ProductionFlags;
+import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
+
+/**
+ * "Advanced" settings sub screen.
+ *
+ * This settings sub screen handles the following advanced preferences.
+ * - Key popup dismiss delay
+ * - Keypress vibration duration
+ * - Keypress sound volume
+ * - Show app icon
+ * - Improve keyboard
+ * - Debug settings
+ */
+public final class AdvancedSettingsFragment extends SubScreenFragment {
+    @Override
+    public void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_advanced);
+
+        final Resources res = getResources();
+        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()}.
+        AudioAndHapticFeedbackManager.init(context);
+
+        final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+
+        if (!Settings.isInternal(prefs)) {
+            removePreference(Settings.SCREEN_DEBUG);
+        }
+
+        if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) {
+            removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS);
+        }
+
+        // TODO: consolidate key preview dismiss delay with the key preview animation parameters.
+        if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
+            removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+        } else {
+            // TODO: Cleanup this setup.
+            final ListPreference keyPreviewPopupDismissDelay =
+                    (ListPreference) findPreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+            final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
+                    R.integer.config_key_preview_linger_timeout));
+            keyPreviewPopupDismissDelay.setEntries(new String[] {
+                    res.getString(R.string.key_preview_popup_dismiss_no_delay),
+                    res.getString(R.string.key_preview_popup_dismiss_default_delay),
+            });
+            keyPreviewPopupDismissDelay.setEntryValues(new String[] {
+                    "0",
+                    popupDismissDelayDefaultValue
+            });
+            if (null == keyPreviewPopupDismissDelay.getValue()) {
+                keyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
+            }
+            keyPreviewPopupDismissDelay.setEnabled(
+                    Settings.readKeyPreviewPopupEnabled(prefs, res));
+        }
+
+        if (!res.getBoolean(R.bool.config_setup_wizard_available)) {
+            removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
+        }
+
+        if (ProductionFlags.IS_METRICS_LOGGING_SUPPORTED) {
+            final Preference enableMetricsLogging =
+                    findPreference(Settings.PREF_ENABLE_METRICS_LOGGING);
+            if (enableMetricsLogging != null) {
+                final int applicationLabelRes = context.getApplicationInfo().labelRes;
+                final String applicationName = res.getString(applicationLabelRes);
+                final String enableMetricsLoggingTitle = res.getString(
+                        R.string.enable_metrics_logging, applicationName);
+                enableMetricsLogging.setTitle(enableMetricsLoggingTitle);
+            }
+        } else {
+            removePreference(Settings.PREF_ENABLE_METRICS_LOGGING);
+        }
+
+        setupKeypressVibrationDurationSettings();
+        setupKeypressSoundVolumeSettings();
+        refreshEnablingsOfKeypressSoundAndVibrationSettings();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+        final TwoStatePreference showSetupWizardIcon =
+                (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
+        if (showSetupWizardIcon != null) {
+            showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity()));
+        }
+        updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        final Resources res = getResources();
+        if (key.equals(Settings.PREF_POPUP_ON)) {
+            setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+                    Settings.readKeyPreviewPopupEnabled(prefs, res));
+        } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
+            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity());
+        }
+        updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+        refreshEnablingsOfKeypressSoundAndVibrationSettings();
+    }
+
+    private void refreshEnablingsOfKeypressSoundAndVibrationSettings() {
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS,
+                Settings.readVibrationEnabled(prefs, res));
+        setPreferenceEnabled(Settings.PREF_KEYPRESS_SOUND_VOLUME,
+                Settings.readKeypressSoundEnabled(prefs, res));
+    }
+
+    private void setupKeypressVibrationDurationSettings() {
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
+                Settings.PREF_VIBRATION_DURATION_SETTINGS);
+        if (pref == null) {
+            return;
+        }
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putInt(key, value).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return Settings.readKeypressVibrationDuration(prefs, res);
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return Settings.readDefaultKeypressVibrationDuration(res);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {
+                AudioAndHapticFeedbackManager.getInstance().vibrate(value);
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                if (value < 0) {
+                    return res.getString(R.string.settings_system_default);
+                }
+                return res.getString(R.string.abbreviation_unit_milliseconds, value);
+            }
+        });
+    }
+
+    private void setupKeypressSoundVolumeSettings() {
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
+                Settings.PREF_KEYPRESS_SOUND_VOLUME);
+        if (pref == null) {
+            return;
+        }
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        final AudioManager am = (AudioManager)getActivity().getSystemService(Context.AUDIO_SERVICE);
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            private static final float PERCENTAGE_FLOAT = 100.0f;
+
+            private float getValueFromPercentage(final int percentage) {
+                return percentage / PERCENTAGE_FLOAT;
+            }
+
+            private int getPercentageFromValue(final float floatValue) {
+                return (int)(floatValue * PERCENTAGE_FLOAT);
+            }
+
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return getPercentageFromValue(Settings.readKeypressSoundVolume(prefs, res));
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return getPercentageFromValue(Settings.readDefaultKeypressSoundVolume(res));
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                if (value < 0) {
+                    return res.getString(R.string.settings_system_default);
+                }
+                return Integer.toString(value);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {
+                am.playSoundEffect(
+                        AudioManager.FX_KEYPRESS_STANDARD, getValueFromPercentage(value));
+            }
+        });
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
new file mode 100644
index 0000000..ec29a7e
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
@@ -0,0 +1,123 @@
+/*
+ * 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.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+
+import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
+import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
+
+import java.util.TreeSet;
+
+/**
+ * "Text correction" settings sub screen.
+ *
+ * This settings sub screen handles the following text correction preferences.
+ * - Personal dictionary
+ * - Add-on dictionaries
+ * - Block offensive words
+ * - Auto-correction
+ * - Show correction suggestions
+ * - Personalized suggestions
+ * - Suggest Contact names
+ * - Next-word suggestions
+ */
+public final class CorrectionSettingsFragment extends SubScreenFragment {
+    private static final boolean DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = false;
+    private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS =
+            DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS
+            || Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2;
+
+    @Override
+    public void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_correction);
+
+        final Context context = getActivity();
+        final PackageManager pm = context.getPackageManager();
+
+        ensureConsistencyOfAutoCorrectionSettings();
+
+        final Preference dictionaryLink = findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
+        final Intent intent = dictionaryLink.getIntent();
+        intent.setClassName(context.getPackageName(), DictionarySettingsActivity.class.getName());
+        final int number = pm.queryIntentActivities(intent, 0).size();
+        if (0 >= number) {
+            removePreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
+        }
+
+        final Preference editPersonalDictionary =
+                findPreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY);
+        final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent();
+        final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS ? null
+                : pm.resolveActivity(
+                        editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY);
+        if (ri == null) {
+            overwriteUserDictionaryPreference(editPersonalDictionary);
+        }
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        ensureConsistencyOfAutoCorrectionSettings();
+    }
+
+    private void ensureConsistencyOfAutoCorrectionSettings() {
+        final String autoCorrectionOff = getString(
+                R.string.auto_correction_threshold_mode_index_off);
+        final ListPreference autoCorrectionThresholdPref = (ListPreference)findPreference(
+                Settings.PREF_AUTO_CORRECTION_THRESHOLD);
+        final String currentSetting = autoCorrectionThresholdPref.getValue();
+        setPreferenceEnabled(
+                Settings.PREF_BIGRAM_PREDICTIONS, !currentSetting.equals(autoCorrectionOff));
+    }
+
+    private void overwriteUserDictionaryPreference(final Preference userDictionaryPreference) {
+        final Activity activity = getActivity();
+        final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity);
+        if (null == localeList) {
+            // The locale list is null if and only if the user dictionary service is
+            // not present or disabled. In this case we need to remove the preference.
+            getPreferenceScreen().removePreference(userDictionaryPreference);
+        } else if (localeList.size() <= 1) {
+            userDictionaryPreference.setFragment(UserDictionarySettings.class.getName());
+            // If the size of localeList is 0, we don't set the locale parameter in the
+            // extras. This will be interpreted by the UserDictionarySettings class as
+            // meaning "the current locale".
+            // Note that with the current code for UserDictionaryList#getUserDictionaryLocalesSet()
+            // the locale list always has at least one element, since it always includes the current
+            // locale explicitly. @see UserDictionaryList.getUserDictionaryLocalesSet().
+            if (localeList.size() == 1) {
+                final String locale = (String)localeList.toArray()[0];
+                userDictionaryPreference.getExtras().putString("locale", locale);
+            }
+        } else {
+            userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
similarity index 98%
rename from java/src/com/android/inputmethod/latin/settings/AdditionalSubtypeSettings.java
rename to java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
index ad411f9..21f2afd 100644
--- a/java/src/com/android/inputmethod/latin/settings/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
@@ -43,7 +43,6 @@
 import android.widget.Toast;
 
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
@@ -54,7 +53,7 @@
 import java.util.ArrayList;
 import java.util.TreeSet;
 
-public final class AdditionalSubtypeSettings extends PreferenceFragment {
+public final class CustomInputStyleSettingsFragment extends PreferenceFragment {
     private RichInputMethodManager mRichImm;
     private SharedPreferences mPrefs;
     private SubtypeLocaleAdapter mSubtypeLocaleAdapter;
@@ -124,9 +123,8 @@
             if (localeString.equals(SubtypeLocaleUtils.NO_LANGUAGE)) {
                 final String displayName = context.getString(R.string.subtype_no_language);
                 return new SubtypeLocaleItem(localeString, displayName);
-            } else {
-                return new SubtypeLocaleItem(localeString);
             }
+            return new SubtypeLocaleItem(localeString);
         }
     }
 
@@ -385,7 +383,7 @@
         }
     }
 
-    public AdditionalSubtypeSettings() {
+    public CustomInputStyleSettingsFragment() {
         // Empty constructor for fragment generation.
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index e4271ad..dce11b4 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -16,28 +16,7 @@
 
 package com.android.inputmethod.latin.settings;
 
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.os.Process;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceScreen;
-import android.preference.TwoStatePreference;
-
-import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.debug.ExternalDictionaryGetterForDebug;
-import com.android.inputmethod.latin.utils.ApplicationUtils;
-import com.android.inputmethod.latin.utils.ResourceUtils;
-
-public final class DebugSettings extends PreferenceFragment
-        implements SharedPreferences.OnSharedPreferenceChangeListener {
-
+public final class DebugSettings {
     public static final String PREF_DEBUG_MODE = "debug_mode";
     public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
     public static final String PREF_KEY_PREVIEW_SHOW_UP_START_SCALE =
@@ -48,251 +27,10 @@
             "pref_key_preview_show_up_duration";
     public static final String PREF_KEY_PREVIEW_DISMISS_DURATION =
             "pref_key_preview_dismiss_duration";
-    private static final String PREF_READ_EXTERNAL_DICTIONARY = "read_external_dictionary";
-    private static final String PREF_KEY_DUMP_DICTS = "pref_key_dump_dictionaries";
-    private static final String PREF_KEY_DUMP_DICT_PREFIX = "pref_key_dump_dictionaries";
-    private static final String DICT_NAME_KEY_FOR_EXTRAS = "dict_name";
     public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview";
     public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
 
-    private boolean mServiceNeedsRestart = false;
-    private TwoStatePreference mDebugMode;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.prefs_screen_debug);
-        TwoStatePreferenceHelper.replaceCheckBoxPreferencesBySwitchPreferences(
-                getPreferenceScreen());
-        SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-        prefs.registerOnSharedPreferenceChangeListener(this);
-
-        final PreferenceScreen readExternalDictionary =
-                (PreferenceScreen) findPreference(PREF_READ_EXTERNAL_DICTIONARY);
-        if (null != readExternalDictionary) {
-            readExternalDictionary.setOnPreferenceClickListener(
-                    new Preference.OnPreferenceClickListener() {
-                        @Override
-                        public boolean onPreferenceClick(final Preference arg0) {
-                            ExternalDictionaryGetterForDebug.chooseAndInstallDictionary(
-                                    getActivity());
-                            mServiceNeedsRestart = true;
-                            return true;
-                        }
-                    });
-        }
-
-        final PreferenceGroup dictDumpPreferenceGroup =
-                (PreferenceGroup)findPreference(PREF_KEY_DUMP_DICTS);
-        final OnPreferenceClickListener dictDumpPrefClickListener =
-                new DictDumpPrefClickListener(this);
-        for (final String dictName : DictionaryFacilitator.DICT_TYPE_TO_CLASS.keySet()) {
-            final Preference preference = new Preference(getActivity());
-            preference.setKey(PREF_KEY_DUMP_DICT_PREFIX + dictName);
-            preference.setTitle("Dump " + dictName + " dictionary");
-            preference.setOnPreferenceClickListener(dictDumpPrefClickListener);
-            preference.getExtras().putString(DICT_NAME_KEY_FOR_EXTRAS, dictName);
-            dictDumpPreferenceGroup.addPreference(preference);
-        }
-        final Resources res = getResources();
-        setupKeyLongpressTimeoutSettings(prefs, res);
-        setupKeyPreviewAnimationDuration(prefs, res, PREF_KEY_PREVIEW_SHOW_UP_DURATION,
-                res.getInteger(R.integer.config_key_preview_show_up_duration));
-        setupKeyPreviewAnimationDuration(prefs, res, PREF_KEY_PREVIEW_DISMISS_DURATION,
-                res.getInteger(R.integer.config_key_preview_dismiss_duration));
-        setupKeyPreviewAnimationScale(prefs, res, PREF_KEY_PREVIEW_SHOW_UP_START_SCALE,
-                ResourceUtils.getFloatFromFraction(
-                        res, R.fraction.config_key_preview_show_up_start_scale));
-        setupKeyPreviewAnimationScale(prefs, res, PREF_KEY_PREVIEW_DISMISS_END_SCALE,
-                ResourceUtils.getFloatFromFraction(
-                        res, R.fraction.config_key_preview_dismiss_end_scale));
-
-        mServiceNeedsRestart = false;
-        mDebugMode = (TwoStatePreference) findPreference(PREF_DEBUG_MODE);
-        updateDebugMode();
-    }
-
-    private static class DictDumpPrefClickListener implements OnPreferenceClickListener {
-        final PreferenceFragment mPreferenceFragment;
-
-        public DictDumpPrefClickListener(final PreferenceFragment preferenceFragment) {
-            mPreferenceFragment = preferenceFragment;
-        }
-
-        @Override
-        public boolean onPreferenceClick(final Preference arg0) {
-            final String dictName = arg0.getExtras().getString(DICT_NAME_KEY_FOR_EXTRAS);
-            if (dictName != null) {
-                final Intent intent =
-                        new Intent(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
-                intent.putExtra(DictionaryDumpBroadcastReceiver.DICTIONARY_NAME_KEY, dictName);
-                mPreferenceFragment.getActivity().sendBroadcast(intent);
-            }
-            return true;
-        }
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-        if (mServiceNeedsRestart) {
-            Process.killProcess(Process.myPid());
-        }
-    }
-
-    @Override
-    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
-        if (key.equals(PREF_DEBUG_MODE) && mDebugMode != null) {
-            mDebugMode.setChecked(prefs.getBoolean(PREF_DEBUG_MODE, false));
-            updateDebugMode();
-            mServiceNeedsRestart = true;
-            return;
-        }
-        if (key.equals(PREF_FORCE_NON_DISTINCT_MULTITOUCH)) {
-            mServiceNeedsRestart = true;
-            return;
-        }
-    }
-
-    private void updateDebugMode() {
-        if (mDebugMode == null) {
-            return;
-        }
-        boolean isDebugMode = mDebugMode.isChecked();
-        final String version = getResources().getString(
-                R.string.version_text, ApplicationUtils.getVersionName(getActivity()));
-        if (!isDebugMode) {
-            mDebugMode.setTitle(version);
-            mDebugMode.setSummary("");
-        } else {
-            mDebugMode.setTitle(getResources().getString(R.string.prefs_debug_mode));
-            mDebugMode.setSummary(version);
-        }
-    }
-
-    private void setupKeyLongpressTimeoutSettings(final SharedPreferences sp,
-            final Resources res) {
-        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
-                PREF_KEY_LONGPRESS_TIMEOUT);
-        if (pref == null) {
-            return;
-        }
-        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
-            @Override
-            public void writeValue(final int value, final String key) {
-                sp.edit().putInt(key, value).apply();
-            }
-
-            @Override
-            public void writeDefaultValue(final String key) {
-                sp.edit().remove(key).apply();
-            }
-
-            @Override
-            public int readValue(final String key) {
-                return Settings.readKeyLongpressTimeout(sp, res);
-            }
-
-            @Override
-            public int readDefaultValue(final String key) {
-                return Settings.readDefaultKeyLongpressTimeout(res);
-            }
-
-            @Override
-            public String getValueText(final int value) {
-                return res.getString(R.string.abbreviation_unit_milliseconds, value);
-            }
-
-            @Override
-            public void feedbackValue(final int value) {}
-        });
-    }
-
-    private void setupKeyPreviewAnimationScale(final SharedPreferences sp, final Resources res,
-            final String prefKey, final float defaultValue) {
-        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
-        if (pref == null) {
-            return;
-        }
-        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
-            private static final float PERCENTAGE_FLOAT = 100.0f;
-
-            private float getValueFromPercentage(final int percentage) {
-                return percentage / PERCENTAGE_FLOAT;
-            }
-
-            private int getPercentageFromValue(final float floatValue) {
-                return (int)(floatValue * PERCENTAGE_FLOAT);
-            }
-
-            @Override
-            public void writeValue(final int value, final String key) {
-                sp.edit().putFloat(key, getValueFromPercentage(value)).apply();
-            }
-
-            @Override
-            public void writeDefaultValue(final String key) {
-                sp.edit().remove(key).apply();
-            }
-
-            @Override
-            public int readValue(final String key) {
-                return getPercentageFromValue(
-                        Settings.readKeyPreviewAnimationScale(sp, key, defaultValue));
-            }
-
-            @Override
-            public int readDefaultValue(final String key) {
-                return getPercentageFromValue(defaultValue);
-            }
-
-            @Override
-            public String getValueText(final int value) {
-                if (value < 0) {
-                    return res.getString(R.string.settings_system_default);
-                }
-                return String.format("%d%%", value);
-            }
-
-            @Override
-            public void feedbackValue(final int value) {}
-        });
-    }
-
-    private void setupKeyPreviewAnimationDuration(final SharedPreferences sp, final Resources res,
-            final String prefKey, final int defaultValue) {
-        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
-        if (pref == null) {
-            return;
-        }
-        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
-            @Override
-            public void writeValue(final int value, final String key) {
-                sp.edit().putInt(key, value).apply();
-            }
-
-            @Override
-            public void writeDefaultValue(final String key) {
-                sp.edit().remove(key).apply();
-            }
-
-            @Override
-            public int readValue(final String key) {
-                return Settings.readKeyPreviewAnimationDuration(sp, key, defaultValue);
-            }
-
-            @Override
-            public int readDefaultValue(final String key) {
-                return defaultValue;
-            }
-
-            @Override
-            public String getValueText(final int value) {
-                return res.getString(R.string.abbreviation_unit_milliseconds, value);
-            }
-
-            @Override
-            public void feedbackValue(final int value) {}
-        });
+    private DebugSettings() {
+        // This class is not publicly instantiable.
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
new file mode 100644
index 0000000..4e41d52
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
@@ -0,0 +1,283 @@
+/*
+ * 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.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Process;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceGroup;
+import android.preference.TwoStatePreference;
+
+import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
+import com.android.inputmethod.latin.DictionaryFacilitator;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.debug.ExternalDictionaryGetterForDebug;
+import com.android.inputmethod.latin.utils.ApplicationUtils;
+import com.android.inputmethod.latin.utils.ResourceUtils;
+
+import java.util.Locale;
+
+/**
+ * "Debug mode" settings sub screen.
+ *
+ * This settings sub screen handles a several preference options for debugging.
+ */
+public final class DebugSettingsFragment extends SubScreenFragment
+        implements OnPreferenceClickListener {
+    private static final String PREF_READ_EXTERNAL_DICTIONARY = "read_external_dictionary";
+    private static final String PREF_KEY_DUMP_DICTS = "pref_key_dump_dictionaries";
+    private static final String PREF_KEY_DUMP_DICT_PREFIX = "pref_key_dump_dictionaries";
+
+    private boolean mServiceNeedsRestart = false;
+    private Preference mReadExternalDictionaryPref;
+    private TwoStatePreference mDebugMode;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_debug);
+
+        mReadExternalDictionaryPref = findPreference(PREF_READ_EXTERNAL_DICTIONARY);
+        if (mReadExternalDictionaryPref != null) {
+            mReadExternalDictionaryPref.setOnPreferenceClickListener(this);
+        }
+
+        final PreferenceGroup dictDumpPreferenceGroup =
+                (PreferenceGroup)findPreference(PREF_KEY_DUMP_DICTS);
+        for (final String dictName : DictionaryFacilitator.DICT_TYPE_TO_CLASS.keySet()) {
+            final Preference pref = new DictDumpPreference(getActivity(), dictName);
+            pref.setOnPreferenceClickListener(this);
+            dictDumpPreferenceGroup.addPreference(pref);
+        }
+        final Resources res = getResources();
+        setupKeyLongpressTimeoutSettings();
+        setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
+                res.getInteger(R.integer.config_key_preview_show_up_duration));
+        setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
+                res.getInteger(R.integer.config_key_preview_dismiss_duration));
+        setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_SCALE,
+                ResourceUtils.getFloatFromFraction(
+                        res, R.fraction.config_key_preview_show_up_start_scale));
+        setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_SCALE,
+                ResourceUtils.getFloatFromFraction(
+                        res, R.fraction.config_key_preview_dismiss_end_scale));
+
+        mServiceNeedsRestart = false;
+        mDebugMode = (TwoStatePreference) findPreference(DebugSettings.PREF_DEBUG_MODE);
+        updateDebugMode();
+    }
+
+    private static class DictDumpPreference extends Preference {
+        public final String mDictName;
+
+        public DictDumpPreference(final Context context, final String dictName) {
+            super(context);
+            setKey(PREF_KEY_DUMP_DICT_PREFIX + dictName);
+            setTitle("Dump " + dictName + " dictionary");
+            mDictName = dictName;
+        }
+    }
+
+    @Override
+    public boolean onPreferenceClick(final Preference pref) {
+        final Context context = getActivity();
+        if (pref == mReadExternalDictionaryPref) {
+            ExternalDictionaryGetterForDebug.chooseAndInstallDictionary(context);
+            mServiceNeedsRestart = true;
+            return true;
+        }
+        if (pref instanceof DictDumpPreference) {
+            final DictDumpPreference dictDumpPref = (DictDumpPreference)pref;
+            final String dictName = dictDumpPref.mDictName;
+            final Intent intent = new Intent(
+                    DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
+            intent.putExtra(DictionaryDumpBroadcastReceiver.DICTIONARY_NAME_KEY, dictName);
+            context.sendBroadcast(intent);
+            return true;
+        }
+        return true;
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        if (mServiceNeedsRestart) {
+            Process.killProcess(Process.myPid());
+        }
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        if (key.equals(DebugSettings.PREF_DEBUG_MODE) && mDebugMode != null) {
+            mDebugMode.setChecked(prefs.getBoolean(DebugSettings.PREF_DEBUG_MODE, false));
+            updateDebugMode();
+            mServiceNeedsRestart = true;
+            return;
+        }
+        if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)) {
+            mServiceNeedsRestart = true;
+            return;
+        }
+    }
+
+    private void updateDebugMode() {
+        boolean isDebugMode = mDebugMode.isChecked();
+        final String version = getString(
+                R.string.version_text, ApplicationUtils.getVersionName(getActivity()));
+        if (!isDebugMode) {
+            mDebugMode.setTitle(version);
+            mDebugMode.setSummary(null);
+        } else {
+            mDebugMode.setTitle(getString(R.string.prefs_debug_mode));
+            mDebugMode.setSummary(version);
+        }
+    }
+
+    private void setupKeyLongpressTimeoutSettings() {
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
+                DebugSettings.PREF_KEY_LONGPRESS_TIMEOUT);
+        if (pref == null) {
+            return;
+        }
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putInt(key, value).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return Settings.readKeyLongpressTimeout(prefs, res);
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return Settings.readDefaultKeyLongpressTimeout(res);
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                return res.getString(R.string.abbreviation_unit_milliseconds, value);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {}
+        });
+    }
+
+    private void setupKeyPreviewAnimationScale(final String prefKey, final float defaultValue) {
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
+        if (pref == null) {
+            return;
+        }
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            private static final float PERCENTAGE_FLOAT = 100.0f;
+
+            private float getValueFromPercentage(final int percentage) {
+                return percentage / PERCENTAGE_FLOAT;
+            }
+
+            private int getPercentageFromValue(final float floatValue) {
+                return (int)(floatValue * PERCENTAGE_FLOAT);
+            }
+
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return getPercentageFromValue(
+                        Settings.readKeyPreviewAnimationScale(prefs, key, defaultValue));
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return getPercentageFromValue(defaultValue);
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                if (value < 0) {
+                    return res.getString(R.string.settings_system_default);
+                }
+                return String.format(Locale.ROOT, "%d%%", value);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {}
+        });
+    }
+
+    private void setupKeyPreviewAnimationDuration(final String prefKey, final int defaultValue) {
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
+        if (pref == null) {
+            return;
+        }
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putInt(key, value).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return Settings.readKeyPreviewAnimationDuration(prefs, key, defaultValue);
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return defaultValue;
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                return res.getString(R.string.abbreviation_unit_milliseconds, value);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {}
+        });
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
new file mode 100644
index 0000000..b95c356
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
@@ -0,0 +1,44 @@
+/*
+ * 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.content.SharedPreferences;
+import android.os.Bundle;
+
+import com.android.inputmethod.latin.R;
+
+/**
+ * "Gesture typing preferences" settings sub screen.
+ *
+ * This settings sub screen handles the following gesture typing preferences.
+ * - Enable gesture typing
+ * - Dynamic floating preview
+ * - Show gesture trail
+ * - Phrase gesture
+ */
+public final class GestureSettingsFragment extends SubScreenFragment {
+    @Override
+    public void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_gesture);
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        // Nothing to do here.
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java
new file mode 100644
index 0000000..f459d68
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/InputSettingsFragment.java
@@ -0,0 +1,100 @@
+/*
+ * 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.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.Preference;
+
+import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.SubtypeSwitcher;
+
+/**
+ * "Input preferences" settings sub screen.
+ *
+ * This settings sub screen handles the following input preferences.
+ * - Auto-capitalization
+ * - Double-space period
+ * - Vibrate on keypress
+ * - Sound on keypress
+ * - Popup on keypress
+ * - Voice input key
+ */
+public final class InputSettingsFragment extends SubScreenFragment {
+    @Override
+    public void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_input);
+
+        final Resources res = getResources();
+        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()}.
+        SubtypeSwitcher.init(context);
+
+        final boolean showVoiceKeyOption = res.getBoolean(
+                R.bool.config_enable_show_voice_key_option);
+        if (!showVoiceKeyOption) {
+            removePreference(Settings.PREF_VOICE_INPUT_KEY);
+        }
+        if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) {
+            removePreference(Settings.PREF_VIBRATE_ON);
+        }
+        if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
+            removePreference(Settings.PREF_POPUP_ON);
+        }
+
+        refreshEnablingsOfKeypressSoundAndVibrationSettings();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY);
+        if (voiceInputKeyOption != null) {
+            final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance()
+                    .isShortcutImeEnabled();
+            voiceInputKeyOption.setEnabled(isShortcutImeEnabled);
+            voiceInputKeyOption.setSummary(
+                    isShortcutImeEnabled ? null : getText(R.string.voice_input_disabled_summary));
+        }
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        final Resources res = getResources();
+        if (key.equals(Settings.PREF_POPUP_ON)) {
+            setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+                    Settings.readKeyPreviewPopupEnabled(prefs, res));
+        }
+        refreshEnablingsOfKeypressSoundAndVibrationSettings();
+    }
+
+    private void refreshEnablingsOfKeypressSoundAndVibrationSettings() {
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS,
+                Settings.readVibrationEnabled(prefs, res));
+        setPreferenceEnabled(Settings.PREF_KEYPRESS_SOUND_VOLUME,
+                Settings.readKeypressSoundEnabled(prefs, res));
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
new file mode 100644
index 0000000..f40106b
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
@@ -0,0 +1,86 @@
+/*
+ * 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.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.
+ *
+ * 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);
+
+        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();
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        // Nothing to do here.
+    }
+
+    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/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
index c899507..b0c4940 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
@@ -18,11 +18,36 @@
 
 import com.android.inputmethod.latin.utils.FragmentUtils;
 
+import android.app.ActionBar;
 import android.content.Intent;
+import android.os.Bundle;
 import android.preference.PreferenceActivity;
+import android.view.MenuItem;
 
 public final class SettingsActivity extends PreferenceActivity {
+    public static final String EXTRA_SHOW_HOME_AS_UP = "show_home_as_up";
     private static final String DEFAULT_FRAGMENT = SettingsFragment.class.getName();
+    private boolean mShowHomeAsUp;
+
+    @Override
+    protected void onCreate(final Bundle savedState) {
+        super.onCreate(savedState);
+        final ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            mShowHomeAsUp = getIntent().getBooleanExtra(EXTRA_SHOW_HOME_AS_UP, true);
+            actionBar.setDisplayHomeAsUpEnabled(mShowHomeAsUp);
+            actionBar.setHomeButtonEnabled(mShowHomeAsUp);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        if (mShowHomeAsUp && item.getItemId() == android.R.id.home) {
+            finish();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
 
     @Override
     public Intent getIntent() {
@@ -35,9 +60,8 @@
         return intent;
     }
 
-    // TODO: Uncomment the override annotation once we start using SDK version 19.
-    // @Override
-    public boolean isValidFragment(String fragmentName) {
+    @Override
+    public boolean isValidFragment(final String fragmentName) {
         return FragmentUtils.isValidFragment(fragmentName);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index b289174..9364520 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -21,59 +21,30 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.media.AudioManager;
-import android.os.Build;
 import android.os.Bundle;
 import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
-import android.preference.TwoStatePreference;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
 import com.android.inputmethod.keyboard.KeyboardTheme;
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.define.ProductionFlags;
-import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
-import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
-import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
-import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.FeedbackUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 import com.android.inputmethodcommon.InputMethodSettingsFragment;
 
-import java.util.TreeSet;
-
 public final class SettingsFragment extends InputMethodSettingsFragment
         implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = SettingsFragment.class.getSimpleName();
-    private static final boolean DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = false;
-    private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS =
-            DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS
-            || Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2;
 
     private static final int NO_MENU_GROUP = Menu.NONE; // We don't care about menu grouping.
     private static final int MENU_FEEDBACK = Menu.FIRST; // The first menu item id and order.
     private static final int MENU_ABOUT = Menu.FIRST + 1; // The second menu item id and order.
 
-    private void setPreferenceEnabled(final String preferenceKey, final boolean enabled) {
-        final Preference preference = findPreference(preferenceKey);
-        if (preference != null) {
-            preference.setEnabled(enabled);
-        }
-    }
-
     private void updateListPreferenceSummaryToCurrentValue(final String prefKey) {
         // Because the "%s" summary trick of {@link ListPreference} doesn't work properly before
         // KitKat, we need to update the summary programmatically.
@@ -86,16 +57,6 @@
         listPreference.setSummary(entryIndex < 0 ? null : entries[entryIndex]);
     }
 
-    private static void removePreference(final String preferenceKey, final PreferenceGroup parent) {
-        if (parent == null) {
-            return;
-        }
-        final Preference preference = parent.findPreference(preferenceKey);
-        if (preference != null) {
-            parent.removePreference(preference);
-        }
-    }
-
     @Override
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
@@ -114,140 +75,22 @@
         // 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()}.
-        SubtypeSwitcher.init(context);
-        SubtypeLocaleUtils.init(context);
         AudioAndHapticFeedbackManager.init(context);
 
         final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
         prefs.registerOnSharedPreferenceChangeListener(this);
 
-        ensureConsistencyOfAutoCorrectionSettings();
-
-        final PreferenceScreen inputScreen =
-                (PreferenceScreen) findPreference(Settings.SCREEN_INPUT);
-        final PreferenceScreen multiLingualScreen =
-                (PreferenceScreen) findPreference(Settings.SCREEN_MULTI_LINGUAL);
-        final PreferenceScreen gestureScreen =
-                (PreferenceScreen) findPreference(Settings.SCREEN_GESTURE);
-        final PreferenceScreen correctionScreen =
-                (PreferenceScreen) findPreference(Settings.SCREEN_CORRECTION);
-        final PreferenceScreen advancedScreen =
-                (PreferenceScreen) findPreference(Settings.SCREEN_ADVANCED);
-        final PreferenceScreen debugScreen =
-                (PreferenceScreen) findPreference(Settings.SCREEN_DEBUG);
-
-        if (!Settings.isInternal(prefs)) {
-            advancedScreen.removePreference(debugScreen);
-        }
-
-        final boolean showVoiceKeyOption = res.getBoolean(
-                R.bool.config_enable_show_voice_key_option);
-        if (!showVoiceKeyOption) {
-            removePreference(Settings.PREF_VOICE_INPUT_KEY, inputScreen);
-        }
-
-        if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) {
-            removePreference(Settings.PREF_VIBRATE_ON, inputScreen);
-            removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedScreen);
-        }
-        if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) {
-            removePreference(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, multiLingualScreen);
-            removePreference(
-                    Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, multiLingualScreen);
-        }
-
-        // TODO: consolidate key preview dismiss delay with the key preview animation parameters.
-        if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
-            removePreference(Settings.PREF_POPUP_ON, inputScreen);
-            removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedScreen);
-        } else {
-            // TODO: Cleanup this setup.
-            final ListPreference keyPreviewPopupDismissDelay =
-                    (ListPreference) findPreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
-            final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
-                    R.integer.config_key_preview_linger_timeout));
-            keyPreviewPopupDismissDelay.setEntries(new String[] {
-                    res.getString(R.string.key_preview_popup_dismiss_no_delay),
-                    res.getString(R.string.key_preview_popup_dismiss_default_delay),
-            });
-            keyPreviewPopupDismissDelay.setEntryValues(new String[] {
-                    "0",
-                    popupDismissDelayDefaultValue
-            });
-            if (null == keyPreviewPopupDismissDelay.getValue()) {
-                keyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
-            }
-            keyPreviewPopupDismissDelay.setEnabled(
-                    Settings.readKeyPreviewPopupEnabled(prefs, res));
-        }
-
-        if (!res.getBoolean(R.bool.config_setup_wizard_available)) {
-            removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedScreen);
-        }
-
-        final PreferenceScreen dictionaryLink =
-                (PreferenceScreen) findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
-        final Intent intent = dictionaryLink.getIntent();
-        intent.setClassName(context.getPackageName(), DictionarySettingsActivity.class.getName());
-        final int number = context.getPackageManager().queryIntentActivities(intent, 0).size();
-        if (0 >= number) {
-            correctionScreen.removePreference(dictionaryLink);
-        }
-
-        if (ProductionFlags.IS_METRICS_LOGGING_SUPPORTED) {
-            final Preference enableMetricsLogging =
-                    findPreference(Settings.PREF_ENABLE_METRICS_LOGGING);
-            if (enableMetricsLogging != null) {
-                final int applicationLabelRes = context.getApplicationInfo().labelRes;
-                final String applicationName = res.getString(applicationLabelRes);
-                final String enableMetricsLoggingTitle = res.getString(
-                        R.string.enable_metrics_logging, applicationName);
-                enableMetricsLogging.setTitle(enableMetricsLoggingTitle);
-            }
-        } else {
-            removePreference(Settings.PREF_ENABLE_METRICS_LOGGING, advancedScreen);
-        }
-
-        final Preference editPersonalDictionary =
-                findPreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY);
-        final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent();
-        final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS ? null
-                : context.getPackageManager().resolveActivity(
-                        editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY);
-        if (ri == null) {
-            overwriteUserDictionaryPreference(editPersonalDictionary);
-        }
-
         if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) {
-            getPreferenceScreen().removePreference(gestureScreen);
+            getPreferenceScreen().removePreference(findPreference(Settings.SCREEN_GESTURE));
         }
 
         AdditionalFeaturesSettingUtils.addAdditionalFeaturesPreferences(context, this);
-
-        setupKeypressVibrationDurationSettings(prefs, res);
-        setupKeypressSoundVolumeSettings(prefs, res);
-        refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res);
     }
 
     @Override
     public void onResume() {
         super.onResume();
         final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-        final Resources res = getResources();
-        final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY);
-        if (voiceInputKeyOption != null) {
-            final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance()
-                    .isShortcutImeEnabled();
-            voiceInputKeyOption.setEnabled(isShortcutImeEnabled);
-            voiceInputKeyOption.setSummary(isShortcutImeEnabled ? null
-                    : res.getText(R.string.voice_input_disabled_summary));
-        }
-        final TwoStatePreference showSetupWizardIcon =
-                (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
-        if (showSetupWizardIcon != null) {
-            showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity()));
-        }
-        updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
         final ListPreference keyboardThemePref = (ListPreference)findPreference(
                 Settings.PREF_KEYBOARD_THEME);
         if (keyboardThemePref != null) {
@@ -258,7 +101,6 @@
             keyboardThemePref.setSummary(entryIndex < 0 ? null : entries[entryIndex]);
             keyboardThemePref.setValue(value);
         }
-        updateCustomInputStylesSummary(prefs, res);
     }
 
     @Override
@@ -289,171 +131,7 @@
             return;
         }
         (new BackupManager(activity)).dataChanged();
-        final Resources res = getResources();
-        if (key.equals(Settings.PREF_POPUP_ON)) {
-            setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
-                    Settings.readKeyPreviewPopupEnabled(prefs, res));
-        } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
-            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity());
-        }
-        ensureConsistencyOfAutoCorrectionSettings();
-        updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
         updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEYBOARD_THEME);
-        refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources());
-    }
-
-    private void ensureConsistencyOfAutoCorrectionSettings() {
-        final String autoCorrectionOff = getResources().getString(
-                R.string.auto_correction_threshold_mode_index_off);
-        final ListPreference autoCorrectionThresholdPref = (ListPreference)findPreference(
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD);
-        final String currentSetting = autoCorrectionThresholdPref.getValue();
-        setPreferenceEnabled(
-                Settings.PREF_BIGRAM_PREDICTIONS, !currentSetting.equals(autoCorrectionOff));
-    }
-
-    private void updateCustomInputStylesSummary(final SharedPreferences prefs,
-            final Resources res) {
-        final PreferenceScreen customInputStyles =
-                (PreferenceScreen)findPreference(Settings.PREF_CUSTOM_INPUT_STYLES);
-        final String prefSubtype = Settings.readPrefAdditionalSubtypes(prefs, res);
-        final InputMethodSubtype[] subtypes =
-                AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype);
-        final StringBuilder styles = new StringBuilder();
-        for (final InputMethodSubtype subtype : subtypes) {
-            if (styles.length() > 0) styles.append(", ");
-            styles.append(SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype));
-        }
-        customInputStyles.setSummary(styles);
-    }
-
-    private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
-            final SharedPreferences sp, final Resources res) {
-        setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS,
-                Settings.readVibrationEnabled(sp, res));
-        setPreferenceEnabled(Settings.PREF_KEYPRESS_SOUND_VOLUME,
-                Settings.readKeypressSoundEnabled(sp, res));
-    }
-
-    private void setupKeypressVibrationDurationSettings(final SharedPreferences sp,
-            final Resources res) {
-        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
-                Settings.PREF_VIBRATION_DURATION_SETTINGS);
-        if (pref == null) {
-            return;
-        }
-        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
-            @Override
-            public void writeValue(final int value, final String key) {
-                sp.edit().putInt(key, value).apply();
-            }
-
-            @Override
-            public void writeDefaultValue(final String key) {
-                sp.edit().remove(key).apply();
-            }
-
-            @Override
-            public int readValue(final String key) {
-                return Settings.readKeypressVibrationDuration(sp, res);
-            }
-
-            @Override
-            public int readDefaultValue(final String key) {
-                return Settings.readDefaultKeypressVibrationDuration(res);
-            }
-
-            @Override
-            public void feedbackValue(final int value) {
-                AudioAndHapticFeedbackManager.getInstance().vibrate(value);
-            }
-
-            @Override
-            public String getValueText(final int value) {
-                if (value < 0) {
-                    return res.getString(R.string.settings_system_default);
-                }
-                return res.getString(R.string.abbreviation_unit_milliseconds, value);
-            }
-        });
-    }
-
-    private void setupKeypressSoundVolumeSettings(final SharedPreferences sp, final Resources res) {
-        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
-                Settings.PREF_KEYPRESS_SOUND_VOLUME);
-        if (pref == null) {
-            return;
-        }
-        final AudioManager am = (AudioManager)getActivity().getSystemService(Context.AUDIO_SERVICE);
-        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
-            private static final float PERCENTAGE_FLOAT = 100.0f;
-
-            private float getValueFromPercentage(final int percentage) {
-                return percentage / PERCENTAGE_FLOAT;
-            }
-
-            private int getPercentageFromValue(final float floatValue) {
-                return (int)(floatValue * PERCENTAGE_FLOAT);
-            }
-
-            @Override
-            public void writeValue(final int value, final String key) {
-                sp.edit().putFloat(key, getValueFromPercentage(value)).apply();
-            }
-
-            @Override
-            public void writeDefaultValue(final String key) {
-                sp.edit().remove(key).apply();
-            }
-
-            @Override
-            public int readValue(final String key) {
-                return getPercentageFromValue(Settings.readKeypressSoundVolume(sp, res));
-            }
-
-            @Override
-            public int readDefaultValue(final String key) {
-                return getPercentageFromValue(Settings.readDefaultKeypressSoundVolume(res));
-            }
-
-            @Override
-            public String getValueText(final int value) {
-                if (value < 0) {
-                    return res.getString(R.string.settings_system_default);
-                }
-                return Integer.toString(value);
-            }
-
-            @Override
-            public void feedbackValue(final int value) {
-                am.playSoundEffect(
-                        AudioManager.FX_KEYPRESS_STANDARD, getValueFromPercentage(value));
-            }
-        });
-    }
-
-    private void overwriteUserDictionaryPreference(Preference userDictionaryPreference) {
-        final Activity activity = getActivity();
-        final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity);
-        if (null == localeList) {
-            // The locale list is null if and only if the user dictionary service is
-            // not present or disabled. In this case we need to remove the preference.
-            getPreferenceScreen().removePreference(userDictionaryPreference);
-        } else if (localeList.size() <= 1) {
-            userDictionaryPreference.setFragment(UserDictionarySettings.class.getName());
-            // If the size of localeList is 0, we don't set the locale parameter in the
-            // extras. This will be interpreted by the UserDictionarySettings class as
-            // meaning "the current locale".
-            // Note that with the current code for UserDictionaryList#getUserDictionaryLocalesSet()
-            // the locale list always has at least one element, since it always includes the current
-            // locale explicitly. @see UserDictionaryList.getUserDictionaryLocalesSet().
-            if (localeList.size() == 1) {
-                final String locale = (String)localeList.toArray()[0];
-                userDictionaryPreference.getExtras().putString("locale", locale);
-            }
-        } else {
-            userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
-        }
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
new file mode 100644
index 0000000..c70bf29
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
@@ -0,0 +1,118 @@
+/*
+ * 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.app.backup.BackupManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+
+/**
+ * A base abstract class for a {@link PreferenceFragment} that implements a nested
+ * {@link PreferenceScreen} of the main preference screen.
+ */
+abstract class SubScreenFragment extends PreferenceFragment
+        implements OnSharedPreferenceChangeListener {
+    private OnSharedPreferenceChangeListener mSharedPreferenceChangeListener;
+
+    static void setPreferenceEnabled(final String prefKey, final boolean enabled,
+            final PreferenceScreen screen) {
+        final Preference preference = screen.findPreference(prefKey);
+        if (preference != null) {
+            preference.setEnabled(enabled);
+        }
+    }
+
+    static void removePreference(final String prefKey, final PreferenceScreen screen) {
+        final Preference preference = screen.findPreference(prefKey);
+        if (preference != null) {
+            screen.removePreference(preference);
+        }
+    }
+
+    static void updateListPreferenceSummaryToCurrentValue(final String prefKey,
+            final PreferenceScreen screen) {
+        // Because the "%s" summary trick of {@link ListPreference} doesn't work properly before
+        // KitKat, we need to update the summary programmatically.
+        final ListPreference listPreference = (ListPreference)screen.findPreference(prefKey);
+        if (listPreference == null) {
+            return;
+        }
+        final CharSequence entries[] = listPreference.getEntries();
+        final int entryIndex = listPreference.findIndexOfValue(listPreference.getValue());
+        listPreference.setSummary(entryIndex < 0 ? null : entries[entryIndex]);
+    }
+
+    final void setPreferenceEnabled(final String prefKey, final boolean enabled) {
+        setPreferenceEnabled(prefKey, enabled, getPreferenceScreen());
+    }
+
+    final void removePreference(final String prefKey) {
+        removePreference(prefKey, getPreferenceScreen());
+    }
+
+    final void updateListPreferenceSummaryToCurrentValue(final String prefKey) {
+        updateListPreferenceSummaryToCurrentValue(prefKey, getPreferenceScreen());
+    }
+
+    final SharedPreferences getSharedPreferences() {
+        return getPreferenceManager().getSharedPreferences();
+    }
+
+    @Override
+    public void addPreferencesFromResource(final int preferencesResId) {
+        super.addPreferencesFromResource(preferencesResId);
+        TwoStatePreferenceHelper.replaceCheckBoxPreferencesBySwitchPreferences(
+                getPreferenceScreen());
+    }
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mSharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
+            @Override
+            public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+                final SubScreenFragment fragment = SubScreenFragment.this;
+                final Context context = fragment.getActivity();
+                if (context == null || fragment.getPreferenceScreen() == null) {
+                    final String tag = fragment.getClass().getSimpleName();
+                    // TODO: Introduce a static function to register this class and ensure that
+                    // onCreate must be called before "onSharedPreferenceChanged" is called.
+                    Log.w(tag, "onSharedPreferenceChanged called before activity starts.");
+                    return;
+                }
+                new BackupManager(context).dataChanged();
+                fragment.onSharedPreferenceChanged(prefs, key);
+            }
+        };
+        getSharedPreferences().registerOnSharedPreferenceChangeListener(
+                mSharedPreferenceChangeListener);
+    }
+
+    @Override
+    public void onDestroy() {
+        getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
+                mSharedPreferenceChangeListener);
+        super.onDestroy();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
index 14ab2db..34e0119 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
@@ -153,7 +153,7 @@
      */
     private SentenceSuggestionsInfo[] splitAndSuggest(TextInfo[] textInfos, int suggestionsLimit) {
         if (textInfos == null || textInfos.length == 0) {
-            return SentenceLevelAdapter.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
+            return SentenceLevelAdapter.getEmptySentenceSuggestionsInfo();
         }
         SentenceLevelAdapter sentenceLevelAdapter;
         synchronized(this) {
@@ -168,7 +168,7 @@
             }
         }
         if (sentenceLevelAdapter == null) {
-            return SentenceLevelAdapter.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
+            return SentenceLevelAdapter.getEmptySentenceSuggestionsInfo();
         }
         final int infosSize = textInfos.length;
         final SentenceSuggestionsInfo[] retval = new SentenceSuggestionsInfo[infosSize];
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
index ae582ea..51c4b1e 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
@@ -35,9 +35,16 @@
  * rewrite everything for any small change.
  */
 public class SentenceLevelAdapter {
-    public static final SentenceSuggestionsInfo[] EMPTY_SENTENCE_SUGGESTIONS_INFOS =
-            new SentenceSuggestionsInfo[] {};
+    private static class EmptySentenceSuggestionsInfosInitializationHolder {
+        public static final SentenceSuggestionsInfo[] EMPTY_SENTENCE_SUGGESTIONS_INFOS =
+                new SentenceSuggestionsInfo[]{};
+    }
     private static final SuggestionsInfo EMPTY_SUGGESTIONS_INFO = new SuggestionsInfo(0, null);
+
+    public static SentenceSuggestionsInfo[] getEmptySentenceSuggestionsInfo() {
+        return EmptySentenceSuggestionsInfosInitializationHolder.EMPTY_SENTENCE_SUGGESTIONS_INFOS;
+    }
+
     /**
      * Container for split TextInfo parameters
      */
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index d76ea10..1979080 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -386,8 +386,7 @@
             final SpacingAndPunctuations spacingAndPunctuations) {
         if (TextUtils.isEmpty(text)) return false;
         final int length = text.length();
-        // TODO: Make this test "length > Constants.DICTIONARY_MAX_WORD_LENGTH".
-        if (length >= Constants.DICTIONARY_MAX_WORD_LENGTH) {
+        if (length > Constants.DICTIONARY_MAX_WORD_LENGTH) {
             return false;
         }
         int i = 0;
diff --git a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
index e300bd1..9858a23 100644
--- a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
@@ -18,8 +18,13 @@
 
 import com.android.inputmethod.dictionarypack.DictionarySettingsFragment;
 import com.android.inputmethod.latin.about.AboutPreferences;
-import com.android.inputmethod.latin.settings.AdditionalSubtypeSettings;
-import com.android.inputmethod.latin.settings.DebugSettings;
+import com.android.inputmethod.latin.settings.AdvancedSettingsFragment;
+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.SettingsFragment;
 import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
 import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordFragment;
@@ -34,8 +39,13 @@
     static {
         sLatinImeFragments.add(DictionarySettingsFragment.class.getName());
         sLatinImeFragments.add(AboutPreferences.class.getName());
-        sLatinImeFragments.add(AdditionalSubtypeSettings.class.getName());
-        sLatinImeFragments.add(DebugSettings.class.getName());
+        sLatinImeFragments.add(InputSettingsFragment.class.getName());
+        sLatinImeFragments.add(MultiLingualSettingsFragment.class.getName());
+        sLatinImeFragments.add(CustomInputStyleSettingsFragment.class.getName());
+        sLatinImeFragments.add(GestureSettingsFragment.class.getName());
+        sLatinImeFragments.add(CorrectionSettingsFragment.class.getName());
+        sLatinImeFragments.add(AdvancedSettingsFragment.class.getName());
+        sLatinImeFragments.add(DebugSettingsFragment.class.getName());
         sLatinImeFragments.add(SettingsFragment.class.getName());
         sLatinImeFragments.add(SpellCheckerSettingsFragment.class.getName());
         sLatinImeFragments.add(UserDictionaryAddWordFragment.class.getName());
diff --git a/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h b/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h
index 661ef1b..aa0d068 100644
--- a/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h
@@ -30,7 +30,7 @@
 
     virtual void getNextBigram(int *const outBigramPos, int *const outProbability,
             bool *const outHasNext, int *const pos) const = 0;
-    virtual void skipAllBigrams(int *const pos) const = 0;
+    virtual bool skipAllBigrams(int *const pos) const = 0;
 
  protected:
     DictionaryBigramsStructurePolicy() {}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
index 6162346..50a4c97 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
@@ -58,8 +58,9 @@
     void getNextBigram(int *const outBigramPos, int *const outProbability,
             bool *const outHasNext, int *const bigramEntryPos) const;
 
-    void skipAllBigrams(int *const pos) const {
+    bool skipAllBigrams(int *const pos) const {
         // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
+        return true;
     }
 
     bool addNewEntry(const int terminalId, const int newTargetTerminalId,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
index 08b4e0b..f7fd5c0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
@@ -38,9 +38,14 @@
 const BigramListReadWriteUtils::BigramFlags
         BigramListReadWriteUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
 
-/* static */ void BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(
-        const uint8_t *const bigramsBuf, BigramFlags *const outBigramFlags,
+/* static */ bool BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(
+        const uint8_t *const bigramsBuf, const int bufSize, BigramFlags *const outBigramFlags,
         int *const outTargetPtNodePos, int *const bigramEntryPos) {
+    if (bufSize <= *bigramEntryPos) {
+        AKLOGE("Read invalid pos in getBigramEntryPropertiesAndAdvancePosition(). bufSize: %d, "
+                "bigramEntryPos: %d.", bufSize, *bigramEntryPos);
+        return false;
+    }
     const BigramFlags bigramFlags = ByteArrayUtils::readUint8AndAdvancePosition(bigramsBuf,
             bigramEntryPos);
     if (outBigramFlags) {
@@ -51,15 +56,19 @@
     if (outTargetPtNodePos) {
         *outTargetPtNodePos = targetPos;
     }
+    return true;
 }
 
-/* static */ void BigramListReadWriteUtils::skipExistingBigrams(const uint8_t *const bigramsBuf,
-        int *const bigramListPos) {
+/* static */ bool BigramListReadWriteUtils::skipExistingBigrams(const uint8_t *const bigramsBuf,
+        const int bufSize, int *const bigramListPos) {
     BigramFlags flags;
     do {
-        getBigramEntryPropertiesAndAdvancePosition(bigramsBuf, &flags, 0 /* outTargetPtNodePos */,
-                bigramListPos);
+        if (!getBigramEntryPropertiesAndAdvancePosition(bigramsBuf, bufSize, &flags,
+                0 /* outTargetPtNodePos */, bigramListPos)) {
+            return false;
+        }
     } while(hasNext(flags));
+    return true;
 }
 
 /* static */ int BigramListReadWriteUtils::getBigramAddressAndAdvancePosition(
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
index 15f924a..10f93fb 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
@@ -30,8 +30,8 @@
 public:
    typedef uint8_t BigramFlags;
 
-   static void getBigramEntryPropertiesAndAdvancePosition(const uint8_t *const bigramsBuf,
-           BigramFlags *const outBigramFlags, int *const outTargetPtNodePos,
+   static bool getBigramEntryPropertiesAndAdvancePosition(const uint8_t *const bigramsBuf,
+           const int bufSize, BigramFlags *const outBigramFlags, int *const outTargetPtNodePos,
            int *const bigramEntryPos);
 
    static AK_FORCE_INLINE int getProbabilityFromFlags(const BigramFlags flags) {
@@ -43,7 +43,8 @@
    }
 
    // Bigrams reading methods
-   static void skipExistingBigrams(const uint8_t *const bigramsBuf, int *const bigramListPos);
+   static bool skipExistingBigrams(const uint8_t *const bigramsBuf, const int bufSize,
+           int *const bigramListPos);
 
 private:
    DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListReadWriteUtils);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
index 00bb502..73e291e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
@@ -27,27 +27,34 @@
 
 class BigramListPolicy : public DictionaryBigramsStructurePolicy {
  public:
-    explicit BigramListPolicy(const uint8_t *const bigramsBuf) : mBigramsBuf(bigramsBuf) {}
+    BigramListPolicy(const uint8_t *const bigramsBuf, const int bufSize)
+            : mBigramsBuf(bigramsBuf), mBufSize(bufSize) {}
 
     ~BigramListPolicy() {}
 
     void getNextBigram(int *const outBigramPos, int *const outProbability, bool *const outHasNext,
             int *const pos) const {
         BigramListReadWriteUtils::BigramFlags flags;
-        BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(mBigramsBuf, &flags,
-                outBigramPos, pos);
+        if (!BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(mBigramsBuf,
+                mBufSize, &flags, outBigramPos, pos)) {
+            AKLOGE("Cannot read bigram entry. mBufSize: %d, pos: %d. ", mBufSize, *pos);
+            *outProbability = NOT_A_PROBABILITY;
+            *outHasNext = false;
+            return;
+        }
         *outProbability = BigramListReadWriteUtils::getProbabilityFromFlags(flags);
         *outHasNext = BigramListReadWriteUtils::hasNext(flags);
     }
 
-    void skipAllBigrams(int *const pos) const {
-        BigramListReadWriteUtils::skipExistingBigrams(mBigramsBuf, pos);
+    bool skipAllBigrams(int *const pos) const {
+        return BigramListReadWriteUtils::skipExistingBigrams(mBigramsBuf, mBufSize, pos);
     }
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListPolicy);
 
     const uint8_t *const mBigramsBuf;
+    const int mBufSize;
 };
 } // namespace latinime
 #endif // LATINIME_BIGRAM_LIST_POLICY_H
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 7fc74be..b909e82 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
@@ -224,7 +224,14 @@
                         mShortcutListPolicy.skipAllShortcuts(&pos);
                     }
                     if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
-                        mBigramListPolicy.skipAllBigrams(&pos);
+                        if (!mBigramListPolicy.skipAllBigrams(&pos)) {
+                            AKLOGE("Cannot skip bigrams. BufSize: %d, pos: %d.", mDictBufferSize,
+                                    pos);
+                            mIsCorrupted = true;
+                            ASSERT(false);
+                            *outUnigramProbability = NOT_A_PROBABILITY;
+                            return 0;
+                        }
                     }
                 }
             } else {
@@ -241,7 +248,13 @@
                     mShortcutListPolicy.skipAllShortcuts(&pos);
                 }
                 if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
-                    mBigramListPolicy.skipAllBigrams(&pos);
+                    if (!mBigramListPolicy.skipAllBigrams(&pos)) {
+                        AKLOGE("Cannot skip bigrams. BufSize: %d, pos: %d.", mDictBufferSize, pos);
+                        mIsCorrupted = true;
+                        ASSERT(false);
+                        *outUnigramProbability = NOT_A_PROBABILITY;
+                        return 0;
+                    }
                 }
             }
 
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 e30c8bf..1dd5705 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
@@ -42,7 +42,7 @@
               mHeaderPolicy(mMmappedBuffer->getBuffer(), FormatUtils::VERSION_2),
               mDictRoot(mMmappedBuffer->getBuffer() + mHeaderPolicy.getSize()),
               mDictBufferSize(mMmappedBuffer->getBufferSize() - mHeaderPolicy.getSize()),
-              mBigramListPolicy(mDictRoot), mShortcutListPolicy(mDictRoot),
+              mBigramListPolicy(mDictRoot, mDictBufferSize), mShortcutListPolicy(mDictRoot),
               mPtNodeReader(mDictRoot, mDictBufferSize, &mBigramListPolicy, &mShortcutListPolicy),
               mPtNodeArrayReader(mDictRoot, mDictBufferSize),
               mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
index 55ba613..4b3bb37 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
@@ -40,8 +40,9 @@
     void getNextBigram(int *const outBigramPos, int *const outProbability,
             bool *const outHasNext, int *const bigramEntryPos) const;
 
-    void skipAllBigrams(int *const pos) const {
+    bool skipAllBigrams(int *const pos) const {
         // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
+        return true;
     }
 
     bool addNewEntry(const int terminalId, const int newTargetTerminalId,