Merge "Import translations. DO NOT MERGE" into nyc-mr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b6b7904..680e179 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -67,6 +67,7 @@
     <uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" />
     <uses-permission android:name="android.permission.READ_PROFILE" />
     <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
+    <uses-permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" />
     <uses-permission android:name="android.permission.SET_TIME" />
     <uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
     <uses-permission android:name="android.permission.REBOOT" />
diff --git a/res/drawable/ic_fingerprint_error.xml b/res/drawable/ic_fingerprint_error.xml
index d00280d..b822d45 100644
--- a/res/drawable/ic_fingerprint_error.xml
+++ b/res/drawable/ic_fingerprint_error.xml
@@ -19,12 +19,12 @@
         android:viewportWidth="32.0"
         android:viewportHeight="32.0">
     <path
-        android:fillColor="@color/warning"
+        android:fillColor="@*android:color/system_error"
         android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
     <path
-        android:fillColor="@color/warning"
+        android:fillColor="@*android:color/system_error"
         android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
     <path
-        android:fillColor="@color/warning"
+        android:fillColor="@*android:color/system_error"
         android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
 </vector>
diff --git a/res/layout/bluetooth_pin_entry.xml b/res/layout/bluetooth_pin_entry.xml
index aa9f187..c309a24 100644
--- a/res/layout/bluetooth_pin_entry.xml
+++ b/res/layout/bluetooth_pin_entry.xml
@@ -28,32 +28,14 @@
         android:layout_width="match_parent"
         android:orientation="vertical">
 
-        <TextView
-            android:id="@+id/message_caption"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
-            android:layout_marginTop="@dimen/bluetooth_dialog_padding"
-            android:gravity="center_vertical"
-            android:textAppearance="@android:style/TextAppearance.Material.Caption" />
-
-        <TextView
-            android:id="@+id/message_subhead"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
-            android:layout_marginBottom="@dimen/bluetooth_dialog_padding"
-            android:gravity="center_vertical"
-            android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
-
         <EditText
             android:id="@+id/text"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+            android:layout_marginStart="@dimen/bluetooth_pairing_edittext_padding"
+            android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+            android:layout_marginTop="11dp"
+            android:minHeight="48dp"
             android:inputType="textPassword"
             android:singleLine="true" />
 
@@ -62,8 +44,9 @@
             android:text="@string/bluetooth_pin_values_hint"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+            android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+            android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+            android:layout_marginBottom="6dp"
             android:gravity="center_vertical"
             android:textAppearance="?android:attr/textAppearanceSmall" />
 
@@ -72,30 +55,37 @@
             android:text="@string/bluetooth_enable_alphanumeric_pin"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+            android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+            android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+            android:layout_marginBottom="16dp"
             android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceSmall" />
+            android:paddingStart="@dimen/bluetooth_checkbox_padding"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary"/>
 
         <TextView
             android:id="@+id/message_below_pin"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+            android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+            android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+            android:layout_marginBottom="12dp"
             android:gravity="center_vertical"
             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:textColor="@*android:color/secondary_text_material_light"/>
+            android:textColor="?android:attr/textColorSecondary"/>
 
         <CheckBox
             android:id="@+id/phonebook_sharing_message_entry_pin"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/bluetooth_dialog_padding"
-            android:layout_marginEnd="@dimen/bluetooth_dialog_padding"
+            android:layout_marginStart="@dimen/bluetooth_pairing_padding"
+            android:layout_marginEnd="@dimen/bluetooth_pairing_padding"
+            android:layout_marginBottom="12dp"
             android:gravity="center_vertical"
+            android:paddingStart="@dimen/bluetooth_checkbox_padding"
             android:text="@string/bluetooth_pairing_shares_phonebook"
-            android:textAppearance="?android:attr/textAppearanceSmall" />
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary"/>
 
     </LinearLayout>
 
diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
index b3500b2..2e5dd5c 100644
--- a/res/layout/dashboard_category.xml
+++ b/res/layout/dashboard_category.xml
@@ -20,8 +20,7 @@
     android:layout_height="@dimen/dashboard_category_height"
     android:orientation="vertical"
     android:paddingBottom="8dip"
-    android:background="@color/card_background"
-    android:importantForAccessibility="noHideDescendants">
+    android:background="@color/card_background">
 
     <TextView android:id="@android:id/title"
         android:layout_width="match_parent"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 4a8cf99..2155245 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -50,16 +50,14 @@
     <color name="setup_wizard_wifi_color_dark">#89ffffff</color>
     <color name="setup_wizard_wifi_color_light">#89000000</color>
 
-    <color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
-
     <color name="lock_pattern_background">#00000000</color>
     <color name="lock_pattern_view_regular_color">#ff37474f</color>
-    <color name="lock_pattern_view_error_color">@color/warning</color>
+    <color name="lock_pattern_view_error_color">@*android:color/system_error</color>
 
     <color name="lock_pattern_view_regular_color_dark">#ffffff</color>
 
     <color name="unlock_pattern_view_regular_color">@android:color/white</color>
-    <color name="unlock_pattern_view_error_color">@color/system_warning_color</color>
+    <color name="unlock_pattern_view_error_color">@*android:color/system_error</color>
 
     <color name="fingerprint_title_area_bg">?android:attr/colorAccent</color>
     <color name="fingerprint_title_color">#ffffffff</color>
@@ -76,7 +74,6 @@
     <color name="wifi_divider">#ffe0e0e0</color>
     <color name="sim_noitification">@*android:color/material_deep_teal_500</color>
 
-    <color name="warning">#ff5621</color>
     <color name="confirm_device_credential_transparent_black">#60000000</color>
     <color name="fab_ripple">#1fffffff</color><!-- 12% white -->
     <color name="fab_shape">?android:attr/colorAccent</color>
@@ -91,7 +88,7 @@
 
     <color name="memory_avg_use">#ff384248</color>
 
-    <color name="zen_rule_name_warning">@color/system_warning_color</color>
+    <color name="zen_rule_name_warning">@*android:color/system_error</color>
 
     <!-- Accent color that matches the settings launcher icon -->
     <color name="icon_accent">#ffabffec</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d65bdfb..2a2b406 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -201,7 +201,9 @@
     <!-- Bluetooth Preferences -->
     <dimen name="bluetooth_dialog_padding">8dip</dimen>
     <integer name="bluetooth_name_length">32</integer>
-    <dimen name="bluetooth_pairing_padding">20dp</dimen>
+    <dimen name="bluetooth_pairing_padding">24dp</dimen>
+    <dimen name="bluetooth_pairing_edittext_padding">21dp</dimen>
+    <dimen name="bluetooth_checkbox_padding">16dp</dimen>
 
     <!-- WiFi Preferences -->
     <dimen name="wifi_divider_height">1px</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9b03fd8..205cfe0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5659,6 +5659,8 @@
     <string name="help_url_fingerprint" translatable="false"></string>
     <!-- Help URL, Gesture settings -->
     <string name="help_url_gestures" translatable="false"></string>
+    <!-- Help URL, Manage Storage [DO NOT TRANSLATE]-->
+    <string name="help_url_manage_storage" translatable="false"></string>
 
     <!-- User account title [CHAR LIMIT=30] -->
     <string name="user_account_title">Account for content</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 87da4b3..12b794a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -219,7 +219,7 @@
         <item name="android:textSize">12sp</item>
         <item name="android:textAlignment">viewStart</item>
         <item name="android:textAppearance">@android:style/TextAppearance.Material.Body1</item>
-        <item name="android:textColor">@color/warning</item>
+        <item name="android:textColor">@*android:color/system_error</item>
     </style>
 
     <style name="wifi_item_content">
@@ -365,7 +365,7 @@
 
     <style name="TextAppearance.FingerprintErrorText"
         parent="android:TextAppearance.Material.Body1">
-        <item name="android:textColor">@color/warning</item>
+        <item name="android:textColor">@*android:color/system_error</item>
     </style>
 
     <style name="TextAppearance.SupportTitle"
@@ -389,7 +389,7 @@
 
     <style name="TextAppearance.ConfirmDeviceCredentialsErrorText"
         parent="android:TextAppearance.Material.Body1">
-        <item name="android:textColor">@color/warning</item>
+        <item name="android:textColor">@*android:color/system_error</item>
     </style>
 
     <style name="TextAppearance.Small.SwitchBar">
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index 2288520..cd3c5ee 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -148,6 +148,13 @@
             android:entries="@array/select_logd_size_titles"
             android:entryValues="@array/select_logd_size_values" />
 
+        <ListPreference
+            android:key="select_logpersist"
+            android:title="@string/select_logpersist_title"
+            android:dialogTitle="@string/select_logpersist_dialog_title"
+            android:entries="@array/select_logpersist_titles"
+            android:entryValues="@array/select_logpersist_values" />
+
     </PreferenceCategory>
 
     <PreferenceCategory android:key="debug_networking_category"
diff --git a/src/com/android/settings/ColorModePreference.java b/src/com/android/settings/ColorModePreference.java
index 94b6499..74abf5d 100644
--- a/src/com/android/settings/ColorModePreference.java
+++ b/src/com/android/settings/ColorModePreference.java
@@ -24,7 +24,6 @@
 import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
 import android.view.Display;
-import android.view.Display.ColorTransform;
 
 import java.util.ArrayList;
 
@@ -34,14 +33,14 @@
     private Display mDisplay;
 
     private int mCurrentIndex;
-    private ArrayList<ColorTransformDescription> mDescriptions;
+    private ArrayList<ColorModeDescription> mDescriptions;
 
     public ColorModePreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         mDisplayManager = getContext().getSystemService(DisplayManager.class);
     }
 
-    public int getTransformsCount() {
+    public int getColorModeCount() {
         return mDescriptions.size();
     }
 
@@ -77,43 +76,24 @@
         mDescriptions = new ArrayList<>();
 
         Resources resources = getContext().getResources();
-        int[] transforms = resources.getIntArray(
-                com.android.internal.R.array.config_colorTransforms);
+        int[] colorModes = resources.getIntArray(R.array.color_mode_ids);
         String[] titles = resources.getStringArray(R.array.color_mode_names);
         String[] descriptions = resources.getStringArray(R.array.color_mode_descriptions);
-        // Map the resource information describing color transforms.
-        for (int i = 0; i < transforms.length; i++) {
-            if (transforms[i] != -1 && i != 1 /* Skip Natural for now. */) {
-                ColorTransformDescription desc = new ColorTransformDescription();
-                desc.colorTransform = transforms[i];
+        // Map the resource information describing color modes.
+        for (int i = 0; i < colorModes.length; i++) {
+            if (colorModes[i] != -1 && i != 1 /* Skip Natural for now. */) {
+                ColorModeDescription desc = new ColorModeDescription();
+                desc.colorMode = colorModes[i];
                 desc.title = titles[i];
                 desc.summary = descriptions[i];
                 mDescriptions.add(desc);
             }
         }
-        // Match up a ColorTransform to every description.
-        ColorTransform[] supportedColorTransforms = mDisplay.getSupportedColorTransforms();
-        for (int i = 0; i < supportedColorTransforms.length; i++) {
-            for (int j = 0; j < mDescriptions.size(); j++) {
-                if (mDescriptions.get(j).colorTransform
-                        == supportedColorTransforms[i].getColorTransform()
-                        && mDescriptions.get(j).transform == null) {
-                    mDescriptions.get(j).transform = supportedColorTransforms[i];
-                    break;
-                }
-            }
-        }
-        // Remove any extras that don't have a transform for some reason.
-        for (int i = 0; i < mDescriptions.size(); i++) {
-            if (mDescriptions.get(i).transform == null) {
-                mDescriptions.remove(i--);
-            }
-        }
 
-        ColorTransform currentTransform = mDisplay.getColorTransform();
+        int currentColorMode = mDisplay.getColorMode();
         mCurrentIndex = -1;
         for (int i = 0; i < mDescriptions.size(); i++) {
-            if (mDescriptions.get(i).colorTransform == currentTransform.getColorTransform()) {
+            if (mDescriptions.get(i).colorMode == currentColorMode) {
                 mCurrentIndex = i;
                 break;
             }
@@ -125,19 +105,18 @@
     protected boolean persistBoolean(boolean value) {
         // Right now this is a switch, so we only support two modes.
         if (mDescriptions.size() == 2) {
-            ColorTransformDescription desc = mDescriptions.get(value ? 1 : 0);
+            ColorModeDescription desc = mDescriptions.get(value ? 1 : 0);
 
-            mDisplay.requestColorTransform(desc.transform);
+            mDisplay.requestColorMode(desc.colorMode);
             mCurrentIndex = mDescriptions.indexOf(desc);
         }
 
         return true;
     }
 
-    private static class ColorTransformDescription {
-        private int colorTransform;
+    private static class ColorModeDescription {
+        private int colorMode;
         private String title;
         private String summary;
-        private ColorTransform transform;
     }
 }
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index a2ce154..34dad58 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -461,7 +461,8 @@
             private void startCheckPattern(final List<LockPatternView.Cell> pattern,
                     final Intent intent) {
                 if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
-                    mCredentialCheckResultTracker.setResult(false, intent, 0, mEffectiveUserId);
+                    // Pattern size is less than the minimum, do not count it as an fail attempt.
+                    onPatternChecked(false, intent, 0, mEffectiveUserId, false /* newResult */);
                     return;
                 }
 
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 4697f43..c988e31 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -172,6 +172,15 @@
     // 32768 is merely a menu marker, 64K is our lowest log buffer size we replace it with.
     private static final String SELECT_LOGD_MINIMUM_SIZE_VALUE = "65536";
     private static final String SELECT_LOGD_OFF_SIZE_MARKER_VALUE = "32768";
+    private static final String SELECT_LOGPERSIST_KEY = "select_logpersist";
+    private static final String SELECT_LOGPERSIST_PROPERTY = "persist.logd.logpersistd";
+    private static final String ACTUAL_LOGPERSIST_PROPERTY = "logd.logpersistd";
+    private static final String SELECT_LOGPERSIST_PROPERTY_SERVICE = "logcatd";
+    private static final String SELECT_LOGPERSIST_PROPERTY_CLEAR = "clear";
+    private static final String SELECT_LOGPERSIST_PROPERTY_STOP = "stop";
+    private static final String SELECT_LOGPERSIST_PROPERTY_BUFFER = "persist.logd.logpersistd.buffer";
+    private static final String ACTUAL_LOGPERSIST_PROPERTY_BUFFER = "logd.logpersistd.buffer";
+    private static final String ACTUAL_LOGPERSIST_PROPERTY_ENABLE = "logd.logpersistd.enable";
 
     private static final String WIFI_DISPLAY_CERTIFICATION_KEY = "wifi_display_certification";
     private static final String WIFI_VERBOSE_LOGGING_KEY = "wifi_verbose_logging";
@@ -274,6 +283,7 @@
     private SwitchPreference mForceRtlLayout;
     private ListPreference mDebugHwOverdraw;
     private ListPreference mLogdSize;
+    private ListPreference mLogpersist;
     private ListPreference mUsbConfiguration;
     private ListPreference mTrackFrameTime;
     private ListPreference mShowNonRectClip;
@@ -314,6 +324,9 @@
     private Dialog mAdbKeysDialog;
     private boolean mUnavailable;
 
+    private boolean mLogpersistCleared;
+    private Dialog mLogpersistClearDialog;
+
     public DevelopmentSettings() {
         super(UserManager.DISALLOW_DEBUGGING_FEATURES);
     }
@@ -426,6 +439,18 @@
         mWifiAllowScansWithTraffic = findAndInitSwitchPref(WIFI_ALLOW_SCAN_WITH_TRAFFIC_KEY);
         mMobileDataAlwaysOn = findAndInitSwitchPref(MOBILE_DATA_ALWAYS_ON);
         mLogdSize = addListPreference(SELECT_LOGD_SIZE_KEY);
+        if ("1".equals(SystemProperties.get("ro.debuggable", "0"))) {
+            mLogpersist = addListPreference(SELECT_LOGPERSIST_KEY);
+        } else {
+            mLogpersist = (ListPreference) findPreference(SELECT_LOGPERSIST_KEY);
+            if (mLogpersist != null) {
+                mLogpersist.setEnabled(false);
+                if (debugDebuggingCategory != null) {
+                    debugDebuggingCategory.removePreference(mLogpersist);
+                }
+            }
+            mLogpersist = null;
+        }
         mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
         mWebViewProvider = addListPreference(WEBVIEW_PROVIDER_KEY);
         mWebViewMultiprocess = findAndInitSwitchPref(WEBVIEW_MULTIPROCESS_KEY);
@@ -478,7 +503,7 @@
 
         mColorModePreference = (ColorModePreference) findPreference(KEY_COLOR_MODE);
         mColorModePreference.updateCurrentAndSupported();
-        if (mColorModePreference.getTransformsCount() < 2) {
+        if (mColorModePreference.getColorModeCount() < 2) {
             removePreference(KEY_COLOR_MODE);
             mColorModePreference = null;
         }
@@ -694,6 +719,7 @@
         updateBugreportOptions();
         updateForceRtlOptions();
         updateLogdSizeValues();
+        updateLogpersistValues();
         updateWifiDisplayCertificationOptions();
         updateWifiVerboseLoggingOptions();
         updateWifiAggressiveHandoverOptions();
@@ -721,6 +747,7 @@
             }
         }
         resetDebuggerOptions();
+        writeLogpersistOption(null, true);
         writeLogdSizeOption(null);
         writeAnimationScaleOption(0, mWindowAnimationScale, null);
         writeAnimationScaleOption(1, mTransitionAnimationScale, null);
@@ -1460,6 +1487,18 @@
             if ((currentTag != null) && currentTag.startsWith(SELECT_LOGD_TAG_SILENCE)) {
                 currentValue = SELECT_LOGD_OFF_SIZE_MARKER_VALUE;
             }
+            if (mLogpersist != null) {
+                String currentLogpersistEnable
+                    = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_ENABLE);
+                if ((currentLogpersistEnable == null)
+                        || !currentLogpersistEnable.equals("true")
+                        || currentValue.equals(SELECT_LOGD_OFF_SIZE_MARKER_VALUE)) {
+                    writeLogpersistOption(null, true);
+                    mLogpersist.setEnabled(false);
+                } else if (mLastEnabledState) {
+                    mLogpersist.setEnabled(true);
+                }
+            }
             if ((currentValue == null) || (currentValue.length() == 0)) {
                 currentValue = defaultLogdSizeValue();
             }
@@ -1527,6 +1566,131 @@
         updateLogdSizeValues();
     }
 
+    private void updateLogpersistValues() {
+        if (mLogpersist == null) {
+            return;
+        }
+        String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
+        if (currentValue == null) {
+            currentValue = "";
+        }
+        String currentBuffers = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_BUFFER);
+        if ((currentBuffers == null) || (currentBuffers.length() == 0)) {
+            currentBuffers = "all";
+        }
+        int index = 0;
+        if (currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) {
+            index = 1;
+            if (currentBuffers.equals("kernel")) {
+                index = 3;
+            } else if (!currentBuffers.equals("all") &&
+                    !currentBuffers.contains("radio") &&
+                    currentBuffers.contains("security") &&
+                    currentBuffers.contains("kernel")) {
+                index = 2;
+                if (!currentBuffers.contains("default")) {
+                    String[] contains = { "main", "events", "system", "crash" };
+                    for (int i = 0; i < contains.length; i++) {
+                        if (!currentBuffers.contains(contains[i])) {
+                            index = 1;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        mLogpersist.setValue(getResources().getStringArray(R.array.select_logpersist_values)[index]);
+        mLogpersist.setSummary(getResources().getStringArray(R.array.select_logpersist_summaries)[index]);
+        mLogpersist.setOnPreferenceChangeListener(this);
+        if (index != 0) {
+            mLogpersistCleared = false;
+        } else if (!mLogpersistCleared) {
+            // would File.delete() directly but need to switch uid/gid to access
+            SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_CLEAR);
+            pokeSystemProperties();
+            mLogpersistCleared = true;
+        }
+    }
+
+    private void setLogpersistOff(boolean update) {
+        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY_BUFFER, "");
+        // deal with trampoline of empty properties
+        SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY_BUFFER, "");
+        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY, "");
+        SystemProperties.set(ACTUAL_LOGPERSIST_PROPERTY,
+            update ? "" : SELECT_LOGPERSIST_PROPERTY_STOP);
+        pokeSystemProperties();
+        if (update) {
+            updateLogpersistValues();
+        } else {
+            for (int i = 0; i < 3; i++) {
+                String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
+                if ((currentValue == null) || currentValue.equals("")) {
+                    break;
+                }
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    private void writeLogpersistOption(Object newValue, boolean skipWarning) {
+        if (mLogpersist == null) {
+            return;
+        }
+        String currentTag = SystemProperties.get(SELECT_LOGD_TAG_PROPERTY);
+        if ((currentTag != null) && currentTag.startsWith(SELECT_LOGD_TAG_SILENCE)) {
+            newValue = null;
+            skipWarning = true;
+        }
+
+        if ((newValue == null) || newValue.toString().equals("")) {
+            if (skipWarning) {
+                mLogpersistCleared = false;
+            } else if (!mLogpersistCleared) {
+                // if transitioning from on to off, pop up an are you sure?
+                String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
+                if ((currentValue != null) &&
+                        currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) {
+                    if (mLogpersistClearDialog != null) dismissDialogs();
+                    mLogpersistClearDialog = new AlertDialog.Builder(getActivity()).setMessage(
+                            getActivity().getResources().getString(
+                                    R.string.dev_logpersist_clear_warning_message))
+                            .setTitle(R.string.dev_logpersist_clear_warning_title)
+                            .setPositiveButton(android.R.string.yes, this)
+                            .setNegativeButton(android.R.string.no, this)
+                            .show();
+                    mLogpersistClearDialog.setOnDismissListener(this);
+                    return;
+                }
+            }
+            setLogpersistOff(true);
+            return;
+        }
+
+        String currentBuffer = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY_BUFFER);
+        if ((currentBuffer != null) && !currentBuffer.equals(newValue.toString())) {
+            setLogpersistOff(false);
+        }
+        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY_BUFFER, newValue.toString());
+        SystemProperties.set(SELECT_LOGPERSIST_PROPERTY, SELECT_LOGPERSIST_PROPERTY_SERVICE);
+        pokeSystemProperties();
+        for (int i = 0; i < 3; i++) {
+            String currentValue = SystemProperties.get(ACTUAL_LOGPERSIST_PROPERTY);
+            if ((currentValue != null)
+                    && currentValue.equals(SELECT_LOGPERSIST_PROPERTY_SERVICE)) {
+                break;
+            }
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+            }
+        }
+        updateLogpersistValues();
+    }
+
     private void updateUsbConfigurationValues() {
         if (mUsbConfiguration != null) {
             UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
@@ -1957,6 +2121,9 @@
         } else if (preference == mLogdSize) {
             writeLogdSizeOption(newValue);
             return true;
+        } else if (preference == mLogpersist) {
+            writeLogpersistOption(newValue, false);
+            return true;
         } else if (preference == mUsbConfiguration) {
             writeUsbConfigurationOption(newValue);
             return true;
@@ -2004,6 +2171,10 @@
             mEnableDialog.dismiss();
             mEnableDialog = null;
         }
+        if (mLogpersistClearDialog != null) {
+            mLogpersistClearDialog.dismiss();
+            mLogpersistClearDialog = null;
+        }
     }
 
     public void onClick(DialogInterface dialog, int which) {
@@ -2040,6 +2211,12 @@
                 // Reset the toggle
                 mSwitchBar.setChecked(false);
             }
+        } else if (dialog == mLogpersistClearDialog) {
+            if (which == DialogInterface.BUTTON_POSITIVE) {
+                setLogpersistOff(true);
+            } else {
+                updateLogpersistValues();
+            }
         }
     }
 
@@ -2055,6 +2232,8 @@
                 mSwitchBar.setChecked(false);
             }
             mEnableDialog = null;
+        } else if (dialog == mLogpersistClearDialog) {
+            mLogpersistClearDialog = null;
         }
     }
 
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index b161c41..ca09e51 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -110,14 +110,10 @@
         return mSuggestions;
     }
 
-    public void setSuggestions(List<Tile> suggestions) {
-        if (!Objects.equals(mSuggestions, suggestions)) {
-            mSuggestions = suggestions;
-            recountItems();
-        }
-    }
-
     public Tile getTile(ComponentName component) {
+        if (mCategories == null) {
+            return null;
+        }
         for (int i = 0; i < mCategories.size(); i++) {
             for (int j = 0; j < mCategories.get(i).tiles.size(); j++) {
                 Tile tile = mCategories.get(i).tiles.get(j);
@@ -129,10 +125,9 @@
         return null;
     }
 
-    public void setCategories(List<DashboardCategory> categories) {
-        if (Objects.equals(mCategories, categories)) {
-            return;
-        }
+    public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
+            List<Tile> suggestions) {
+        mSuggestions = suggestions;
         mCategories = categories;
 
         // TODO: Better place for tinting?
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 24b5aee..3a75c8a 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -200,10 +200,6 @@
             return;
         }
 
-        List<DashboardCategory> categories =
-                ((SettingsActivity) getActivity()).getDashboardCategories();
-        mAdapter.setCategories(categories);
-
         // recheck to see if any suggestions have been changed.
         new SuggestionLoader().execute();
     }
@@ -235,7 +231,9 @@
 
         @Override
         protected void onPostExecute(List<Tile> tiles) {
-            mAdapter.setSuggestions(tiles);
+            List<DashboardCategory> categories =
+                    ((SettingsActivity) getActivity()).getDashboardCategories();
+            mAdapter.setCategoriesAndSuggestions(categories, tiles);
         }
     }
 }
diff --git a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
index 9f2fb42..20efdda 100644
--- a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
+++ b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
@@ -150,6 +150,11 @@
         return true;
     }
 
+    @Override
+    protected int getHelpResource() {
+        return R.string.help_uri_storage;
+    }
+
     private static int daysValueToIndex(int value, String[] indices) {
         for (int i = 0; i < indices.length; i++) {
             int thisValue = Integer.parseInt(indices[i]);
diff --git a/src/com/android/settings/gestures/GesturePreference.java b/src/com/android/settings/gestures/GesturePreference.java
index c6ee0a7..a11455a 100644
--- a/src/com/android/settings/gestures/GesturePreference.java
+++ b/src/com/android/settings/gestures/GesturePreference.java
@@ -14,13 +14,18 @@
 
 package com.android.settings.gestures;
 
+import android.app.LoaderManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Loader;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.SurfaceTexture;
 import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer;
 import android.net.Uri;
+import android.os.Bundle;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.view.View;
@@ -31,22 +36,24 @@
 import android.util.Log;
 
 import com.android.settings.R;
+import com.android.settings.utils.AsyncLoader;
 
 /**
  * Preference item for a gesture with a switch to signify if it should be enabled.
  * This shows the title and description of the gesture along with an animation showing how to do
  * the gesture
  */
-public final class GesturePreference extends SwitchPreference {
+public final class GesturePreference extends SwitchPreference implements
+        LoaderManager.LoaderCallbacks<Bitmap> {
     private static final String TAG = "GesturePreference";
     private final Context mContext;
 
     private Uri mVideoPath;
     private MediaPlayer mMediaPlayer;
-    private MediaMetadataRetriever mMediaMetadata;
     private boolean mAnimationAvailable;
-    private boolean mPreviewReady;
+    private boolean mVideoReady;
     private boolean mScrolling;
+    private BitmapDrawable mPreviewImage;
 
     public GesturePreference(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -62,15 +69,12 @@
                     .authority(context.getPackageName())
                     .appendPath(String.valueOf(animation))
                     .build();
-            mMediaMetadata = new MediaMetadataRetriever();
-            mMediaMetadata.setDataSource(mContext, mVideoPath);
             mMediaPlayer = MediaPlayer.create(mContext, mVideoPath);
             if (mMediaPlayer != null) {
                 mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
                     @Override
                     public void onSeekComplete(MediaPlayer mp) {
-                        mPreviewReady = true;
-                        mMediaPlayer.setOnSeekCompleteListener(null);
+                        mVideoReady = true;
                     }
                 });
 
@@ -82,6 +86,7 @@
                 });
             }
             mAnimationAvailable = true;
+
         } catch (Exception e) {
             Log.w(TAG, "Animation resource not found. Will not show animation.");
         } finally {
@@ -125,6 +130,7 @@
                     int height) {
                 if (mMediaPlayer != null) {
                     mMediaPlayer.setSurface(new Surface(surfaceTexture));
+                    mVideoReady = false;
                     mMediaPlayer.seekTo(0);
                 }
             }
@@ -136,12 +142,16 @@
 
             @Override
             public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+                if (mPreviewImage != null && imageView.getDrawable() == null) {
+                    imageView.setImageDrawable(mPreviewImage);
+                }
+                imageView.setVisibility(View.VISIBLE);
                 return false;
             }
 
             @Override
             public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
-                if (mPreviewReady && imageView.getVisibility() == View.VISIBLE) {
+                if (mVideoReady && imageView.getVisibility() == View.VISIBLE) {
                     imageView.setVisibility(View.GONE);
                 } else if (mScrolling) {
                     mScrolling = false;
@@ -153,13 +163,14 @@
             }
         });
 
+        if (mPreviewImage != null) {
+            imageView.setImageDrawable(mPreviewImage);
+        }
+
     }
 
     @Override
     public void onDetached() {
-        if (mMediaMetadata != null) {
-            mMediaMetadata.release();
-        }
         if (mMediaPlayer != null) {
             mMediaPlayer.stop();
             mMediaPlayer.reset();
@@ -172,4 +183,55 @@
         mScrolling = scrolling;
     }
 
+    void loadPreview(LoaderManager manager, int id) {
+        Loader<Bitmap> loader = manager.initLoader(id, Bundle.EMPTY, this);
+    }
+
+    private static final class PreviewRetriever extends AsyncLoader<Bitmap> {
+        private Uri mVideoPath;
+
+        public PreviewRetriever(Context context, Uri videoPath) {
+            super(context);
+            mVideoPath = videoPath;
+        }
+
+        @Override
+        public Bitmap loadInBackground() {
+            MediaMetadataRetriever mediaMetadata = new MediaMetadataRetriever();
+            try {
+                mediaMetadata.setDataSource(getContext(), mVideoPath);
+                return mediaMetadata.getFrameAtTime(0);
+            } catch (Exception e) {
+                Log.w(TAG, "Unable to get animation preview.");
+            } finally {
+                mediaMetadata.release();
+            }
+            return null;
+        }
+
+        @Override
+        public void onDiscardResult(final Bitmap result) {
+            if (result != null && !result.isRecycled()) {
+                result.recycle();
+            }
+        }
+
+    }
+
+    @Override
+    public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
+        return new PreviewRetriever(mContext, mVideoPath);
+    }
+
+    @Override
+    public void onLoadFinished(final Loader<Bitmap> loader, final Bitmap bitmap) {
+        if (bitmap != null) {
+            mPreviewImage = new BitmapDrawable(mContext.getResources(), bitmap);
+        }
+    }
+
+    @Override
+    public void onLoaderReset(Loader<Bitmap> loader) {
+    }
+
 }
diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java
index a61509f..37dcc7e 100644
--- a/src/com/android/settings/gestures/GestureSettings.java
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -56,6 +56,10 @@
     private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint";
     private static final String DEBUG_DOZE_COMPONENT = "debug.doze.component";
     private static final String ARG_SCROLL_TO_PREFERENCE = "gesture_scroll_to_preference";
+    private static final int PREF_ID_DOUBLE_TAP_POWER = 0;
+    private static final int PREF_ID_DOUBLE_TWIST = 1;
+    private static final int PREF_ID_PICK_UP_AND_NUDG = 2;
+    private static final int PREF_ID_SWIPE_DOWN_FINGERPRINT = 3;
 
     private int mScrollPosition = -1;
     private List<GesturePreference> mPreferences;
@@ -71,7 +75,7 @@
         if (isCameraDoubleTapPowerGestureAvailable(getResources())) {
             int cameraDisabled = Secure.getInt(
                     getContentResolver(), Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
-            addPreference(PREF_KEY_DOUBLE_TAP_POWER, cameraDisabled == 0);
+            addPreference(PREF_KEY_DOUBLE_TAP_POWER, cameraDisabled == 0, PREF_ID_DOUBLE_TAP_POWER);
         } else {
             removePreference(PREF_KEY_DOUBLE_TAP_POWER);
         }
@@ -79,14 +83,15 @@
         // Ambient Display
         if (isDozeAvailable(context)) {
             int dozeEnabled = Secure.getInt(getContentResolver(), Secure.DOZE_ENABLED, 1);
-            addPreference(PREF_KEY_PICK_UP_AND_NUDGE, dozeEnabled != 0);
+            addPreference(PREF_KEY_PICK_UP_AND_NUDGE, dozeEnabled != 0, PREF_ID_DOUBLE_TWIST);
         } else {
             removePreference(PREF_KEY_PICK_UP_AND_NUDGE);
         }
 
         // Fingerprint slide for notifications
         if (isSystemUINavigationAvailable(context)) {
-            addPreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT, isSystemUINavigationEnabled(context));
+            addPreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT, isSystemUINavigationEnabled(context),
+                    PREF_ID_PICK_UP_AND_NUDG);
         } else {
             removePreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT);
         }
@@ -95,7 +100,8 @@
         if (isDoubleTwistAvailable(context)) {
             int doubleTwistEnabled = Secure.getInt(
                     getContentResolver(), Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1);
-            addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0);
+            addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0,
+                    PREF_ID_SWIPE_DOWN_FINGERPRINT);
         } else {
             removePreference(PREF_KEY_DOUBLE_TWIST);
         }
@@ -211,10 +217,11 @@
         return false;
     }
 
-    private void addPreference(String key, boolean enabled) {
+    private void addPreference(String key, boolean enabled, int id) {
         GesturePreference preference = (GesturePreference) findPreference(key);
         preference.setChecked(enabled);
         preference.setOnPreferenceChangeListener(this);
+        preference.loadPreview(getLoaderManager(), id);
         mPreferences.add(preference);
     }
 
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 84223b7..b0c24b0 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -212,9 +212,9 @@
             clearLoader();
             mLastHardKeyboards.clear();
             mLastHardKeyboards.addAll(newHardKeyboards);
+            mLoaderIDs.add(mNextLoaderId);
             getLoaderManager().initLoader(mNextLoaderId, null,
                     new Callbacks(getContext(), this, mLastHardKeyboards));
-            mLoaderIDs.add(mNextLoaderId);
             ++mNextLoaderId;
         }
     }