Merge "Add support for showing the admin disabling settings."
diff --git a/res/drawable/ic_add_24dp.xml b/res/drawable/ic_add_24dp.xml
index 6535107..97178b2 100644
--- a/res/drawable/ic_add_24dp.xml
+++ b/res/drawable/ic_add_24dp.xml
@@ -14,11 +14,12 @@
   ~ limitations under the License
   -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/colorAccent">
     <path
-        android:fillColor="?android:attr/colorAccent"
-        android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z"/>
+        android:fillColor="@android:color/white"
+        android:pathData="M38,26L26,26l0,12l-4,0L22,26L10,26l0,-4l12,0L22,10l4,0l0,12l12,0l0,4.0z"/>
 </vector>
diff --git a/res/drawable/ic_info.xml b/res/drawable/ic_info.xml
index 13d00a4..6e19d26 100644
--- a/res/drawable/ic_info.xml
+++ b/res/drawable/ic_info.xml
@@ -14,11 +14,11 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M11.0,17.0l2.0,0.0l0.0,-6.0l-2.0,0.0l0.0,6.0zm1.0,-15.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zm0.0,18.0c-4.41,0.0 -8.0,-3.59 -8.0,-8.0s3.59,-8.0 8.0,-8.0 8.0,3.59 8.0,8.0 -3.59,8.0 -8.0,8.0zM11.0,9.0l2.0,0.0L13.0,7.0l-2.0,0.0l0.0,2.0z"/>
+        android:fillColor="@android:color/white"
+        android:pathData="M11,17l2,0l0,-6l-2,0l0,6.0zm1,-15.0C6.48,2 2,6.48 2,12.0s4.48,10 10,10 10,-4.48 10,-10.0S17.52,2 12,2.0zm0,18.0c-4.41,0 -8,-3.59 -8,-8.0s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8.0zM11,9l2,0L13,7l-2,0l0,2.0z"/>
 </vector>
diff --git a/res/drawable/ic_remove_24dp.xml b/res/drawable/ic_remove_24dp.xml
new file mode 100644
index 0000000..9233623
--- /dev/null
+++ b/res/drawable/ic_remove_24dp.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/colorAccent">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M38 26H10v-4h28v4z"/>
+</vector>
diff --git a/res/drawable/screen_zoom_preview_action_background.xml b/res/drawable/screen_zoom_preview_action_background.xml
new file mode 100644
index 0000000..32fbb02
--- /dev/null
+++ b/res/drawable/screen_zoom_preview_action_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <size android:width="24dp"
+          android:height="24dp" />
+    <solid android:color="@android:color/white" />
+</shape>
diff --git a/res/layout/screen_zoom_activity.xml b/res/layout/screen_zoom_activity.xml
new file mode 100644
index 0000000..81ce102
--- /dev/null
+++ b/res/layout/screen_zoom_activity.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp"
+        android:paddingLeft="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/screen_zoom_summary"
+            android:layout_marginBottom="16dp"
+            android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/screen_zoom_preview_height"
+            android:background="?android:attr/colorBackgroundFloating"
+            android:elevation="2dp">
+
+            <com.android.settings.display.TouchBlockingFrameLayout
+                android:id="@+id/preview_frame"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
+
+            <TextView
+                android:id="@+id/current_density"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal|bottom"
+                android:padding="8dp"
+                android:theme="@android:style/Theme.Material"
+                android:background="?android:attr/colorBackgroundFloating"
+                android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                android:textAllCaps="true"
+                android:elevation="2dp" />
+        </FrameLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp">
+
+            <ImageView
+                android:id="@+id/smaller"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:background="?android:attr/selectableItemBackgroundBorderless"
+                android:src="@drawable/ic_remove_24dp"
+                android:tint="?android:attr/colorControlNormal"
+                android:tintMode="src_in"
+                android:scaleType="center"
+                android:focusable="true"
+                android:contentDescription="@string/screen_zoom_make_smaller_desc" />
+
+            <SeekBar
+                android:id="@+id/seek_bar"
+                android:layout_width="0dp"
+                android:layout_height="48dp"
+                android:layout_weight="1" />
+
+            <ImageView
+                android:id="@+id/larger"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:background="?android:attr/selectableItemBackgroundBorderless"
+                android:src="@drawable/ic_add_24dp"
+                android:tint="?android:attr/colorControlNormal"
+                android:tintMode="src_in"
+                android:scaleType="center"
+                android:focusable="true"
+                android:contentDescription="@string/screen_zoom_make_larger_desc" />
+        </LinearLayout>
+    </LinearLayout>
+</ScrollView>
diff --git a/res/layout/screen_zoom_preview.xml b/res/layout/screen_zoom_preview.xml
new file mode 100644
index 0000000..7cdb663
--- /dev/null
+++ b/res/layout/screen_zoom_preview.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:orientation="horizontal"
+        android:theme="?android:attr/actionBarTheme"
+        style="?android:attr/actionBarStyle">
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_marginLeft="16dp"
+            android:text="@string/screen_zoom_preview_title"
+            android:textAppearance="@android:style/TextAppearance.Material.Widget.ActionBar.Title" />
+
+        <ImageView
+            android:layout_width="36dp"
+            android:layout_height="48dp"
+            style="?android:attr/actionOverflowButtonStyle" />
+    </LinearLayout>
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scrollbars="none"
+        android:background="?android:attr/colorBackgroundFloating">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <TextView
+                style="@android:style/TextAppearance.Material.Subhead"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="16dp"
+                android:layout_marginTop="16dp"
+                android:text="@string/permissions_label" />
+
+            <include layout="@layout/screen_zoom_preview_item" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:layout_marginLeft="62dp"
+                android:layout_marginRight="8dp"
+                android:background="#36000000" />
+
+            <include layout="@layout/screen_zoom_preview_item" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:layout_marginLeft="62dp"
+                android:layout_marginRight="8dp"
+                android:background="#36000000" />
+
+            <include layout="@layout/screen_zoom_preview_item" />
+
+        </LinearLayout>
+
+    </ScrollView>
+</LinearLayout>
diff --git a/res/layout/screen_zoom_preview_item.xml b/res/layout/screen_zoom_preview_item.xml
new file mode 100644
index 0000000..68076f0
--- /dev/null
+++ b/res/layout/screen_zoom_preview_item.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:gravity="center_vertical"
+              android:padding="16dp"
+              tools:showIn="@layout/screen_zoom_preview">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:background="@drawable/screen_zoom_preview_action_background"
+        android:backgroundTint="?android:attr/colorAccent"
+        android:src="@drawable/ic_settings_32dp"
+        android:scaleType="center" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:paddingStart="16dp">
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/usage_access"
+            style="@android:style/TextAppearance.Material.Body1" />
+
+        <TextView
+            android:id="@+id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/usage_access_description"
+            style="@android:style/TextAppearance.Material.Caption" />
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/action"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginLeft="24dp"
+        android:src="@drawable/ic_info"
+        android:tint="?android:attr/colorControlNormal"
+        android:tintMode="src_in"
+        android:scaleType="center" />
+</LinearLayout>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index d15c254..7612c97 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -48,4 +48,7 @@
     <!-- Fingerprint -->
     <item name="fingerprint_illustration_aspect_ratio" format="float" type="dimen">0.0</item>
     <dimen name="fingerprint_decor_padding_top">24dp</dimen>
+
+    <!-- Display, Screen zoom -->
+    <dimen name="screen_zoom_preview_height">160dp</dimen>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d9426c9..86030ff 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -261,4 +261,7 @@
 
     <!-- Button bar padding for unmount button. -->
     <dimen name="unmount_button_padding">8dp</dimen>
+
+    <!-- Display, Screen zoom -->
+    <dimen name="screen_zoom_preview_height">240dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 99a83e4..7120163 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3659,6 +3659,8 @@
     <string name="accessibility_power_button_ends_call_prerefence_title">Power button ends call</string>
     <!-- Title for the accessibility preference to speak passwords. [CHAR LIMIT=35] -->
     <string name="accessibility_toggle_speak_password_preference_title">Speak passwords</string>
+    <!-- Title for the accessibility preference for enabling/disabling large icons for mouse/trackpad pointers. [CHAR LIMIT=35] -->
+    <string name="accessibility_toggle_large_pointer_icon_title">Large mouse pointer</string>
     <!-- Title for accessibility preference to choose long-press delay i.e. timeout before it is detected. [CHAR LIMIT=35] -->
     <string name="accessibility_long_press_timeout_preference_title">Touch &amp; hold delay</string>
     <!-- Title for the accessibility preference to configure display color inversion. [CHAR LIMIT=NONE] -->
@@ -6611,23 +6613,33 @@
     <!-- Description of setting that controls gesture to open camera by double tapping the power button [CHAR LIMIT=NONE] -->
     <string name="camera_double_tap_power_gesture_desc">Quickly open camera without unlocking your screen</string>
 
-    <!-- Title of setting that controls display scale (e.g. density). [CHAR LIMIT=40] -->
-    <string name="force_density_preference_title">Display scale</string>
-    <!-- Keywords for setting that controls display scale (e.g. density). [CHAR LIMIT=NONE] -->
-    <string name="force_density_keywords">display density zoom scale scaling</string>
-    <!-- Description for the display scale that makes interface elements small. [CHAR LIMIT=24] -->
-    <string name="force_density_summary_small">Small</string>
-    <!-- Description for the device's default display scale. [CHAR LIMIT=24] -->
-    <string name="force_density_summary_normal">Normal</string>
-    <!-- Description for the display scale that makes interface elements large. [CHAR LIMIT=24] -->
-    <string name="force_density_summary_large">Large</string>
-    <!-- Description for the display scale that makes interface elements larger. [CHAR LIMIT=24] -->
-    <string name="force_density_summary_very_large">Larger</string>
-    <!-- Description for the display scale that makes interface elements largest. [CHAR LIMIT=24] -->
-    <string name="force_density_summary_extremely_large">Largest</string>
-    <!-- Description for a custom display scale. This shows the requested display
-         density in raw pixels per inch rather than computing a scale amount. [CHAR LIMIT=24] -->
-    <string name="force_density_summary_custom">Custom (<xliff:g id="densityDpi" example="160">%d</xliff:g>)</string>
+    <!-- Title of setting that controls screen zoom (e.g. how large interface elements appear). [CHAR LIMIT=40] -->
+    <string name="screen_zoom_title">Screen zoom</string>
+    <!-- Keywords for setting that controls screen zoom (e.g. how large interface elements appear). [CHAR LIMIT=NONE] -->
+    <string name="screen_zoom_keywords">display density screen zoom scale scaling</string>
+
+    <string name="screen_zoom_summary">Choose how zoomed you want the screen using the slider below the preview image.</string>
+
+    <!-- Title of the screen zoom preview activity. -->
+    <string name="screen_zoom_preview_title">Preview</string>
+    <!-- Description for the button that makes interface elements smaller. [CHAR_LIMIT=NONE] -->
+    <string name="screen_zoom_make_smaller_desc">Make smaller</string>
+    <!-- Description for the button that makes interface elements larger. [CHAR_LIMIT=NONE] -->
+    <string name="screen_zoom_make_larger_desc">Make larger</string>
+
+    <!-- Description for the screen zoom level that makes interface elements small. [CHAR LIMIT=24] -->
+    <string name="screen_zoom_summary_small">Small</string>
+    <!-- Description for the device's default screen zoom level. [CHAR LIMIT=24] -->
+    <string name="screen_zoom_summary_normal">Normal</string>
+    <!-- Description for the screen zoom level that makes interface elements large. [CHAR LIMIT=24] -->
+    <string name="screen_zoom_summary_large">Large</string>
+    <!-- Description for the screen zoom level that makes interface elements larger. [CHAR LIMIT=24] -->
+    <string name="screen_zoom_summary_very_large">Larger</string>
+    <!-- Description for the screen zoom level that makes interface elements largest. [CHAR LIMIT=24] -->
+    <string name="screen_zoom_summary_extremely_large">Largest</string>
+    <!-- Description for a custom screen zoom level. This shows the requested display
+         density in raw pixels per inch rather than using a relative description. [CHAR LIMIT=24] -->
+    <string name="screen_zoom_summary_custom">Custom (<xliff:g id="densityDpi" example="160">%d</xliff:g>)</string>
 
     <!-- Button to show all top-level settings items [CHAR LIMIT=20] -->
     <string name="see_all">See all</string>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 881037d..791f1b8 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -68,6 +68,10 @@
                 android:title="@string/accessibility_toggle_speak_password_preference_title"
                 android:persistent="false"/>
 
+        <SwitchPreference
+                android:key="toggle_large_pointer_icon"
+                android:title="@string/accessibility_toggle_large_pointer_icon_title" />
+
         <PreferenceScreen
                 android:fragment="com.android.settings.accessibility.ToggleGlobalGesturePreferenceFragment"
                 android:key="enable_global_gesture_preference_screen"
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 60730a9..1016c2a 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -99,12 +99,10 @@
                 android:entries="@array/entries_font_size"
                 android:entryValues="@array/entryvalues_font_size" />
 
-        <com.android.settings.DisplayDensityPreference
-                android:key="display_density"
-                android:title="@string/force_density_preference_title"
-                android:summary="%s"
-                settings:keywords="@string/force_density_keywords"
-                android:persistent="false" />
+        <com.android.settings.display.ScreenZoomPreference
+                android:key="screen_zoom"
+                android:title="@string/screen_zoom_title"
+                settings:keywords="@string/screen_zoom_keywords" />
 
         <com.android.settings.DropDownPreference
                 android:key="auto_rotate"
diff --git a/src/com/android/settings/AirplaneModeVoiceActivity.java b/src/com/android/settings/AirplaneModeVoiceActivity.java
index e0649e4..21bfef2 100644
--- a/src/com/android/settings/AirplaneModeVoiceActivity.java
+++ b/src/com/android/settings/AirplaneModeVoiceActivity.java
@@ -16,7 +16,9 @@
 
 package com.android.settings;
 
+import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -31,9 +33,10 @@
 
     protected boolean onVoiceSettingInteraction(Intent intent) {
         if (intent.hasExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED)) {
-            Settings.Global.putInt(getContentResolver(),
-                    Settings.Global.AIRPLANE_MODE_ON,
-                    intent.getBooleanExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED, false) ? 1 : 0);
+            ConnectivityManager mgr = (ConnectivityManager) getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
+            mgr.setAirplaneMode(intent.getBooleanExtra(
+                    Settings.EXTRA_AIRPLANE_MODE_ENABLED, false));
         } else {
             Log.v(TAG, "Missing airplane mode extra");
         }
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index e785abb..20fb9ea 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -203,10 +203,22 @@
         mFirstTime = icicle == null;
 
         if (action.equals(Intent.ACTION_EDIT)) {
-            mUri = intent.getData();
+            Uri uri = intent.getData();
+            if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
+                Log.e(TAG, "Edit request not for carrier table. Uri: " + uri);
+                finish();
+                return;
+            }
+            mUri = uri;
         } else if (action.equals(Intent.ACTION_INSERT)) {
             if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
-                mUri = getContentResolver().insert(intent.getData(), new ContentValues());
+                Uri uri = intent.getData();
+                if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
+                    Log.e(TAG, "Insert request not for carrier table. Uri: " + uri);
+                    finish();
+                    return;
+                }
+                mUri = getContentResolver().insert(uri, new ContentValues());
             } else {
                 mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
                         icicle.getInt(SAVED_POS));
diff --git a/src/com/android/settings/BugreportPreference.java b/src/com/android/settings/BugreportPreference.java
index 24af284..fc0466f 100644
--- a/src/com/android/settings/BugreportPreference.java
+++ b/src/com/android/settings/BugreportPreference.java
@@ -37,7 +37,7 @@
     @Override
     protected void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_POSITIVE) {
-            SystemProperties.set("ctl.start", "bugreport");
+            SystemProperties.set("ctl.start", "bugreportplus");
         }
     }
 }
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 65f0ba6..114637c 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -220,13 +220,17 @@
                     && !dpm.getDoNotAskCredentialsOnBoot()) {
                 mEncryptionRequestQuality = quality;
                 mEncryptionRequestDisabled = disabled;
+                // Get the intent that the encryption interstitial should start for creating
+                // the new unlock method.
+                Intent unlockMethodIntent = getIntentForUnlockMethod(quality, disabled);
                 final Context context = getActivity();
                 // If accessibility is enabled and the user hasn't seen this dialog before, set the
                 // default state to agree with that which is compatible with accessibility
                 // (password not required).
                 final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
                 final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
-                Intent intent = getEncryptionInterstitialIntent(context, quality, required);
+                Intent intent = getEncryptionInterstitialIntent(context, quality, required,
+                        unlockMethodIntent);
                 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
                         mForFingerprint);
                 startActivityForResult(intent, ENABLE_ENCRYPTION_REQUEST);
@@ -246,9 +250,8 @@
                 updatePreferencesOrFinish();
             } else if (requestCode == ENABLE_ENCRYPTION_REQUEST
                     && resultCode == Activity.RESULT_OK) {
-                mRequirePassword = data.getBooleanExtra(
-                        EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
-                updateUnlockMethodAndFinish(mEncryptionRequestQuality, mEncryptionRequestDisabled);
+                getActivity().setResult(resultCode, data);
+                finish();
             } else if (requestCode == CHOOSE_LOCK_REQUEST) {
                 getActivity().setResult(resultCode, data);
                 finish();
@@ -451,8 +454,9 @@
         }
 
         protected Intent getEncryptionInterstitialIntent(Context context, int quality,
-                boolean required) {
-            return EncryptionInterstitial.createStartIntent(context, quality, required);
+                boolean required, Intent unlockMethodIntent) {
+            return EncryptionInterstitial.createStartIntent(context, quality, required,
+                    unlockMethodIntent);
         }
 
         /**
@@ -471,34 +475,13 @@
             }
 
             quality = upgradeQuality(quality);
+            Intent intent = getIntentForUnlockMethod(quality, disabled);
+            if (intent != null) {
+                startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
+                return;
+            }
 
-            final Context context = getActivity();
-            if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
-                int minLength = mDPM.getPasswordMinimumLength(null);
-                if (minLength < MIN_PASSWORD_LENGTH) {
-                    minLength = MIN_PASSWORD_LENGTH;
-                }
-                final int maxLength = mDPM.getPasswordMaximumLength(quality);
-                Intent intent;
-                if (mHasChallenge) {
-                    intent = getLockPasswordIntent(context, quality, minLength,
-                            maxLength, mRequirePassword, mChallenge, mUserId);
-                } else {
-                    intent = getLockPasswordIntent(context, quality, minLength,
-                        maxLength, mRequirePassword, mUserPassword, mUserId);
-                }
-                startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
-            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
-                Intent intent;
-                if (mHasChallenge) {
-                    intent = getLockPatternIntent(context, mRequirePassword,
-                        mChallenge, mUserId);
-                } else {
-                    intent = getLockPatternIntent(context, mRequirePassword,
-                        mUserPassword, mUserId);
-                }
-                startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
-            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+            if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                 mChooseLockSettingsHelper.utils().clearLock(mUserId);
                 mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
                 removeAllFingerprintTemplatesAndFinish();
@@ -508,6 +491,34 @@
             }
         }
 
+        private Intent getIntentForUnlockMethod(int quality, boolean disabled) {
+            Intent intent = null;
+            final Context context = getActivity();
+            if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
+                int minLength = mDPM.getPasswordMinimumLength(null);
+                if (minLength < MIN_PASSWORD_LENGTH) {
+                    minLength = MIN_PASSWORD_LENGTH;
+                }
+                final int maxLength = mDPM.getPasswordMaximumLength(quality);
+                if (mHasChallenge) {
+                    intent = getLockPasswordIntent(context, quality, minLength,
+                            maxLength, mRequirePassword, mChallenge, mUserId);
+                } else {
+                    intent = getLockPasswordIntent(context, quality, minLength,
+                            maxLength, mRequirePassword, mUserPassword, mUserId);
+                }
+            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
+                if (mHasChallenge) {
+                    intent = getLockPatternIntent(context, mRequirePassword,
+                            mChallenge, mUserId);
+                } else {
+                    intent = getLockPatternIntent(context, mRequirePassword,
+                            mUserPassword, mUserId);
+                }
+            }
+            return intent;
+        }
+
         private void removeAllFingerprintTemplatesAndFinish() {
             if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()
                     && mFingerprintManager.getEnrolledFingerprints().size() > 0) {
diff --git a/src/com/android/settings/DisplayDensityPreference.java b/src/com/android/settings/DisplayDensityPreference.java
deleted file mode 100644
index 85f2fb2..0000000
--- a/src/com/android/settings/DisplayDensityPreference.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2015 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.settings;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.AsyncTask;
-import android.os.RemoteException;
-import android.support.annotation.ArrayRes;
-import android.support.v7.preference.ListPreference;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
-
-import com.android.settings.R;
-
-import java.util.Arrays;
-
-/**
- * Preference for changing the density of the display on which the preference
- * is visible.
- */
-public class DisplayDensityPreference extends ListPreference {
-    private static final String LOG_TAG = "DisplayDensityPreference";
-
-    /** Minimum increment between density scales. */
-    private static final float MIN_SCALE_INTERVAL = 0.09f;
-
-    /** Minimum density scale. This is available on all devices. */
-    private static final float MIN_SCALE = 0.85f;
-
-    /** Maximum density scale. The actual scale used depends on the device. */
-    private static final float MAX_SCALE = 1.50f;
-
-    /** Sentinel value for "normal" scaling (effectively disabled). */
-    private static final int DENSITY_VALUE_NORMAL = -1;
-
-    /** Summary used for "normal" scale. */
-    private static final int DENSITY_SUMMARY_NORMAL = R.string.force_density_summary_normal;
-
-    /**
-     * Summaries for scales smaller than "normal" in order of smallest to
-     * largest.
-     */
-    private static final int[] SMALLER_SUMMARIES = new int[] {
-            R.string.force_density_summary_small
-    };
-
-    /**
-     * Summaries for scales larger than "normal" in order of smallest to
-     * largest.
-     */
-    private static final int[] LARGER_SUMMARIES = new int[] {
-            R.string.force_density_summary_large,
-            R.string.force_density_summary_very_large,
-            R.string.force_density_summary_extremely_large,
-    };
-
-    /**
-     * Minimum allowed screen dimension, corresponds to resource qualifiers
-     * "small" or "sw320dp". This value must be at least the minimum screen
-     * size required by the CDD so that we meet developer expectations.
-     */
-    private static final int MIN_DIMENSION_DP = 320;
-
-    /** The ID of the display affected by this preference. */
-    private int mDisplayId = Display.DEFAULT_DISPLAY;
-
-    public DisplayDensityPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        if (!prepareList()) {
-            setEnabled(false);
-        }
-    }
-
-    private boolean prepareList() {
-        final int initialDensity = getInitialDisplayDensity(mDisplayId);
-        if (initialDensity <= 0) {
-            return false;
-        }
-
-        final Resources res = getContext().getResources();
-        final DisplayMetrics metrics = res.getDisplayMetrics();
-        final int currentDensity = metrics.densityDpi;
-        int currentDensityIndex = -1;
-
-        // Compute number of "larger" and "smaller" scales for this display.
-        final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels);
-        final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
-        final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) initialDensity);
-        final float minScale = MIN_SCALE;
-        final int numLarger = (int) MathUtils.constrain((maxScale - 1) / MIN_SCALE_INTERVAL,
-                0, LARGER_SUMMARIES.length);
-        final int numSmaller = (int) MathUtils.constrain((1 - minScale) / MIN_SCALE_INTERVAL,
-                0, SMALLER_SUMMARIES.length);
-
-        CharSequence[] values = new CharSequence[1 + numSmaller + numLarger];
-        CharSequence[] entries = new CharSequence[values.length];
-        int curIndex = 0;
-
-        if (numSmaller > 0) {
-            final float interval = (1 - minScale) / numSmaller;
-            for (int i = numSmaller - 1; i >= 0; i--) {
-                final int density = (int) (initialDensity * (1 - (i + 1) * interval));
-                if (currentDensity == density) {
-                    currentDensityIndex = curIndex;
-                }
-                values[curIndex] = Integer.toString(density);
-                entries[curIndex] = res.getText(SMALLER_SUMMARIES[i]);
-                curIndex++;
-            }
-        }
-
-        if (currentDensity == initialDensity) {
-            currentDensityIndex = curIndex;
-        }
-        values[curIndex] = Integer.toString(DENSITY_VALUE_NORMAL);
-        entries[curIndex] = res.getText(DENSITY_SUMMARY_NORMAL);
-        curIndex++;
-
-        if (numLarger > 0) {
-            final float interval = (maxScale - 1) / numLarger;
-            for (int i = 0; i < numLarger; i++) {
-                final int density = (int) (initialDensity * (1 + (i + 1) * interval));
-                if (currentDensity == density) {
-                    currentDensityIndex = curIndex;
-                }
-                values[curIndex] = Integer.toString(density);
-                entries[curIndex] = res.getText(LARGER_SUMMARIES[i]);
-                curIndex++;
-            }
-        }
-
-        final int displayIndex;
-        if (currentDensityIndex >= 0) {
-            displayIndex = currentDensityIndex;
-        } else {
-            // We don't understand the current density. Must have been set by
-            // someone else. Make room for another entry...
-            values = Arrays.copyOf(values, values.length + 1);
-            values[curIndex] = res.getString(R.string.force_density_summary_custom, currentDensity);
-
-            entries = Arrays.copyOf(entries, values.length + 1);
-            entries[curIndex] = Integer.toString(currentDensity);
-
-            displayIndex = curIndex;
-        }
-
-        super.setEntryValues(values);
-        super.setEntries(entries);
-
-        setValueIndex(displayIndex);
-
-        return true;
-    }
-
-    @Override
-    public boolean callChangeListener(Object newValue) {
-        final boolean allowed = super.callChangeListener(newValue);
-        if (allowed) {
-            final int density = Integer.parseInt((String) newValue);
-            setForcedDisplayDensity(mDisplayId, density);
-        }
-
-        return allowed;
-    }
-
-    @Override
-    public void setEntries(CharSequence[] entries) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setEntries(@ArrayRes int entriesResId) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setEntryValues(CharSequence[] entryValues) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setEntryValues(@ArrayRes int entryValuesResId) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Returns the initial density for the specified display.
-     *
-     * @param displayId the identifier of the display
-     * @return the initial density of the specified display, or {@code -1} if
-     *         the display does not exist or the density could not be obtained
-     */
-    private static int getInitialDisplayDensity(int displayId) {
-        try {
-            IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
-            return wm.getInitialDisplayDensity(displayId);
-        } catch (RemoteException exc) {
-            return -1;
-        }
-    }
-
-    /**
-     * Asynchronously applies display density changes to the specified display.
-     *
-     * @param displayId the identifier of the display to modify
-     * @param density the density to force for the specified display, or <= 0
-     *                to clear any previously forced density
-     */
-    private static void setForcedDisplayDensity(final int displayId, final int density) {
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
-                    if (density <= 0) {
-                        wm.clearForcedDisplayDensity(displayId);
-                    } else {
-                        wm.setForcedDisplayDensity(displayId, density);
-                    }
-                } catch (RemoteException exc) {
-                    Log.w(LOG_TAG, "Unable to save forced display density setting");
-                }
-            }
-        });
-    }
-}
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 0d52aa7..e9ab1f7 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -76,7 +76,6 @@
     private static final String KEY_CAMERA_GESTURE = "camera_gesture";
     private static final String KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE
             = "camera_double_tap_power_gesture";
-    private static final String KEY_DISPLAY_DENSITY = "display_density";
 
     private DropDownPreference mFontSizePref;
 
@@ -214,9 +213,6 @@
             mNightModePreference.setValue(String.valueOf(currentNightMode));
             mNightModePreference.setOnPreferenceChangeListener(this);
         }
-
-        final Preference displayDensity = findPreference(KEY_DISPLAY_DENSITY);
-        displayDensity.setOnPreferenceChangeListener(this);
     }
 
     private static boolean allowAllRotations(Context context) {
diff --git a/src/com/android/settings/DropDownPreference.java b/src/com/android/settings/DropDownPreference.java
index 3088497..70bd663 100644
--- a/src/com/android/settings/DropDownPreference.java
+++ b/src/com/android/settings/DropDownPreference.java
@@ -64,6 +64,7 @@
             }
         });
         setPersistent(false);
+        setSummary("%s");
         updateEntries();
     }
 
@@ -95,7 +96,6 @@
     public void setValue(String value) {
         super.setValue(value);
         mSpinner.setSelection(findIndexOfValue(getValue()));
-        setSummary(getEntry());
     }
 
     public void setValueIndex(int index) {
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
index 3aec03e..5cd0508 100644
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ b/src/com/android/settings/EncryptionInterstitial.java
@@ -26,10 +26,12 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.Button;
 import android.widget.RadioButton;
 import android.widget.TextView;
 
@@ -39,9 +41,12 @@
 import java.util.List;
 
 public class EncryptionInterstitial extends SettingsActivity {
+    private final static String TAG = EncryptionInterstitial.class.getSimpleName();
 
     protected static final String EXTRA_PASSWORD_QUALITY = "extra_password_quality";
+    protected static final String EXTRA_UNLOCK_METHOD_INTENT = "extra_unlock_method_intent";
     public static final String EXTRA_REQUIRE_PASSWORD = "extra_require_password";
+    private static final int CHOOSE_LOCK_REQUEST = 100;
 
     @Override
     public Intent getIntent() {
@@ -56,7 +61,7 @@
     }
 
     public static Intent createStartIntent(Context ctx, int quality,
-            boolean requirePasswordDefault) {
+            boolean requirePasswordDefault, Intent unlockMethodIntent) {
         return new Intent(ctx, EncryptionInterstitial.class)
                 .putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
                 .putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
@@ -64,7 +69,8 @@
                         R.string.encryption_continue_button))
                 .putExtra(EXTRA_PASSWORD_QUALITY, quality)
                 .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.encryption_interstitial_header)
-                .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault);
+                .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault)
+                .putExtra(EXTRA_UNLOCK_METHOD_INTENT, unlockMethodIntent);
     }
 
     public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
@@ -75,6 +81,7 @@
         private RadioButton mDontRequirePasswordToDecryptButton;
         private TextView mEncryptionMessage;
         private boolean mPasswordRequired;
+        private Intent mUnlockMethodIntent;
 
         @Override
         protected int getMetricsCategory() {
@@ -98,7 +105,9 @@
                     (TextView) view.findViewById(R.id.encryption_message);
             boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
-            int quality = getActivity().getIntent().getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
+            Intent intent = getActivity().getIntent();
+            final int quality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
+            mUnlockMethodIntent = (Intent) intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
             final int msgId;
             final int enableId;
             final int disableId;
@@ -136,6 +145,36 @@
 
             setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
                     EXTRA_REQUIRE_PASSWORD, true));
+
+            Button nextButton = getNextButton();
+            if (nextButton != null) {
+                nextButton.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        startLockIntent();
+                    }
+                });
+            }
+        }
+
+        protected void startLockIntent() {
+            if (mUnlockMethodIntent != null) {
+                mUnlockMethodIntent.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
+                startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);
+            } else {
+                Log.wtf(TAG, "no unlock intent to start");
+                finish();
+            }
+        }
+
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            super.onActivityResult(requestCode, resultCode, data);
+            if (requestCode == CHOOSE_LOCK_REQUEST &&
+                    resultCode == RESULT_FIRST_USER) {
+                getActivity().setResult(RESULT_OK, data);
+                finish();
+            }
         }
 
         @Override
@@ -206,15 +245,6 @@
             mPasswordRequired = required;
             mRequirePasswordToDecryptButton.setChecked(required);
             mDontRequirePasswordToDecryptButton.setChecked(!required);
-
-            // Updates value returned by SettingsActivity.onActivityResult().
-            SettingsActivity sa = (SettingsActivity)getActivity();
-            Intent resultIntentData = sa.getResultIntentData();
-            if (resultIntentData == null) {
-                resultIntentData = new Intent();
-                sa.setResultIntentData(resultIntentData);
-            }
-            resultIntentData.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
         }
 
         @Override
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index 44fd110..cc0014d 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -32,6 +32,7 @@
     public static final int SOUND = UNDECLARED + 2;
     public static final int CONFIGURE_NOTIFICATION = UNDECLARED + 3;
     public static final int CONFIGURE_WIFI = UNDECLARED + 4;
+    public static final int DISPLAY_SCREEN_ZOOM = UNDECLARED + 5;
 
     /**
      * Declare the view of this category.
diff --git a/src/com/android/settings/SetupChooseLockGeneric.java b/src/com/android/settings/SetupChooseLockGeneric.java
index 0b0333b..9559f8d 100644
--- a/src/com/android/settings/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/SetupChooseLockGeneric.java
@@ -170,9 +170,9 @@
 
         @Override
         protected Intent getEncryptionInterstitialIntent(Context context, int quality,
-                boolean required) {
+                boolean required, Intent unlockMethodIntent) {
             Intent intent = SetupEncryptionInterstitial.createStartIntent(context, quality,
-                    required);
+                    required, unlockMethodIntent);
             SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
             return intent;
         }
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
index cd943af..8d061ec 100644
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ b/src/com/android/settings/SetupEncryptionInterstitial.java
@@ -38,9 +38,9 @@
 public class SetupEncryptionInterstitial extends EncryptionInterstitial {
 
     public static Intent createStartIntent(Context ctx, int quality,
-            boolean requirePasswordDefault) {
+            boolean requirePasswordDefault, Intent unlockMethodIntent) {
         Intent startIntent = EncryptionInterstitial.createStartIntent(ctx, quality,
-                requirePasswordDefault);
+                requirePasswordDefault, unlockMethodIntent);
         startIntent.setClass(ctx, SetupEncryptionInterstitial.class);
         startIntent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)
                 .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
@@ -102,12 +102,7 @@
 
         @Override
         public void onNavigateNext() {
-            final SetupEncryptionInterstitial activity =
-                    (SetupEncryptionInterstitial) getActivity();
-            if (activity != null) {
-                activity.setResult(RESULT_OK, activity.getResultIntentData());
-                finish();
-            }
+            startLockIntent();
         }
     }
 }
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index b2ccdd1..672582d 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -85,6 +85,8 @@
             "toggle_lock_screen_rotation_preference";
     private static final String TOGGLE_SPEAK_PASSWORD_PREFERENCE =
             "toggle_speak_password_preference";
+    private static final String TOGGLE_LARGE_POINTER_ICON =
+            "toggle_large_pointer_icon";
     private static final String SELECT_LONG_PRESS_TIMEOUT_PREFERENCE =
             "select_long_press_timeout_preference";
     private static final String ENABLE_ACCESSIBILITY_GESTURE_PREFERENCE_SCREEN =
@@ -181,6 +183,7 @@
     private SwitchPreference mTogglePowerButtonEndsCallPreference;
     private SwitchPreference mToggleLockScreenRotationPreference;
     private SwitchPreference mToggleSpeakPasswordPreference;
+    private SwitchPreference mToggleLargePointerIconPreference;
     private ListPreference mSelectLongPressTimeoutPreference;
     private Preference mNoServicesMessagePreference;
     private PreferenceScreen mCaptioningPreferenceScreen;
@@ -278,6 +281,9 @@
         } else if (mToggleSpeakPasswordPreference == preference) {
             handleToggleSpeakPasswordPreferenceClick();
             return true;
+        } else if (mToggleLargePointerIconPreference == preference) {
+            handleToggleLargePointerIconPreferenceClick();
+            return true;
         } else if (mGlobalGesturePreferenceScreen == preference) {
             handleToggleEnableAccessibilityGesturePreferenceClick();
             return true;
@@ -322,6 +328,12 @@
                 mToggleSpeakPasswordPreference.isChecked() ? 1 : 0);
     }
 
+    private void handleToggleLargePointerIconPreferenceClick() {
+        Settings.Secure.putInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
+                mToggleLargePointerIconPreference.isChecked() ? 1 : 0);
+    }
+
     private void handleToggleEnableAccessibilityGesturePreferenceClick() {
         Bundle extras = mGlobalGesturePreferenceScreen.getExtras();
         extras.putString(EXTRA_TITLE, getString(
@@ -379,6 +391,10 @@
         mToggleSpeakPasswordPreference =
                 (SwitchPreference) findPreference(TOGGLE_SPEAK_PASSWORD_PREFERENCE);
 
+        // Large pointer icon.
+        mToggleLargePointerIconPreference =
+                (SwitchPreference) findPreference(TOGGLE_LARGE_POINTER_ICON);
+
         // Long press timeout.
         mSelectLongPressTimeoutPreference =
                 (ListPreference) findPreference(SELECT_LONG_PRESS_TIMEOUT_PREFERENCE);
@@ -565,6 +581,10 @@
                 Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0;
         mToggleSpeakPasswordPreference.setChecked(speakPasswordEnabled);
 
+        // Large pointer icon.
+        mToggleLargePointerIconPreference.setChecked(Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 0) != 0);
+
         // Long press timeout.
         final int longPressTimeout = Settings.Secure.getInt(getContentResolver(),
                 Settings.Secure.LONG_PRESS_TIMEOUT, mLongPressTimeoutDefault);
diff --git a/src/com/android/settings/display/DisplayDensityUtils.java b/src/com/android/settings/display/DisplayDensityUtils.java
new file mode 100644
index 0000000..cef5418
--- /dev/null
+++ b/src/com/android/settings/display/DisplayDensityUtils.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2015 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.settings.display;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+import java.util.Arrays;
+
+/**
+ * Utility methods for working with display density.
+ */
+class DisplayDensityUtils {
+    private static final String LOG_TAG = "DisplayDensityUtils";
+
+    /** Minimum increment between density scales. */
+    private static final float MIN_SCALE_INTERVAL = 0.09f;
+
+    /** Minimum density scale. This is available on all devices. */
+    private static final float MIN_SCALE = 0.85f;
+
+    /** Maximum density scale. The actual scale used depends on the device. */
+    private static final float MAX_SCALE = 1.50f;
+
+    /** Summary used for "normal" scale. */
+    private static final int SUMMARY_NORMAL = R.string.screen_zoom_summary_normal;
+
+    /** Summary used for "custom" scale. */
+    private static final int SUMMARY_CUSTOM = R.string.screen_zoom_summary_custom;
+
+    /**
+     * Summaries for scales smaller than "normal" in order of smallest to
+     * largest.
+     */
+    private static final int[] SUMMARIES_SMALLER = new int[] {
+            R.string.screen_zoom_summary_small
+    };
+
+    /**
+     * Summaries for scales larger than "normal" in order of smallest to
+     * largest.
+     */
+    private static final int[] SUMMARIES_LARGER = new int[] {
+            R.string.screen_zoom_summary_large,
+            R.string.screen_zoom_summary_very_large,
+            R.string.screen_zoom_summary_extremely_large,
+    };
+
+    /**
+     * Minimum allowed screen dimension, corresponds to resource qualifiers
+     * "small" or "sw320dp". This value must be at least the minimum screen
+     * size required by the CDD so that we meet developer expectations.
+     */
+    private static final int MIN_DIMENSION_DP = 320;
+
+    private final String[] mEntries;
+    private final int[] mValues;
+
+    private final int mNormalDensity;
+    private final int mCurrentIndex;
+
+    public DisplayDensityUtils(Context context) {
+        final int normalDensity = DisplayDensityUtils.getNormalDisplayDensity(
+                Display.DEFAULT_DISPLAY);
+        if (normalDensity <= 0) {
+            mEntries = null;
+            mValues = null;
+            mNormalDensity = 0;
+            mCurrentIndex = -1;
+            return;
+        }
+
+        final Resources res = context.getResources();
+        final DisplayMetrics metrics = res.getDisplayMetrics();
+        final int currentDensity = metrics.densityDpi;
+        int currentDensityIndex = -1;
+
+        // Compute number of "larger" and "smaller" scales for this display.
+        final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels);
+        final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
+        final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) normalDensity);
+        final float minScale = MIN_SCALE;
+        final int numLarger = (int) MathUtils.constrain((maxScale - 1) / MIN_SCALE_INTERVAL,
+                0, SUMMARIES_LARGER.length);
+        final int numSmaller = (int) MathUtils.constrain((1 - minScale) / MIN_SCALE_INTERVAL,
+                0, SUMMARIES_SMALLER.length);
+
+        String[] entries = new String[1 + numSmaller + numLarger];
+        int[] values = new int[entries.length];
+        int curIndex = 0;
+
+        if (numSmaller > 0) {
+            final float interval = (1 - minScale) / numSmaller;
+            for (int i = numSmaller - 1; i >= 0; i--) {
+                final int density = (int) (normalDensity * (1 - (i + 1) * interval));
+                if (currentDensity == density) {
+                    currentDensityIndex = curIndex;
+                }
+                entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
+                values[curIndex] = density;
+                curIndex++;
+            }
+        }
+
+        if (currentDensity == normalDensity) {
+            currentDensityIndex = curIndex;
+        }
+        values[curIndex] = normalDensity;
+        entries[curIndex] = res.getString(SUMMARY_NORMAL);
+        curIndex++;
+
+        if (numLarger > 0) {
+            final float interval = (maxScale - 1) / numLarger;
+            for (int i = 0; i < numLarger; i++) {
+                final int density = (int) (normalDensity * (1 + (i + 1) * interval));
+                if (currentDensity == density) {
+                    currentDensityIndex = curIndex;
+                }
+                values[curIndex] = density;
+                entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
+                curIndex++;
+            }
+        }
+
+        final int displayIndex;
+        if (currentDensityIndex >= 0) {
+            displayIndex = currentDensityIndex;
+        } else {
+            // We don't understand the current density. Must have been set by
+            // someone else. Make room for another entry...
+            values = Arrays.copyOf(values, values.length + 1);
+            values[curIndex] = currentDensity;
+
+            entries = Arrays.copyOf(entries, values.length + 1);
+            entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);
+
+            displayIndex = curIndex;
+        }
+
+        mNormalDensity = normalDensity;
+        mCurrentIndex = displayIndex;
+        mEntries = entries;
+        mValues = values;
+    }
+
+    public String[] getEntries() {
+        return mEntries;
+    }
+
+    public int[] getValues() {
+        return mValues;
+    }
+
+    public int getCurrentIndex() {
+        return mCurrentIndex;
+    }
+
+    public int getNormalDensity() {
+        return mNormalDensity;
+    }
+
+    /**
+     * Returns the normal (default) density for the specified display.
+     *
+     * @param displayId the identifier of the display
+     * @return the normal density of the specified display, or {@code -1} if
+     *         the display does not exist or the density could not be obtained
+     */
+    private static int getNormalDisplayDensity(int displayId) {
+       try {
+           final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+           return wm.getInitialDisplayDensity(displayId);
+       } catch (RemoteException exc) {
+           return -1;
+       }
+    }
+
+    /**
+     * Asynchronously applies display density changes to the specified display.
+     *
+     * @param displayId the identifier of the display to modify
+     */
+    public static void clearForcedDisplayDensity(final int displayId) {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+                    wm.clearForcedDisplayDensity(displayId);
+                } catch (RemoteException exc) {
+                    Log.w(LOG_TAG, "Unable to clear forced display density setting");
+                }
+            }
+        });
+    }
+
+    /**
+     * Asynchronously applies display density changes to the specified display.
+     *
+     * @param displayId the identifier of the display to modify
+     * @param density the density to force for the specified display
+     */
+    public static void setForcedDisplayDensity(final int displayId, final int density) {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+                    wm.setForcedDisplayDensity(displayId, density);
+                } catch (RemoteException exc) {
+                    Log.w(LOG_TAG, "Unable to save forced display density setting");
+                }
+            }
+        });
+    }
+}
diff --git a/src/com/android/settings/display/ScreenZoomPreference.java b/src/com/android/settings/display/ScreenZoomPreference.java
new file mode 100644
index 0000000..78cc49c
--- /dev/null
+++ b/src/com/android/settings/display/ScreenZoomPreference.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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.settings.display;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.PreferenceGroup;
+import android.util.AttributeSet;
+
+/**
+ * Preference for changing the density of the display on which the preference
+ * is visible.
+ */
+public class ScreenZoomPreference extends PreferenceGroup {
+    public ScreenZoomPreference(Context context, AttributeSet attrs) {
+        super(context, attrs, TypedArrayUtils.getAttr(context,
+                android.support.v7.preference.R.attr.preferenceScreenStyle,
+                android.R.attr.preferenceScreenStyle));
+
+        setFragment("com.android.settings.display.ScreenZoomSettings");
+
+        final DisplayDensityUtils density = new DisplayDensityUtils(context);
+        final int defaultIndex = density.getCurrentIndex();
+        if (defaultIndex < 0) {
+            setVisible(false);
+            setEnabled(false);
+        } else {
+            final String[] entries = density.getEntries();
+            final int currentIndex = density.getCurrentIndex();
+            setSummary(entries[currentIndex]);
+        }
+    }
+
+    @Override
+    protected boolean isOnSameScreenAsChildren() {
+        return false;
+    }
+}
diff --git a/src/com/android/settings/display/ScreenZoomSettings.java b/src/com/android/settings/display/ScreenZoomSettings.java
new file mode 100644
index 0000000..1ddcaab
--- /dev/null
+++ b/src/com/android/settings/display/ScreenZoomSettings.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2015 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.settings.display;
+
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Preference fragment used to control screen zoom.
+ */
+public class ScreenZoomSettings extends SettingsPreferenceFragment implements Indexable {
+    /** Duration to use when cross-fading between previews. */
+    private static final long CROSS_FADE_DURATION_MS = 400;
+
+    /** Interpolator to use when cross-fading between previews. */
+    private static final Interpolator FADE_IN_INTERPOLATOR = new DecelerateInterpolator();
+
+    /** Interpolator to use when cross-fading between previews. */
+    private static final Interpolator FADE_OUT_INTERPOLATOR = new AccelerateInterpolator();
+
+    private ViewGroup mPreviewFrame;
+    private TextView mLabel;
+    private View mLarger;
+    private View mSmaller;
+
+    private String[] mEntries;
+    private int[] mValues;
+    private int mNormalDensity;
+    private int mInitialIndex;
+
+    private int mCurrentIndex;
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final DisplayDensityUtils density = new DisplayDensityUtils(getContext());
+
+        final int initialIndex = density.getCurrentIndex();
+        if (initialIndex < 0) {
+            // Failed to obtain normal density, which means we failed to
+            // connect to the window manager service. Just use the current
+            // density and don't let the user change anything.
+            final int densityDpi = getResources().getDisplayMetrics().densityDpi;
+            mValues = new int[] { densityDpi };
+            mEntries = new String[] { getString(R.string.screen_zoom_summary_normal) };
+            mInitialIndex = 0;
+            mNormalDensity = densityDpi;
+        } else {
+            mValues = density.getValues();
+            mEntries = density.getEntries();
+            mInitialIndex = initialIndex;
+            mNormalDensity = density.getNormalDensity();
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View root = super.onCreateView(inflater, container, savedInstanceState);
+        final ViewGroup list_container = (ViewGroup) root.findViewById(android.R.id.list_container);
+        list_container.removeAllViews();
+
+        final View content = inflater.inflate(R.layout.screen_zoom_activity, list_container, false);
+        list_container.addView(content);
+
+        mLabel = (TextView) content.findViewById(R.id.current_density);
+
+        // The maximum SeekBar value always needs to be non-zero. If there's
+        // only one available zoom level, we'll handle this by disabling the
+        // seek bar.
+        final int max = Math.max(1, mValues.length - 1);
+
+        final SeekBar seekBar = (SeekBar) content.findViewById(R.id.seek_bar);
+        seekBar.setMax(max);
+        seekBar.setProgress(mInitialIndex);
+        seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                setPreviewLayer(progress, true);
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {}
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {}
+        });
+
+        mSmaller = content.findViewById(R.id.smaller);
+        mSmaller.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                final int progress = seekBar.getProgress();
+                if (progress > 0) {
+                    seekBar.setProgress(progress - 1, true);
+                }
+            }
+        });
+
+        mLarger = content.findViewById(R.id.larger);
+        mLarger.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                final int progress = seekBar.getProgress();
+                if (progress < seekBar.getMax()) {
+                    seekBar.setProgress(progress + 1, true);
+                }
+            }
+        });
+
+        if (mValues.length == 1) {
+            // The larger and smaller buttons will be disabled when we call
+            // setPreviewLayer() later in this method.
+            seekBar.setEnabled(false);
+        }
+
+        mPreviewFrame = (FrameLayout) content.findViewById(R.id.preview_frame);
+
+        // Populate the sample layouts.
+        final Context context = getContext();
+        final Configuration origConfig = context.getResources().getConfiguration();
+        for (int mValue : mValues) {
+            final Configuration config = new Configuration(origConfig);
+            config.densityDpi = mValue;
+
+            // Create a new configuration for the specified density. It won't
+            // have any theme set, so manually apply the current theme.
+            final Context configContext = context.createConfigurationContext(config);
+            configContext.setTheme(context.getThemeResId());
+
+            final LayoutInflater configInflater = LayoutInflater.from(configContext);
+            final View sampleView = configInflater.inflate(
+                    R.layout.screen_zoom_preview, mPreviewFrame, false);
+            sampleView.setAlpha(0);
+            sampleView.setVisibility(View.INVISIBLE);
+
+            mPreviewFrame.addView(sampleView);
+        }
+
+        setPreviewLayer(mInitialIndex, false);
+
+        return root;
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+
+        // This will adjust the density SLIGHTLY after the activity has
+        // finished, which could be considered a feature or a bug...
+        commit();
+    }
+
+    private void setPreviewLayer(int index, boolean animate) {
+        mLabel.setText(mEntries[index]);
+
+        if (mCurrentIndex >= 0) {
+            final View lastLayer = mPreviewFrame.getChildAt(mCurrentIndex);
+            if (animate) {
+                lastLayer.animate()
+                        .alpha(0)
+                        .setInterpolator(FADE_OUT_INTERPOLATOR)
+                        .setDuration(CROSS_FADE_DURATION_MS)
+                        .withEndAction(new Runnable() {
+                            @Override
+                            public void run() {
+                                lastLayer.setVisibility(View.INVISIBLE);
+                            }
+                        });
+            } else {
+                lastLayer.setAlpha(0);
+                lastLayer.setVisibility(View.INVISIBLE);
+            }
+        }
+
+        final View nextLayer = mPreviewFrame.getChildAt(index);
+        if (animate) {
+            nextLayer.animate()
+                    .alpha(1)
+                    .setInterpolator(FADE_IN_INTERPOLATOR)
+                    .setDuration(CROSS_FADE_DURATION_MS)
+                    .withStartAction(new Runnable() {
+                @Override
+                public void run() {
+                    nextLayer.setVisibility(View.VISIBLE);
+                }
+            });
+        } else {
+            nextLayer.setVisibility(View.VISIBLE);
+            nextLayer.setAlpha(1);
+        }
+
+        mSmaller.setEnabled(index > 0);
+        mLarger.setEnabled(index < mEntries.length - 1);
+
+        mCurrentIndex = index;
+    }
+
+    /**
+     * Persists the selected density and sends a configuration change.
+     */
+    private void commit() {
+        final int densityDpi = mValues[mCurrentIndex];
+        if (densityDpi == mNormalDensity) {
+            DisplayDensityUtils.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
+        } else {
+            DisplayDensityUtils.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, densityDpi);
+        }
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.DISPLAY_SCREEN_ZOOM;
+    }
+
+    /** Index provider used to expose this fragment in search. */
+    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
+                    final Resources res = context.getResources();
+                    final SearchIndexableRaw data = new SearchIndexableRaw(context);
+                    data.title = res.getString(R.string.screen_zoom_title);
+                    data.screenTitle = res.getString(R.string.screen_zoom_title);
+                    data.keywords = res.getString(R.string.screen_zoom_keywords);
+
+                    final List<SearchIndexableRaw> result = new ArrayList<>(1);
+                    result.add(data);
+                    return result;
+                }
+            };
+}
diff --git a/src/com/android/settings/display/TouchBlockingFrameLayout.java b/src/com/android/settings/display/TouchBlockingFrameLayout.java
new file mode 100644
index 0000000..3f5483d
--- /dev/null
+++ b/src/com/android/settings/display/TouchBlockingFrameLayout.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.settings.display;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+/**
+ * Extension of FrameLayout that consumes all touch events.
+ */
+public class TouchBlockingFrameLayout extends FrameLayout {
+    public TouchBlockingFrameLayout(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return true;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return true;
+    }
+}
diff --git a/src/com/android/settings/notification/ImportanceSeekBarPreference.java b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
index fdba42c..ec77467 100644
--- a/src/com/android/settings/notification/ImportanceSeekBarPreference.java
+++ b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
@@ -33,7 +33,6 @@
         SeekBar.OnSeekBarChangeListener {
     private static final String TAG = "ImportanceSeekBarPref";
 
-    public static final int IMPORTANCE_PROGRESS_OFFSET = 2;
     private Callback mCallback;
     private TextView mSummaryTextView;
     private String mSummary;
@@ -89,8 +88,6 @@
     }
 
     private String getProgressSummary(int progress) {
-        // Map progress 0-4 values to Importance's -2-2.
-        progress = progress - IMPORTANCE_PROGRESS_OFFSET;
         switch (progress) {
             case NotificationListenerService.Ranking.IMPORTANCE_NONE:
                 return getContext().getString(
diff --git a/src/com/android/settings/notification/TopicNotificationSettings.java b/src/com/android/settings/notification/TopicNotificationSettings.java
index 71196b7..e847e34 100644
--- a/src/com/android/settings/notification/TopicNotificationSettings.java
+++ b/src/com/android/settings/notification/TopicNotificationSettings.java
@@ -135,13 +135,11 @@
                 mTopicRow.importance == NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED
                 ? NotificationListenerService.Ranking.IMPORTANCE_DEFAULT
                         : mTopicRow.importance;
-        mImportance.setProgress(
-                importance + ImportanceSeekBarPreference.IMPORTANCE_PROGRESS_OFFSET);
+        mImportance.setProgress(importance);
         mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
             @Override
             public void onImportanceChanged(int progress) {
-                mBackend.setImportance(mTopicRow.pkg, mTopicRow.uid, mTopicRow.topic,
-                        progress - ImportanceSeekBarPreference.IMPORTANCE_PROGRESS_OFFSET);
+                mBackend.setImportance(mTopicRow.pkg, mTopicRow.uid, mTopicRow.topic, progress);
             }
         });
         mPriority.setChecked(mTopicRow.priority);
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 4ac4fb8..3d5ff35 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -36,6 +36,7 @@
 import com.android.settings.applications.ManageDefaultApps;
 import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.display.ScreenZoomSettings;
 import com.android.settings.fuelgauge.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
@@ -122,6 +123,7 @@
 
         // Display
         sRankMap.put(DisplaySettings.class.getName(), RANK_DISPLAY);
+        sRankMap.put(ScreenZoomSettings.class.getName(), RANK_WIFI);
 
         // Wallpapers
         sRankMap.put(WallpaperTypeSettings.class.getName(), RANK_WALLPAPER);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 6d6ca08..f15ff63 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -38,6 +38,7 @@
 import com.android.settings.applications.ManageDefaultApps;
 import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.display.ScreenZoomSettings;
 import com.android.settings.fuelgauge.BatterySaverSettings;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
@@ -131,6 +132,13 @@
                         HomeSettings.class.getName(),
                         R.drawable.ic_settings_home));
 
+        sResMap.put(ScreenZoomSettings.class.getName(),
+                new SearchIndexableResource(
+                        Ranking.getRankForClassName(ScreenZoomSettings.class.getName()),
+                        NO_DATA_RES_ID,
+                        ScreenZoomSettings.class.getName(),
+                        R.drawable.ic_settings_display));
+
         sResMap.put(DisplaySettings.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(DisplaySettings.class.getName()),
diff --git a/src/com/android/settings/vpn2/AppPreference.java b/src/com/android/settings/vpn2/AppPreference.java
index 84897be..af4192e 100644
--- a/src/com/android/settings/vpn2/AppPreference.java
+++ b/src/com/android/settings/vpn2/AppPreference.java
@@ -39,18 +39,13 @@
     private int mState = STATE_DISCONNECTED;
     private String mPackageName;
     private String mName;
-    private int mUid;
+    private int mUserId = UserHandle.USER_NULL;
 
-    public AppPreference(Context context, OnClickListener onManage, final String packageName,
-            int uid) {
+    public AppPreference(Context context, OnClickListener onManage) {
         super(context, null /* attrs */, onManage);
-        mPackageName = packageName;
-        mUid = uid;
-        update();
     }
 
     public PackageInfo getPackageInfo() {
-        UserHandle user = new UserHandle(UserHandle.getUserId(mUid));
         try {
             PackageManager pm = getUserContext().getPackageManager();
             return pm.getPackageInfo(mPackageName, 0 /* flags */);
@@ -67,8 +62,18 @@
         return mPackageName;
     }
 
-    public int getUid() {
-        return mUid;
+    public void setPackageName(String name) {
+        mPackageName = name;
+        update();
+    }
+
+    public int getUserId() {
+        return mUserId;
+    }
+
+    public void setUserId(int userId) {
+        mUserId = userId;
+        update();
     }
 
     public int getState() {
@@ -81,6 +86,10 @@
     }
 
     private void update() {
+        if (mPackageName == null || mUserId == UserHandle.USER_NULL) {
+            return;
+        }
+
         final String[] states = getContext().getResources().getStringArray(R.array.vpn_states);
         setSummary(mState != STATE_DISCONNECTED ? states[mState] : "");
 
@@ -116,7 +125,7 @@
     }
 
     private Context getUserContext() throws PackageManager.NameNotFoundException {
-        UserHandle user = new UserHandle(UserHandle.getUserId(mUid));
+        UserHandle user = UserHandle.of(mUserId);
         return getContext().createPackageContextAsUser(
                 getContext().getPackageName(), 0 /* flags */, user);
     }
@@ -128,7 +137,7 @@
             if ((result = another.mState - mState) == 0 &&
                     (result = mName.compareToIgnoreCase(another.mName)) == 0 &&
                     (result = mPackageName.compareTo(another.mPackageName)) == 0) {
-                result = mUid - another.mUid;
+                result = mUserId - another.mUserId;
             }
             return result;
         } else if (preference instanceof ConfigPreference) {
diff --git a/src/com/android/settings/vpn2/ConfigPreference.java b/src/com/android/settings/vpn2/ConfigPreference.java
index a2736a0..c7ecddb 100644
--- a/src/com/android/settings/vpn2/ConfigPreference.java
+++ b/src/com/android/settings/vpn2/ConfigPreference.java
@@ -31,12 +31,15 @@
  * state.
  */
 public class ConfigPreference extends ManageablePreference {
-    private VpnProfile mProfile;
-    private int mState = -1;
+    public static int STATE_NONE = -1;
 
-    ConfigPreference(Context context, OnClickListener onManage, VpnProfile profile) {
+    private VpnProfile mProfile;
+
+    /** One of the STATE_* fields from LegacyVpnInfo, or STATE_NONE */
+    private int mState = STATE_NONE;
+
+    ConfigPreference(Context context, OnClickListener onManage) {
         super(context, null /* attrs */, onManage);
-        setProfile(profile);
     }
 
     public VpnProfile getProfile() {
@@ -54,15 +57,16 @@
     }
 
     private void update() {
-        if (mState < 0) {
+        if (mState == STATE_NONE) {
             setSummary("");
         } else {
-            String[] states = getContext().getResources()
-                    .getStringArray(R.array.vpn_states);
+            final String[] states = getContext().getResources().getStringArray(R.array.vpn_states);
             setSummary(states[mState]);
         }
-        setIcon(R.mipmap.ic_launcher_settings);
-        setTitle(mProfile.name);
+        if (mProfile != null) {
+            setIcon(R.mipmap.ic_launcher_settings);
+            setTitle(mProfile.name);
+        }
         notifyHierarchyChanged();
     }
 
@@ -72,7 +76,7 @@
             ConfigPreference another = (ConfigPreference) preference;
             int result;
             if ((result = another.mState - mState) == 0 &&
-                    (result = mProfile.name.compareTo(another.mProfile.name)) == 0 &&
+                    (result = mProfile.name.compareToIgnoreCase(another.mProfile.name)) == 0 &&
                     (result = mProfile.type - another.mProfile.type) == 0) {
                 result = mProfile.key.compareTo(another.mProfile.key);
             }
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index b903463..00f6a12 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -16,13 +16,16 @@
 
 package com.android.settings.vpn2;
 
+import android.annotation.NonNull;
+import android.annotation.UiThread;
+import android.annotation.WorkerThread;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
@@ -40,7 +43,9 @@
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceGroup;
 import android.support.v7.preference.PreferenceScreen;
-import android.util.SparseArray;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -57,8 +62,10 @@
 import com.google.android.collect.Lists;
 
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import static android.app.AppOpsManager.OP_ACTIVATE_VPN;
 
@@ -87,8 +94,8 @@
 
     private final KeyStore mKeyStore = KeyStore.getInstance();
 
-    private HashMap<String, ConfigPreference> mConfigPreferences = new HashMap<>();
-    private HashMap<String, AppPreference> mAppPreferences = new HashMap<>();
+    private Map<String, ConfigPreference> mConfigPreferences = new ArrayMap<>();
+    private Map<AppVpnInfo, AppPreference> mAppPreferences = new ArrayMap<>();
 
     private Handler mUpdater;
     private LegacyVpnInfo mConnectedLegacyVpn;
@@ -211,58 +218,64 @@
     public boolean handleMessage(Message message) {
         mUpdater.removeMessages(RESCAN_MESSAGE);
 
-        // Pref group within which to list VPNs
-        PreferenceGroup vpnGroup = getPreferenceScreen();
-        vpnGroup.removeAll();
-        mConfigPreferences.clear();
-        mAppPreferences.clear();
+        final List<VpnProfile> vpnProfiles = loadVpnProfiles(mKeyStore);
+        final List<AppVpnInfo> vpnApps = getVpnApps();
 
-        // Fetch configured VPN profiles from KeyStore
-        for (VpnProfile profile : loadVpnProfiles(mKeyStore)) {
-            final ConfigPreference pref = new ConfigPreference(getPrefContext(), mManageListener,
-                    profile);
-            pref.setOnPreferenceClickListener(this);
-            mConfigPreferences.put(profile.key, pref);
-            vpnGroup.addPreference(pref);
-        }
+        final List<LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns();
+        final List<AppVpnInfo> connectedAppVpns = getConnectedAppVpns();
 
-        // 3rd-party VPN apps can change elsewhere. Reload them every time.
-        for (AppOpsManager.PackageOps pkg : getVpnApps()) {
-            String key = getVpnIdentifier(UserHandle.getUserId(pkg.getUid()), pkg.getPackageName());
-            final AppPreference pref = new AppPreference(getPrefContext(), mManageListener,
-                    pkg.getPackageName(), pkg.getUid());
-            pref.setOnPreferenceClickListener(this);
-            mAppPreferences.put(key, pref);
-            vpnGroup.addPreference(pref);
-        }
+        // Refresh the PreferenceGroup which lists VPNs
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Find new VPNs by subtracting existing ones from the full set
+                final Set<Preference> updates = new ArraySet<>();
 
-        // Mark out connections with a subtitle
-        try {
-            // Legacy VPNs
-            mConnectedLegacyVpn = null;
-            LegacyVpnInfo info = mConnectivityService.getLegacyVpnInfo(UserHandle.myUserId());
-            if (info != null) {
-                ConfigPreference preference = mConfigPreferences.get(info.key);
-                if (preference != null) {
-                    preference.setState(info.state);
-                    mConnectedLegacyVpn = info;
+                for (VpnProfile profile : vpnProfiles) {
+                    ConfigPreference p = findOrCreatePreference(profile);
+                    p.setState(ConfigPreference.STATE_NONE);
+                    updates.add(p);
                 }
-            }
+                for (AppVpnInfo app : vpnApps) {
+                    AppPreference p = findOrCreatePreference(app);
+                    p.setState(AppPreference.STATE_DISCONNECTED);
+                    updates.add(p);
+                }
 
-            // Third-party VPNs
-            for (UserHandle profile : mUserManager.getUserProfiles()) {
-                VpnConfig cfg = mConnectivityService.getVpnConfig(profile.getIdentifier());
-                if (cfg != null) {
-                    final String key = getVpnIdentifier(profile.getIdentifier(), cfg.user);
-                    final AppPreference preference = mAppPreferences.get(key);
+                // Trim preferences for deleted VPNs
+                mConfigPreferences.values().retainAll(updates);
+                mAppPreferences.values().retainAll(updates);
+
+                final PreferenceGroup vpnGroup = getPreferenceScreen();
+                for (int i = vpnGroup.getPreferenceCount() - 1; i >= 0; i--) {
+                    Preference p = vpnGroup.getPreference(i);
+                    if (updates.contains(p)) {
+                        updates.remove(p);
+                    } else {
+                        vpnGroup.removePreference(p);
+                    }
+                }
+
+                // Show any new preferences on the screen
+                for (Preference pref : updates) {
+                    vpnGroup.addPreference(pref);
+                }
+
+                // Mark connected VPNs
+                for (LegacyVpnInfo info : connectedLegacyVpns) {
+                    final ConfigPreference preference = mConfigPreferences.get(info.key);
+                    if (preference != null) {
+                        preference.setState(info.state);
+                    }
+                }
+                for (AppVpnInfo app : connectedAppVpns) {
+                    final AppPreference preference = mAppPreferences.get(app);
                     if (preference != null) {
                         preference.setState(AppPreference.STATE_CONNECTED);
                     }
                 }
             }
-        } catch (RemoteException e) {
-            // ignore
-        }
+        });
 
         mUpdater.sendEmptyMessageDelayed(RESCAN_MESSAGE, RESCAN_INTERVAL_MS);
         return true;
@@ -278,7 +291,7 @@
                     mConnectedLegacyVpn.intent.send();
                     return true;
                 } catch (Exception e) {
-                    // ignore
+                    Log.w(LOG_TAG, "Starting config intent failed", e);
                 }
             }
             ConfigDialogFragment.show(this, profile, false /* editing */, true /* exists */);
@@ -289,7 +302,7 @@
 
             if (!connected) {
                 try {
-                    UserHandle user = new UserHandle(UserHandle.getUserId(pref.getUid()));
+                    UserHandle user = UserHandle.of(pref.getUserId());
                     Context userContext = getActivity().createPackageContextAsUser(
                             getActivity().getPackageName(), 0 /* flags */, user);
                     PackageManager pm = userContext.getPackageManager();
@@ -299,11 +312,11 @@
                         return true;
                     }
                 } catch (PackageManager.NameNotFoundException nnfe) {
-                    // Fall through
+                    Log.w(LOG_TAG, "VPN provider does not exist: " + pref.getPackageName(), nnfe);
                 }
             }
 
-            // Already onnected or no launch intent available - show an info dialog
+            // Already connected or no launch intent available - show an info dialog
             PackageInfo pkgInfo = pref.getPackageInfo();
             AppDialogFragment.show(this, pkgInfo, pref.getLabel(), false /* editing */, connected);
             return true;
@@ -311,6 +324,11 @@
         return false;
     }
 
+    @Override
+    protected int getHelpResource() {
+        return R.string.help_url_vpn;
+    }
+
     private View.OnClickListener mManageListener = new View.OnClickListener() {
         @Override
         public void onClick(View view) {
@@ -329,10 +347,6 @@
         }
     };
 
-    private static String getVpnIdentifier(int userId, String packageName) {
-        return Integer.toString(userId)+ "_" + packageName;
-    }
-
     private NetworkCallback mNetworkCallback = new NetworkCallback() {
         @Override
         public void onAvailable(Network network) {
@@ -349,18 +363,68 @@
         }
     };
 
-    @Override
-    protected int getHelpResource() {
-        return R.string.help_url_vpn;
+    @UiThread
+    private ConfigPreference findOrCreatePreference(VpnProfile profile) {
+        ConfigPreference pref = mConfigPreferences.get(profile.key);
+        if (pref == null) {
+            pref = new ConfigPreference(getPrefContext(), mManageListener);
+            pref.setOnPreferenceClickListener(this);
+            mConfigPreferences.put(profile.key, pref);
+        }
+        pref.setProfile(profile);
+        return pref;
     }
 
-    private List<AppOpsManager.PackageOps> getVpnApps() {
-        List<AppOpsManager.PackageOps> result = Lists.newArrayList();
+    @UiThread
+    private AppPreference findOrCreatePreference(AppVpnInfo app) {
+        AppPreference pref = mAppPreferences.get(app);
+        if (pref == null) {
+            pref = new AppPreference(getPrefContext(), mManageListener);
+            pref.setOnPreferenceClickListener(this);
+            mAppPreferences.put(app, pref);
+        }
+        pref.setUserId(app.userId);
+        pref.setPackageName(app.packageName);
+        return pref;
+    }
+
+    @WorkerThread
+    private List<LegacyVpnInfo> getConnectedLegacyVpns() {
+        try {
+            mConnectedLegacyVpn = mConnectivityService.getLegacyVpnInfo(UserHandle.myUserId());
+            if (mConnectedLegacyVpn != null) {
+                return Collections.singletonList(mConnectedLegacyVpn);
+            }
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Failure updating VPN list with connected legacy VPNs", e);
+        }
+        return Collections.emptyList();
+    }
+
+    @WorkerThread
+    private List<AppVpnInfo> getConnectedAppVpns() {
+        // Mark connected third-party services
+        List<AppVpnInfo> connections = new ArrayList<>();
+        try {
+            for (UserHandle profile : mUserManager.getUserProfiles()) {
+                VpnConfig config = mConnectivityService.getVpnConfig(profile.getIdentifier());
+                if (config != null && !config.legacy) {
+                    connections.add(new AppVpnInfo(profile.getIdentifier(), config.user));
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Failure updating VPN list with connected app VPNs", e);
+        }
+        return connections;
+    }
+
+    private List<AppVpnInfo> getVpnApps() {
+        List<AppVpnInfo> result = Lists.newArrayList();
 
         // Build a filter of currently active user profiles.
-        SparseArray<Boolean> currentProfileIds = new SparseArray<>();
+        Set<Integer> currentProfileIds = new ArraySet<>();
         for (UserHandle profile : mUserManager.getUserProfiles()) {
-            currentProfileIds.put(profile.getIdentifier(), Boolean.TRUE);
+            currentProfileIds.add(profile.getIdentifier());
         }
 
         // Fetch VPN-enabled apps from AppOps.
@@ -369,7 +433,7 @@
         if (apps != null) {
             for (AppOpsManager.PackageOps pkg : apps) {
                 int userId = UserHandle.getUserId(pkg.getUid());
-                if (currentProfileIds.get(userId) == null) {
+                if (!currentProfileIds.contains(userId)) {
                     // Skip packages for users outside of our profile group.
                     continue;
                 }
@@ -382,7 +446,7 @@
                     }
                 }
                 if (allowed) {
-                    result.add(pkg);
+                    result.add(new AppVpnInfo(userId, pkg.getPackageName()));
                 }
             }
         }
@@ -407,4 +471,29 @@
         }
         return result;
     }
+
+    /** Utility holder for packageName:userId pairs */
+    private static class AppVpnInfo {
+        public int userId;
+        public String packageName;
+
+        public AppVpnInfo(int userId, @NonNull String packageName) {
+            this.userId = userId;
+            this.packageName = packageName;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof AppVpnInfo) {
+                AppVpnInfo that = (AppVpnInfo) other;
+                return userId == that.userId && packageName.equals(that.packageName);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return (packageName != null ? packageName.hashCode() : 0) * 31 + userId;
+        }
+    }
 }