Merge "Disable AssistGestureSetting search if not supported" into oc-mr1-dev
diff --git a/res/drawable/ic_data_saver.xml b/res/drawable/ic_data_saver.xml
index 7356772..d2d55a9 100644
--- a/res/drawable/ic_data_saver.xml
+++ b/res/drawable/ic_data_saver.xml
@@ -17,14 +17,9 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,19.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.5 2.6,-6.4 6.0,-6.9L11.0,2.0C5.9,2.5 2.0,6.8 2.0,12.0c0.0,5.5 4.5,10.0 10.0,10.0c3.3,0.0 6.2,-1.6 8.1,-4.1l-2.6,-1.5C16.2,18.0 14.2,19.0 12.0,19.0z"/>
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M13.0,2.0l0.0,3.0c3.4,0.5 6.0,3.4 6.0,6.9c0.0,0.9 -0.2,1.8 -0.5,2.5l2.6,1.5c0.6,-1.2 0.9,-2.6 0.9,-4.1C22.0,6.8 18.0,2.6 13.0,2.0z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M16.0,11.0l0.0,2.0 -3.0,0.0 0.0,3.0 -2.0,0.0 0.0,-3.0 -3.0,0.0 0.0,-2.0 3.0,0.0 0.0,-3.0 2.0,0.0 0.0,3.0z"/>
+        android:pathData="M18.32,16.75l1.32,0.76c0.26,0.15 0.34,0.51 0.15,0.74 -2.09,2.6 -5.44,4.14 -9.14,3.65 -4.4,-0.58 -7.96,-4.12 -8.56,-8.52C1.34,7.8 5.21,2.95 10.43,2.12c0.3,-0.05 0.57,0.2 0.57,0.5v1.53c0,0.24 -0.18,0.44 -0.41,0.49 -3.6,0.69 -6.29,3.95 -6.07,7.79 0.21,3.82 3.43,6.95 7.25,7.07 2.37,0.08 4.51,-0.96 5.93,-2.63a0.48,0.48 0,0 1,0.62 -0.12zM19.5,12c0,0.83 -0.14,1.63 -0.39,2.38 -0.08,0.23 0.01,0.47 0.21,0.59l1.33,0.77c0.26,0.15 0.61,0.04 0.72,-0.24 0.4,-1.09 0.63,-2.27 0.63,-3.5 0,-4.99 -3.65,-9.12 -8.43,-9.88 -0.3,-0.04 -0.57,0.2 -0.57,0.5v1.53c0,0.24 0.18,0.44 0.41,0.48 3.46,0.68 6.09,3.72 6.09,7.37z" />
 </vector>
diff --git a/res/drawable/ic_network_cell.xml b/res/drawable/ic_network_cell.xml
index cc3c633..6da57ef 100644
--- a/res/drawable/ic_network_cell.xml
+++ b/res/drawable/ic_network_cell.xml
@@ -20,10 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?android:attr/colorControlNormal">
     <path
-        android:pathData="M2,22h20V2z"
-        android:fillAlpha=".3"
-        android:fillColor="#FFFFFFFF"/>
-    <path
-        android:pathData="M17,7L2,22h15z"
+        android:pathData="m3.8,22l17.19,0c0.55,0 1.01,-0.45 1.01,-1.01l0,-17.19c0,-0.71 -0.87,-1.08 -1.38,-0.57l-17.38,17.39c-0.51,0.51 -0.15,1.38 0.56,1.38z"
         android:fillColor="#FFFFFFFF"/>
 </vector>
diff --git a/res/drawable/ic_settings_bluetooth.xml b/res/drawable/ic_settings_bluetooth.xml
index fb4dfa4..6e32e1a 100644
--- a/res/drawable/ic_settings_bluetooth.xml
+++ b/res/drawable/ic_settings_bluetooth.xml
@@ -16,10 +16,10 @@
 <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:viewportWidth="24.0"
+        android:viewportHeight="24.0"
         android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M35.41,15.41L24.0,4.0l-2.0,0.0l0.0,15.17L12.83,10.0 10.0,12.83 21.17,24.0 10.0,35.17 12.83,38.0 22.0,28.83L22.0,44.0l2.0,0.0l11.41,-11.41L26.83,24.0l8.58,-8.59zM26.0,11.66l3.76,3.76L26.0,19.17l0.0,-7.51zm3.76,20.93L26.0,36.34l0.0,-7.52l3.76,3.77z"/>
+        android:pathData="M13.5,12l3.8,-3.7c0.4,-0.4 0.4,-1.1 0,-1.5l-4.5,-4.5c-0.4,-0.4 -1.1,-0.4 -1.5,0.1C11.1,2.5 11,2.8 11,3v6.4L6.9,5.4C6.5,5 5.9,5 5.5,5.4s-0.4,1.1 0,1.5l5.1,5.1l-5.1,5.1c-0.4,0.4 -0.4,1.1 0,1.5s1.1,0.4 1.5,0l4.1,-4V21c0,0.6 0.5,1 1,1c0.3,0 0.5,-0.1 0.7,-0.3l0.1,0l4.5,-4.5c0.4,-0.4 0.4,-1.1 0,-1.5L13.5,12zM13,9.7V5.4l2.1,2.2L13,9.7zM13,18.6v-4.3l2.1,2.2L13,18.6z"/>
 </vector>
diff --git a/res/drawable/ic_settings_wireless.xml b/res/drawable/ic_settings_wireless.xml
index 9859f31..0c894eb 100644
--- a/res/drawable/ic_settings_wireless.xml
+++ b/res/drawable/ic_settings_wireless.xml
@@ -16,10 +16,10 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24.0dp"
         android:height="24.0dp"
-        android:viewportWidth="18.0"
-        android:viewportHeight="18.0"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
         android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M9.01,15.99l8.8,-10.96C17.47,4.77 14.08,2.0 9.0,2.0S0.53,4.7 0.19,5.03l8.8,10.96l0.02,0.0z"/>
+        android:pathData="M23.66,8.11c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3 6.44,3 2.33,5.36 0.56,6.57c-0.51,0.35 -0.61,1.06 -0.23,1.54L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L23.66,8.11z"/>
 </vector>
diff --git a/res/drawable/ic_wifi_tethering.xml b/res/drawable/ic_wifi_tethering.xml
index 359da5f..676c307 100644
--- a/res/drawable/ic_wifi_tethering.xml
+++ b/res/drawable/ic_wifi_tethering.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?android:attr/colorControlNormal">
     <path
-        android:pathData="M12,11c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,13c0,-3.31 -2.69,-6 -6,-6s-6,2.69 -6,6c0,2.22 1.21,4.15 3,5.19l1,-1.74c-1.19,-0.7 -2,-1.97 -2,-3.45 0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,1.48 -0.81,2.75 -2,3.45l1,1.74c1.79,-1.04 3,-2.97 3,-5.19zM12,3C6.48,3 2,7.48 2,13c0,3.7 2.01,6.92 4.99,8.65l1,-1.73C5.61,18.53 4,15.96 4,13c0,-4.42 3.58,-8 8,-8s8,3.58 8,8c0,2.96 -1.61,5.53 -4,6.92l1,1.73c2.99,-1.73 5,-4.95 5,-8.65 0,-5.52 -4.48,-10 -10,-10z"
+        android:pathData="M12,11c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,13a6,6 0,0 0,-6.75 -5.95c-2.62,0.32 -4.78,2.41 -5.18,5.02 -0.32,2.14 0.49,4.11 1.92,5.39 0.48,0.43 1.24,0.33 1.56,-0.23 0.24,-0.42 0.14,-0.94 -0.22,-1.26a3.99,3.99 0,0 1,-1.22 -3.94,3.954 3.954,0 0,1 2.9,-2.91A4.007,4.007 0,0 1,16 13c0,1.18 -0.51,2.23 -1.33,2.96 -0.36,0.33 -0.47,0.85 -0.23,1.27 0.31,0.54 1.04,0.69 1.5,0.28A5.97,5.97 0,0 0,18 13zM10.83,3.07c-4.62,0.52 -8.35,4.33 -8.78,8.96a9.966,9.966 0,0 0,4.02 9.01c0.48,0.35 1.16,0.2 1.46,-0.31 0.25,-0.43 0.14,-0.99 -0.26,-1.29 -2.28,-1.69 -3.65,-4.55 -3.16,-7.7 0.54,-3.5 3.46,-6.29 6.98,-6.68C15.91,4.51 20,8.28 20,13c0,2.65 -1.29,4.98 -3.27,6.44 -0.4,0.3 -0.51,0.85 -0.26,1.29 0.3,0.52 0.98,0.66 1.46,0.31A9.96,9.96 0,0 0,22 13c0,-5.91 -5.13,-10.62 -11.17,-9.93z"
         android:fillColor="#FFFFFFFF"/>
 </vector>
diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml
index 4423e10..ec2aaea 100644
--- a/res/layout/master_clear.xml
+++ b/res/layout/master_clear.xml
@@ -45,6 +45,13 @@
                 android:visibility="gone"
                 android:textSize="18sp"
                 android:text="@string/master_clear_desc_also_erases_external" />
+            <TextView android:id="@+id/also_erases_esim"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:includeFontPadding="false"
+                android:visibility="gone"
+                android:textSize="18sp"
+                android:text="@string/master_clear_desc_also_erases_esim" />
             <TextView android:id="@+id/accounts_label"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
@@ -65,6 +72,12 @@
                 android:visibility="gone"
                 android:textSize="18sp"
                 android:text="@string/master_clear_other_users_present" />
+            <TextView android:id="@+id/no_cancel_mobile_plan"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:textSize="18sp"
+                android:text="@string/master_clear_desc_no_cancel_mobile_plan" />
             <TextView android:id="@+id/erase_external_option_text"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
@@ -102,38 +115,6 @@
                         android:text="@string/erase_external_storage_description" />
                 </LinearLayout>
             </LinearLayout>
-            <LinearLayout android:id="@+id/erase_esim_container"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    android:focusable="true"
-                    android:clickable="true">
-                <CheckBox android:id="@+id/erase_esim"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="center_vertical"
-                        android:paddingEnd="8dp"
-                        android:focusable="false"
-                        android:clickable="false"
-                        android:duplicateParentState="true" />
-                <LinearLayout android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="center_vertical"
-                        android:orientation="vertical">
-                    <TextView
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:paddingTop="12dp"
-                        android:textSize="18sp"
-                        android:text="@string/erase_esim_storage" />
-                    <TextView
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:paddingTop="4sp"
-                        android:textSize="14sp"
-                        android:text="@string/erase_esim_storage_description" />
-                </LinearLayout>
-            </LinearLayout>
         </LinearLayout>
     </ScrollView>
     <Button
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6703309..426716c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3150,13 +3150,17 @@
     <!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
     <string name="master_clear_desc" product="tablet">"This will erase all data from your tablet\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Factory data reset [CHAR LIMIT=NONE] -->
-    <string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps"</li></string>
+    <string name="master_clear_desc" product="default">"This will erase all data from your phone\u2019s <b>internal storage</b>, including:\n\n<li>Your Google account</li>\n<li>System and app data and settings</li>\n<li>Downloaded apps</li>"</string>
     <!-- SD card & phone storage settings screen, instructions and list of current accounts.  The list of accounts follows this text[CHAR LIMIT=NONE] -->
     <string name="master_clear_accounts" product="default">"\n\nYou are currently signed into the following accounts:\n"</string>
     <!-- SD card & phone storage settings screen, notification if other users are present on the device [CHAR LIMIT=NONE] -->
     <string name="master_clear_other_users_present" product="default">"\n\nThere are other users present on this device.\n"</string>
     <!-- SD card & phone storage settings screen, list of items in user data storage (USB storage or SD card) that will be erased during this operation [CHAR LIMIT=NONE] -->
     <string name="master_clear_desc_also_erases_external">"<li>Music</li>\n<li>Photos</li>\n<li>Other user data</li>"</string>
+    <!-- SD card & phone storage settings screen, list of items on an eSIM (embedded SIM) that will be erased during this operation [CHAR LIMIT=NONE] -->
+    <string name="master_clear_desc_also_erases_esim">"<li>Carriers on eSIM</li>"</string>
+    <!-- SD card & phone storage settings screen, notification if there are eSIM (embedded SIM) profiles present that the user's mobile service plan will not be canceled [CHAR LIMIT=NONE] -->
+    <string name="master_clear_desc_no_cancel_mobile_plan">"\n\nThis will not cancel your mobile service plan.</string>
     <!-- SD card & phone storage settings screen, instructions about whether to also erase the external storage (SD card) when erasing the internal storage [CHAR LIMIT=NONE] -->
     <string name="master_clear_desc_erase_external_storage" product="nosdcard">"\n\nTo clear music, pictures, and other user data, the <b>USB storage</b> needs to be erased."</string>
     <!-- SD card & phone storage settings screen, instructions about whether to also erase the external storage (SD card) when erasing the internal storage [CHAR LIMIT=NONE] -->
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index 95628ef..e9c9737 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -83,8 +83,7 @@
         <SwitchPreference
             android:key="vibrate_input_devices"
             android:title="@string/vibrate_input_devices"
-            android:summaryOn="@string/vibrate_input_devices_summary"
-            android:summaryOff="@string/vibrate_input_devices_summary"/>
+            android:summary="@string/vibrate_input_devices_summary" />
 
     </PreferenceCategory>
 
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index f5705bb..b0aff02 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -90,7 +90,6 @@
 
     <!-- Other sounds -->
     <PreferenceCategory
-          android:key="other_sound_preferecence_category"
           android:title="@string/other_sound_category_preference_title"
           android:order="-50">
 
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 1bdd6f4..96ce17e 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -81,8 +81,6 @@
     private Button mInitiateButton;
     private View mExternalStorageContainer;
     @VisibleForTesting CheckBox mExternalStorage;
-    private View mEsimStorageContainer;
-    @VisibleForTesting CheckBox mEsimStorage;
     private ScrollView mScrollView;
 
     private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
@@ -126,7 +124,8 @@
     void showFinalConfirmation() {
         Bundle args = new Bundle();
         args.putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked());
-        args.putBoolean(ERASE_ESIMS_EXTRA, mEsimStorage.isChecked());
+        // TODO: Offer the user a choice to wipe eSIMs when it is technically feasible to do so.
+        args.putBoolean(ERASE_ESIMS_EXTRA, true);
         ((SettingsActivity) getActivity()).startPreferencePanel(
                 this, MasterClearConfirm.class.getName(),
                 args, R.string.master_clear_confirm_title, null, null, 0);
@@ -175,8 +174,6 @@
         mInitiateButton.setOnClickListener(mInitiateListener);
         mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container);
         mExternalStorage = (CheckBox) mContentView.findViewById(R.id.erase_external);
-        mEsimStorageContainer = mContentView.findViewById(R.id.erase_esim_container);
-        mEsimStorage = (CheckBox) mContentView.findViewById(R.id.erase_esim);
         mScrollView = (ScrollView) mContentView.findViewById(R.id.master_clear_scrollview);
 
         /*
@@ -211,15 +208,11 @@
         }
 
         if (showWipeEuicc()) {
-            mEsimStorageContainer.setOnClickListener(new View.OnClickListener() {
+            final View esimAlsoErased = mContentView.findViewById(R.id.also_erases_esim);
+            esimAlsoErased.setVisibility(View.VISIBLE);
 
-                @Override
-                public void onClick(View v) {
-                    mEsimStorage.toggle();
-                }
-            });
-        } else {
-            mEsimStorageContainer.setVisibility(View.GONE);
+            final View noCancelMobilePlan = mContentView.findViewById(R.id.no_cancel_mobile_plan);
+            noCancelMobilePlan.setVisibility(View.VISIBLE);
         }
 
         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
@@ -245,9 +238,9 @@
     }
 
     /**
-     * Whether to show the checkbox to wipe the eUICC.
+     * Whether to show strings indicating that the eUICC will be wiped.
      *
-     * <p>We show the checkbox on any device which supports eUICC as long as the eUICC was ever
+     * <p>We show the strings on any device which supports eUICC as long as the eUICC was ever
      * provisioned (that is, at least one profile was ever downloaded onto it).
      */
     @VisibleForTesting
diff --git a/src/com/android/settings/applications/AccessibilityServiceInfoWrapper.java b/src/com/android/settings/applications/AccessibilityServiceInfoWrapper.java
new file mode 100644
index 0000000..6ce0a4a
--- /dev/null
+++ b/src/com/android/settings/applications/AccessibilityServiceInfoWrapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.applications;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+
+/**
+ * This interface replicates a subset of the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo}. The interface
+ * exists so that we can use a thin wrapper around it in production code and a mock in tests.
+ * We cannot directly mock or shadow it, because some of the methods we rely on are newer than
+ * the API version supported by Robolectric.
+ */
+public interface AccessibilityServiceInfoWrapper {
+
+    /**
+     * Returns the real {@code AccessibilityServiceInfo} object.
+     */
+    AccessibilityServiceInfo getAccessibilityServiceInfo();
+
+    ComponentName getComponentName();
+}
diff --git a/src/com/android/settings/applications/AccessibilityServiceInfoWrapperImpl.java b/src/com/android/settings/applications/AccessibilityServiceInfoWrapperImpl.java
new file mode 100644
index 0000000..d0d99ea
--- /dev/null
+++ b/src/com/android/settings/applications/AccessibilityServiceInfoWrapperImpl.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.applications;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+
+public class AccessibilityServiceInfoWrapperImpl implements AccessibilityServiceInfoWrapper {
+
+    private final AccessibilityServiceInfo mServiceInfo;
+
+    public AccessibilityServiceInfoWrapperImpl(AccessibilityServiceInfo serviceInfo) {
+        mServiceInfo = serviceInfo;
+    }
+
+    @Override
+    public AccessibilityServiceInfo getAccessibilityServiceInfo() {
+        return mServiceInfo;
+    }
+
+    @Override
+    public ComponentName getComponentName() {
+        return mServiceInfo.getComponentName();
+    }
+}
diff --git a/src/com/android/settings/datausage/DataPlanUsageSummary.java b/src/com/android/settings/datausage/DataPlanUsageSummary.java
index 5132d55..0743749 100644
--- a/src/com/android/settings/datausage/DataPlanUsageSummary.java
+++ b/src/com/android/settings/datausage/DataPlanUsageSummary.java
@@ -54,13 +54,19 @@
 public class DataPlanUsageSummary extends DataUsageBase implements Indexable {
 
     public static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
-    public static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions";
-    private static final String KEY_DATA_PLAN_USAGE = "data_plan_usage";
+    public static final String KEY_DATA_PLAN_USAGE = "data_plan_usage";
 
-    private static final String KEY_STATUS_HEADER = "status_header";
-    private static final String KEY_LIMIT_SUMMARY = "plan_summary";
-    private static final String KEY_MOBILE_USAGE_TITLE = "data_usage_mobile_category";
-    private static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
+    public static final String KEY_STATUS_HEADER = "status_header";
+    public static final String KEY_LIMIT_SUMMARY = "plan_summary";
+
+    // Mobile data keys
+    public static final String KEY_MOBILE_USAGE_TITLE = "data_usage_mobile_category";
+    public static final String KEY_MOBILE_DATA_USAGE_TOGGLE = "data_usage_enable";
+
+    // Wifi keys
+    public static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
+    public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage";
+    public static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions";
 
     private DataUsageController mDataUsageController;
     private DataUsageInfoController mDataInfoController;
@@ -364,19 +370,17 @@
                         boolean enabled) {
                     List<SearchIndexableResource> resources = new ArrayList<>();
                     SearchIndexableResource resource = new SearchIndexableResource(context);
-                    resource.xmlResId = R.xml.data_plan_usage;
+                    resource.xmlResId = R.xml.data_usage;
                     resources.add(resource);
 
-                    if (DataUsageUtils.hasMobileData(context)) {
-                        resource = new SearchIndexableResource(context);
-                        resource.xmlResId = R.xml.data_plan_usage_cell_data_preference_screen;
-                        resources.add(resource);
-                    }
-                    if (DataUsageUtils.hasWifiRadio(context)) {
-                        resource = new SearchIndexableResource(context);
-                        resource.xmlResId = R.xml.data_usage_wifi;
-                        resources.add(resource);
-                    }
+                    resource = new SearchIndexableResource(context);
+                    resource.xmlResId = R.xml.data_plan_usage_cell_data_preference_screen;
+                    resources.add(resource);
+
+                    resource = new SearchIndexableResource(context);
+                    resource.xmlResId = R.xml.data_usage_wifi;
+                    resources.add(resource);
+
                     return resources;
                 }
 
@@ -384,12 +388,16 @@
                 public List<String> getNonIndexableKeys(Context context) {
                     List<String> keys = super.getNonIndexableKeys(context);
 
-                    if (DataUsageUtils.hasMobileData(context)) {
-                        keys.add(KEY_RESTRICT_BACKGROUND);
+                    if (!DataUsageUtils.hasMobileData(context)) {
+                        keys.add(KEY_MOBILE_USAGE_TITLE);
+                        keys.add(KEY_MOBILE_DATA_USAGE_TOGGLE);
                     }
-                    if (DataUsageUtils.hasWifiRadio(context)) {
+
+                    if (!DataUsageUtils.hasWifiRadio(context)) {
+                        keys.add(KEY_WIFI_DATA_USAGE);
                         keys.add(KEY_NETWORK_RESTRICTIONS);
                     }
+
                     keys.add(KEY_WIFI_USAGE_TITLE);
 
                     return keys;
diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java
index ec47a4d..e37cc4a 100644
--- a/src/com/android/settings/datausage/DataUsageSummary.java
+++ b/src/com/android/settings/datausage/DataUsageSummary.java
@@ -69,12 +69,21 @@
     static final boolean LOGD = false;
 
     public static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
-    public static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions";
 
     private static final String KEY_STATUS_HEADER = "status_header";
     private static final String KEY_LIMIT_SUMMARY = "limit_summary";
-    private static final String KEY_MOBILE_USAGE_TITLE = "mobile_category";
-    private static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
+
+    // Mobile data keys
+    public static final String KEY_MOBILE_USAGE_TITLE = "mobile_category";
+    public static final String KEY_MOBILE_DATA_USAGE_TOGGLE = "data_usage_enable";
+    public static final String KEY_MOBILE_DATA_USAGE = "cellular_data_usage";
+    public static final String KEY_MOBILE_BILLING_CYCLE = "billing_preference";
+
+    // Wifi keys
+    public static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
+    public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage";
+    public static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions";
+
 
     private DataUsageController mDataUsageController;
     private DataUsageInfoController mDataInfoController;
@@ -381,16 +390,14 @@
                 resource.xmlResId = R.xml.data_usage;
                 resources.add(resource);
 
-                if (DataUsageUtils.hasMobileData(context)) {
-                    resource = new SearchIndexableResource(context);
-                    resource.xmlResId = R.xml.data_usage_cellular;
-                    resources.add(resource);
-                }
-                if (DataUsageUtils.hasWifiRadio(context)) {
-                    resource = new SearchIndexableResource(context);
-                    resource.xmlResId = R.xml.data_usage_wifi;
-                    resources.add(resource);
-                }
+                resource = new SearchIndexableResource(context);
+                resource.xmlResId = R.xml.data_usage_cellular;
+                resources.add(resource);
+
+                resource = new SearchIndexableResource(context);
+                resource.xmlResId = R.xml.data_usage_wifi;
+                resources.add(resource);
+
                 return resources;
             }
 
@@ -398,12 +405,19 @@
             public List<String> getNonIndexableKeys(Context context) {
                 List<String> keys = super.getNonIndexableKeys(context);
 
-                if (DataUsageUtils.hasMobileData(context)) {
-                    keys.add(KEY_RESTRICT_BACKGROUND);
+                if (!DataUsageUtils.hasMobileData(context)) {
+                    keys.add(KEY_MOBILE_USAGE_TITLE);
+                    keys.add(KEY_MOBILE_DATA_USAGE_TOGGLE);
+                    keys.add(KEY_MOBILE_DATA_USAGE);
+                    keys.add(KEY_MOBILE_BILLING_CYCLE);
                 }
-                if (DataUsageUtils.hasWifiRadio(context)) {
+
+                if (!DataUsageUtils.hasWifiRadio(context)) {
+                    keys.add(KEY_WIFI_DATA_USAGE);
                     keys.add(KEY_NETWORK_RESTRICTIONS);
                 }
+
+                // This title is named Wifi, and will confuse users.
                 keys.add(KEY_WIFI_USAGE_TITLE);
 
                 return keys;
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index a5d1223..af2d257 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -39,7 +39,7 @@
      * Returns whether device has mobile data.
      * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method.
      */
-    static boolean hasMobileData(Context context) {
+    public static boolean hasMobileData(Context context) {
         ConnectivityManager connectivityManager = ConnectivityManager.from(context);
         return connectivityManager != null && connectivityManager
                 .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
index 53898e8..fffa243 100644
--- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
+++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
@@ -77,7 +77,7 @@
 
     @Override
     public boolean isAvailable() {
-        return mConfig.alwaysOnAvailable();
+        return mConfig.alwaysOnAvailableForUser(MY_USER);
     }
 
     @Override
diff --git a/src/com/android/settings/graph/UsageGraph.java b/src/com/android/settings/graph/UsageGraph.java
index 5a4a9cd..a39cb43 100644
--- a/src/com/android/settings/graph/UsageGraph.java
+++ b/src/com/android/settings/graph/UsageGraph.java
@@ -28,8 +28,8 @@
 import android.graphics.Path;
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.VisibleForTesting;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.SparseIntArray;
 import android.util.TypedValue;
 import android.view.View;
@@ -93,7 +93,7 @@
         float dots = resources.getDimensionPixelSize(R.dimen.usage_graph_dot_size);
         float interval = resources.getDimensionPixelSize(R.dimen.usage_graph_dot_interval);
         mDottedPaint.setStrokeWidth(dots * 3);
-        mDottedPaint.setPathEffect(new DashPathEffect(new float[]{dots, interval}, 0));
+        mDottedPaint.setPathEffect(new DashPathEffect(new float[] {dots, interval}, 0));
         mDottedPaint.setColor(context.getColor(R.color.usage_graph_dots));
 
         TypedValue v = new TypedValue();
@@ -136,8 +136,8 @@
         addPathAndUpdate(points, mProjectedPaths, mLocalProjectedPaths);
     }
 
-    private void addPathAndUpdate(SparseIntArray points, SparseIntArray paths,
-            SparseIntArray localPaths) {
+    private void addPathAndUpdate(
+            SparseIntArray points, SparseIntArray paths, SparseIntArray localPaths) {
         final long startTime = System.currentTimeMillis();
         for (int i = 0, size = points.size(); i < size; i++) {
             paths.put(points.keyAt(i), points.valueAt(i));
@@ -170,41 +170,44 @@
         calculateLocalPaths(mProjectedPaths, mLocalProjectedPaths);
     }
 
-    private void calculateLocalPaths(SparseIntArray paths, SparseIntArray localPaths) {
+    @VisibleForTesting
+    void calculateLocalPaths(SparseIntArray paths, SparseIntArray localPaths) {
         final long startTime = System.currentTimeMillis();
         if (getWidth() == 0) {
             return;
         }
         localPaths.clear();
-        int pendingXLoc = 0;
-        int pendingYLoc = PATH_DELIM;
+        // Store the local coordinates of the most recent point.
+        int lx = 0;
+        int ly = PATH_DELIM;
+        boolean skippedLastPoint = false;
         for (int i = 0; i < paths.size(); i++) {
             int x = paths.keyAt(i);
             int y = paths.valueAt(i);
             if (y == PATH_DELIM) {
-                if (i == paths.size() - 1 && pendingYLoc != PATH_DELIM) {
-                    // Connect to the end of the graph.
-                    localPaths.put(pendingXLoc, pendingYLoc);
+                if (i == paths.size() - 1 && skippedLastPoint) {
+                    // Add back skipped point to complete the path.
+                    localPaths.put(lx, ly);
                 }
-                // Clear out any pending points.
-                pendingYLoc = PATH_DELIM;
-                localPaths.put(pendingXLoc + 1, PATH_DELIM);
+                skippedLastPoint = false;
+                localPaths.put(lx + 1, PATH_DELIM);
             } else {
-                final int lx = getX(x);
-                final int ly = getY(y);
-                pendingXLoc = lx;
+                lx = getX(x);
+                ly = getY(y);
+                // Skip this point if it is not far enough from the last one added.
                 if (localPaths.size() > 0) {
                     int lastX = localPaths.keyAt(localPaths.size() - 1);
                     int lastY = localPaths.valueAt(localPaths.size() - 1);
                     if (lastY != PATH_DELIM && !hasDiff(lastX, lx) && !hasDiff(lastY, ly)) {
-                        pendingYLoc = ly;
+                        skippedLastPoint = true;
                         continue;
                     }
                 }
+                skippedLastPoint = false;
                 localPaths.put(lx, ly);
             }
         }
-        BatteryUtils.logRuntime(LOG_TAG,"calculateLocalPaths", startTime);
+        BatteryUtils.logRuntime(LOG_TAG, "calculateLocalPaths", startTime);
     }
 
     private boolean hasDiff(int x1, int x2) {
@@ -221,8 +224,8 @@
 
     private void updateGradient() {
         mFillPaint.setShader(
-                new LinearGradient(0, 0, 0, getHeight(), getColor(mAccentColor, .2f), 0,
-                        TileMode.CLAMP));
+                new LinearGradient(
+                        0, 0, 0, getHeight(), getColor(mAccentColor, .2f), 0, TileMode.CLAMP));
     }
 
     private int getColor(int color, float alphaScale) {
@@ -236,7 +239,9 @@
         if (mMiddleDividerLoc != 0) {
             drawDivider(0, canvas, mTopDividerTint);
         }
-        drawDivider((int) ((canvas.getHeight() - mDividerSize) * mMiddleDividerLoc), canvas,
+        drawDivider(
+                (int) ((canvas.getHeight() - mDividerSize) * mMiddleDividerLoc),
+                canvas,
                 mMiddleDividerTint);
         drawDivider(canvas.getHeight() - mDividerSize, canvas, -1);
 
diff --git a/src/com/android/settings/inputmethod/GameControllerPreferenceController.java b/src/com/android/settings/inputmethod/GameControllerPreferenceController.java
index f7bc143..6a0e853 100644
--- a/src/com/android/settings/inputmethod/GameControllerPreferenceController.java
+++ b/src/com/android/settings/inputmethod/GameControllerPreferenceController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.hardware.input.InputManager;
 import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
@@ -31,11 +32,14 @@
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
 
+import java.util.List;
+
 public class GameControllerPreferenceController extends AbstractPreferenceController
         implements PreferenceControllerMixin, InputManager.InputDeviceListener, LifecycleObserver,
         OnResume, OnPause {
 
-    public static final String PREF_KEY = "vibrate_input_devices";
+    @VisibleForTesting
+    static final String PREF_KEY = "vibrate_input_devices";
     private static final String CATEGORY_KEY = "game_controller_settings_category";
 
     private final InputManager mIm;
@@ -106,6 +110,14 @@
     }
 
     @Override
+    public void updateNonIndexableKeys(List<String> keys) {
+        if (!isAvailable()) {
+            keys.add(CATEGORY_KEY);
+            keys.add(PREF_KEY);
+        }
+    }
+
+    @Override
     public void onInputDeviceAdded(int deviceId) {
         updateGameControllers();
     }
diff --git a/src/com/android/settings/search/ResultPayload.java b/src/com/android/settings/search/ResultPayload.java
index b008616..048c172 100644
--- a/src/com/android/settings/search/ResultPayload.java
+++ b/src/com/android/settings/search/ResultPayload.java
@@ -66,7 +66,8 @@
      * Enumerates the possible values for the Availability of a setting.
      */
     @IntDef({Availability.AVAILABLE,
-            Availability.DISABLED_DEPENDENCY,
+            Availability.DISABLED_DEPENDENT_SETTING,
+            Availability.DISABLED_DEPENDENT_APP,
             Availability.DISABLED_UNSUPPORTED,
             Availability.RESOURCE_CONTENTION})
     @Retention(RetentionPolicy.SOURCE)
@@ -77,9 +78,10 @@
         int AVAILABLE = 0;
 
         /**
-         * The setting has a dependency which is currently disabled, blocking access.
+         * The setting has a dependency in settings app which is currently disabled, blocking
+         * access.
          */
-        int DISABLED_DEPENDENCY = 1;
+        int DISABLED_DEPENDENT_SETTING = 1;
 
         /**
          * The setting is not supported by the device.
@@ -91,6 +93,11 @@
          * be changed until it is released by said application.
          */
         int RESOURCE_CONTENTION = 3;
+
+        /**
+         * The setting is disabled because corresponding app is disabled
+         */
+        int DISABLED_DEPENDENT_APP = 4;
     }
 
     @IntDef({SettingsSource.UNKNOWN, SettingsSource.SYSTEM, SettingsSource.SECURE,
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index ee4acd1..33fdf2d 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -174,10 +174,9 @@
                 }
                 mSelectedAccessPoint = mDlgAccessPoint;
 
-                mDialog = new WifiDialog(getActivity(), this, mDlgAccessPoint,
-                        WifiConfigUiBase.MODE_VIEW, true /* hide the submit button */);
+                mDialog = WifiDialog.createModal(getActivity(), this, mDlgAccessPoint,
+                        WifiConfigUiBase.MODE_VIEW);
                 return mDialog;
-
         }
         return super.onCreateDialog(dialogId);
     }
diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java
index e6674b8..81f2a14 100644
--- a/src/com/android/settings/wifi/WifiDialog.java
+++ b/src/com/android/settings/wifi/WifiDialog.java
@@ -27,6 +27,7 @@
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.wifi.AccessPoint;
 
+// TODO(b/64069122) Have this extend a dialogfragment to handle the fullscreen launch case.
 class WifiDialog extends AlertDialog implements WifiConfigUiBase, DialogInterface.OnClickListener {
 
     public interface WifiDialogListener {
@@ -45,21 +46,31 @@
     private WifiConfigController mController;
     private boolean mHideSubmitButton;
 
-    public WifiDialog(Context context, WifiDialogListener listener, AccessPoint accessPoint,
-            int mode, boolean hideSubmitButton) {
-        this(context, listener, accessPoint, mode);
-        mHideSubmitButton = hideSubmitButton;
+
+    /** Creates a WifiDialog with fullscreen style. It displays in fullscreen mode. */
+    public static WifiDialog createFullscreen(Context context, WifiDialogListener listener,
+            AccessPoint accessPoint, int mode) {
+        return new WifiDialog(context, listener, accessPoint, mode,
+                R.style.Theme_Settings_NoActionBar, false /* hideSubmitButton */);
     }
 
-    public WifiDialog(Context context, WifiDialogListener listener, AccessPoint accessPoint,
-            int mode) {
-        // conditionally sets the theme to fullscreen dialog for "Add Network"
-        super(context,
-                mode == WifiConfigUiBase.MODE_CONNECT ? R.style.Theme_Settings_NoActionBar : 0);
+    /**
+     * Creates a WifiDialog with no additional style. It displays as a dialog above the current
+     * view.
+     */
+    public static WifiDialog createModal(Context context, WifiDialogListener listener,
+            AccessPoint accessPoint, int mode) {
+        return new WifiDialog(context, listener, accessPoint, mode, 0 /* style */,
+                mode == WifiConfigUiBase.MODE_VIEW /* hideSubmitButton*/);
+    }
+
+    /* package */ WifiDialog(Context context, WifiDialogListener listener, AccessPoint accessPoint,
+        int mode, int style, boolean hideSubmitButton) {
+        super(context, style);
         mMode = mode;
         mListener = listener;
         mAccessPoint = accessPoint;
-        mHideSubmitButton = false;
+        mHideSubmitButton = hideSubmitButton;
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java
index af723c3..4f9c7a6 100644
--- a/src/com/android/settings/wifi/WifiDialogActivity.java
+++ b/src/com/android/settings/wifi/WifiDialogActivity.java
@@ -55,7 +55,7 @@
             accessPoint = new AccessPoint(this, accessPointState);
         }
 
-        WifiDialog dialog = new WifiDialog(this, this, accessPoint, WifiConfigUiBase.MODE_CONNECT);
+        WifiDialog dialog = WifiDialog.createModal(this, this, accessPoint, WifiConfigUiBase.MODE_CONNECT);
         dialog.show();
         dialog.setOnDismissListener(this);
     }
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 166a8ac..7cd1ab3 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -626,20 +626,23 @@
     public Dialog onCreateDialog(int dialogId) {
         switch (dialogId) {
             case WIFI_DIALOG_ID:
-                AccessPoint ap = mDlgAccessPoint; // For manual launch
-                if (ap == null) { // For re-launch from saved state
-                    if (mAccessPointSavedState != null) {
-                        ap = new AccessPoint(getActivity(), mAccessPointSavedState);
-                        // For repeated orientation changes
-                        mDlgAccessPoint = ap;
+                if (mDlgAccessPoint == null && mAccessPointSavedState == null) {
+                    // add new network
+                    mDialog = WifiDialog
+                            .createFullscreen(getActivity(), this, mDlgAccessPoint, mDialogMode);
+                } else {
+                    // modify network
+                    if (mDlgAccessPoint == null) {
+                        // restore AP from save state
+                        mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState);
                         // Reset the saved access point data
                         mAccessPointSavedState = null;
                     }
+                    mDialog = WifiDialog
+                            .createModal(getActivity(), this, mDlgAccessPoint, mDialogMode);
                 }
-                // If it's null, fine, it's for Add Network
-                mSelectedAccessPoint = ap;
-                mDialog = new WifiDialog(getActivity(), this, ap, mDialogMode,
-                        /* no hide submit/connect */ false);
+
+                mSelectedAccessPoint = mDlgAccessPoint;
                 return mDialog;
             case WPS_PBC_DIALOG_ID:
                 return new WpsDialog(getActivity(), WpsInfo.PBC);
diff --git a/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java b/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 59ca483..3dcf6ab 100644
--- a/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -62,6 +62,10 @@
         return true;
     }
 
+    public boolean alwaysOnAvailableForUser(int user) {
+        return true;
+    }
+
     public boolean available() {
         return true;
     }
diff --git a/tests/robotests/src/com/android/settings/MasterClearTest.java b/tests/robotests/src/com/android/settings/MasterClearTest.java
index edad391..b501654 100644
--- a/tests/robotests/src/com/android/settings/MasterClearTest.java
+++ b/tests/robotests/src/com/android/settings/MasterClearTest.java
@@ -123,32 +123,6 @@
     }
 
     @Test
-    public void testShowFinalConfirmation_EraseEsimChecked() {
-        ActivityForTest testActivity = new ActivityForTest();
-        when(mMasterClear.getActivity()).thenReturn(testActivity);
-
-        mMasterClear.mEsimStorage = (CheckBox) mContentView.findViewById(R.id.erase_esim);
-        mMasterClear.mExternalStorage = (CheckBox) mContentView.findViewById(R.id.erase_external);
-        mMasterClear.mEsimStorage.setChecked(true);
-        mMasterClear.showFinalConfirmation();
-        assertThat(testActivity.getArgs().getBoolean(MasterClear.ERASE_ESIMS_EXTRA, false))
-                .isTrue();
-    }
-
-    @Test
-    public void testShowFinalConfirmation_EraseEsimUnchecked() {
-        ActivityForTest testActivity = new ActivityForTest();
-        when(mMasterClear.getActivity()).thenReturn(testActivity);
-
-        mMasterClear.mEsimStorage = (CheckBox) mContentView.findViewById(R.id.erase_esim);
-        mMasterClear.mExternalStorage = (CheckBox) mContentView.findViewById(R.id.erase_external);
-        mMasterClear.mEsimStorage.setChecked(false);
-        mMasterClear.showFinalConfirmation();
-        assertThat(testActivity.getArgs().getBoolean(MasterClear.ERASE_ESIMS_EXTRA, true))
-                .isFalse();
-    }
-
-    @Test
     public void testHasReachedBottom_NotScrollDown_returnFalse() {
         initScrollView(100, 0, 200);
 
diff --git a/tests/robotests/src/com/android/settings/datausage/DataPlanUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataPlanUsageSummaryTest.java
index d2af22b..30c7736 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataPlanUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataPlanUsageSummaryTest.java
@@ -35,6 +35,7 @@
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settings.testutils.shadow.ShadowConnectivityManager;
+import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
 import com.android.settingslib.NetworkPolicyEditor;
 import java.util.ArrayList;
 import java.util.List;
@@ -129,28 +130,50 @@
     }
 
     @Test
+    @Config(shadows = ShadowDataUsageUtils.class)
     public void testNonIndexableKeys_existInXmlLayout() {
-        Context context = RuntimeEnvironment.application;
-        List<String> niks = DataPlanUsageSummary.SEARCH_INDEX_DATA_PROVIDER
+        final Context context = RuntimeEnvironment.application;
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
+        final List<String> niks = DataPlanUsageSummary.SEARCH_INDEX_DATA_PROVIDER
                 .getNonIndexableKeys(context);
-        List<String> keys = new ArrayList<>();
+        final List<String> keys = new ArrayList<>();
 
         keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.data_usage_wifi));
         keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.data_usage));
+        keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context,
+                R.xml.data_plan_usage_cell_data_preference_screen));
 
         assertThat(keys).containsAllIn(niks);
     }
 
     @Test
-    @Config(shadows = ShadowConnectivityManager.class)
-    public void testNonIndexableKeys_hasMobileData_restrictedAccessesAdded() {
-        ShadowConnectivityManager.setIsNetworkSupported(true);
+    @Config(shadows = ShadowDataUsageUtils.class)
+    public void testNonIndexableKeys_hasMobileData_hasWifi_allNonIndexableKeysAdded() {
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = false;
+        ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = false;
         List<String> keys = DataPlanUsageSummary.SEARCH_INDEX_DATA_PROVIDER
                 .getNonIndexableKeys(mContext);
 
-        assertThat(keys).contains(DataPlanUsageSummary.KEY_RESTRICT_BACKGROUND);
+        // Mobile data keys
+        assertThat(keys).contains(DataPlanUsageSummary.KEY_MOBILE_USAGE_TITLE);
+        assertThat(keys).contains(DataPlanUsageSummary.KEY_MOBILE_DATA_USAGE_TOGGLE);
+
+        // Wifi keys
+        assertThat(keys).contains(DataPlanUsageSummary.KEY_WIFI_DATA_USAGE);
         assertThat(keys).contains(DataPlanUsageSummary.KEY_NETWORK_RESTRICTIONS);
-        ShadowConnectivityManager.setIsNetworkSupported(false);
+        assertThat(keys).contains(DataPlanUsageSummary.KEY_WIFI_USAGE_TITLE);
+    }
+
+    @Test
+    @Config(shadows = ShadowDataUsageUtils.class)
+    public void testNonIndexableKeys_noMobile_noWifi_limitedNonIndexableKeys() {
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
+        List<String> keys = DataPlanUsageSummary.SEARCH_INDEX_DATA_PROVIDER
+                .getNonIndexableKeys(mContext);
+
+        assertThat(keys).containsExactly(DataPlanUsageSummary.KEY_WIFI_USAGE_TITLE);
     }
 
     private void initTest() {
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
index 6ee802b..431796a 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
@@ -82,29 +82,4 @@
         verify(preference).setSummary(mContext.getResources().getQuantityString(
             R.plurals.network_restrictions_summary, 0, 0));
     }
-
-    @Test
-    public void testNonIndexableKeys_existInXmlLayout() {
-        final Context context = RuntimeEnvironment.application;
-        final List<String> niks = DataUsageSummary.SEARCH_INDEX_DATA_PROVIDER
-                .getNonIndexableKeys(context);
-        final List<String> keys = new ArrayList<>();
-
-        keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.data_usage_wifi));
-        keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.data_usage));
-
-        assertThat(keys).containsAllIn(niks);
-    }
-
-    @Test
-    @Config(shadows = ShadowConnectivityManager.class)
-    public void testNonIndexableKeys_hasMobileData_restrictedAccessesAdded() {
-        ShadowConnectivityManager.setIsNetworkSupported(true);
-        List<String> keys = DataUsageSummary.SEARCH_INDEX_DATA_PROVIDER
-                .getNonIndexableKeys(mContext);
-
-        assertThat(keys).contains(DataUsageSummary.KEY_RESTRICT_BACKGROUND);
-        assertThat(keys).contains(DataUsageSummary.KEY_NETWORK_RESTRICTIONS);
-        ShadowConnectivityManager.setIsNetworkSupported(false);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
index 3f3f4b5..3869807 100644
--- a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
@@ -105,7 +105,7 @@
 
     @Test
     public void isAvailable_available() throws Exception {
-        when(mConfig.alwaysOnAvailable())
+        when(mConfig.alwaysOnAvailableForUser(anyInt()))
                 .thenReturn(true);
 
         assertThat(mController.isAvailable()).isTrue();
@@ -113,7 +113,7 @@
 
     @Test
     public void isAvailable_unavailable() throws Exception {
-        when(mConfig.alwaysOnAvailable())
+        when(mConfig.alwaysOnAvailableForUser(anyInt()))
                 .thenReturn(false);
 
         assertThat(mController.isAvailable()).isFalse();
diff --git a/tests/robotests/src/com/android/settings/graph/UsageGraphTest.java b/tests/robotests/src/com/android/settings/graph/UsageGraphTest.java
new file mode 100644
index 0000000..fbd6fd4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/graph/UsageGraphTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2017 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.graph;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.SparseIntArray;
+
+import com.android.settings.TestConfig;
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UsageGraphTest {
+    private UsageGraph mGraph;
+
+    @Before
+    public void setUp() {
+        // Set up a graph view of width 1000, height 200, and corner radius 5.
+        Context context = spy(RuntimeEnvironment.application);
+        Resources resources = spy(context.getResources());
+        doReturn(resources).when(context).getResources();
+        doReturn(5).when(resources).getDimensionPixelSize(R.dimen.usage_graph_line_corner_radius);
+        doReturn(1).when(resources).getDimensionPixelSize(R.dimen.usage_graph_line_width);
+        doReturn(1).when(resources).getDimensionPixelSize(R.dimen.usage_graph_dot_size);
+        doReturn(1).when(resources).getDimensionPixelSize(R.dimen.usage_graph_dot_interval);
+        doReturn(1).when(resources).getDimensionPixelSize(R.dimen.usage_graph_divider_size);
+        mGraph = spy(new UsageGraph(context, null));
+        doReturn(1000).when(mGraph).getWidth();
+        doReturn(200).when(mGraph).getHeight();
+
+        // Set the conceptual size of the graph to 500ms x 100%.
+        mGraph.setMax(500, 100);
+    }
+
+    @Test
+    public void testCalculateLocalPaths_singlePath() {
+        SparseIntArray paths = new SparseIntArray();
+        paths.append(0, 100);
+        paths.append(500, 50);
+        paths.append(501, -1);
+
+        SparseIntArray localPaths = new SparseIntArray();
+        mGraph.calculateLocalPaths(paths, localPaths);
+
+        assertThat(localPaths.size()).isEqualTo(3);
+        assertThat(localPaths.keyAt(0)).isEqualTo(0);
+        assertThat(localPaths.valueAt(0)).isEqualTo(0);
+        assertThat(localPaths.keyAt(1)).isEqualTo(1000);
+        assertThat(localPaths.valueAt(1)).isEqualTo(100);
+        assertThat(localPaths.keyAt(2)).isEqualTo(1001);
+        assertThat(localPaths.valueAt(2)).isEqualTo(-1);
+    }
+
+    @Test
+    public void testCalculateLocalPaths_multiplePaths() {
+        SparseIntArray paths = new SparseIntArray();
+        paths.append(0, 100);
+        paths.append(200, 75);
+        paths.append(201, -1);
+
+        paths.append(300, 50);
+        paths.append(500, 25);
+        paths.append(501, -1);
+
+        SparseIntArray localPaths = new SparseIntArray();
+        mGraph.calculateLocalPaths(paths, localPaths);
+
+        assertThat(localPaths.size()).isEqualTo(6);
+
+        assertThat(localPaths.keyAt(0)).isEqualTo(0);
+        assertThat(localPaths.valueAt(0)).isEqualTo(0);
+        assertThat(localPaths.keyAt(1)).isEqualTo(400);
+        assertThat(localPaths.valueAt(1)).isEqualTo(50);
+        assertThat(localPaths.keyAt(2)).isEqualTo(401);
+        assertThat(localPaths.valueAt(2)).isEqualTo(-1);
+
+        assertThat(localPaths.keyAt(3)).isEqualTo(600);
+        assertThat(localPaths.valueAt(3)).isEqualTo(100);
+        assertThat(localPaths.keyAt(4)).isEqualTo(1000);
+        assertThat(localPaths.valueAt(4)).isEqualTo(150);
+        assertThat(localPaths.keyAt(5)).isEqualTo(1001);
+        assertThat(localPaths.valueAt(5)).isEqualTo(-1);
+    }
+
+    @Test
+    public void testCalculateLocalPaths_similarPointMiddle() {
+        SparseIntArray paths = new SparseIntArray();
+        paths.append(0, 100);
+        paths.append(1, 99); // This point should be omitted.
+        paths.append(500, 50);
+        paths.append(501, -1);
+
+        SparseIntArray localPaths = new SparseIntArray();
+        mGraph.calculateLocalPaths(paths, localPaths);
+
+        assertThat(localPaths.size()).isEqualTo(3);
+        assertThat(localPaths.keyAt(0)).isEqualTo(0);
+        assertThat(localPaths.valueAt(0)).isEqualTo(0);
+        assertThat(localPaths.keyAt(1)).isEqualTo(1000);
+        assertThat(localPaths.valueAt(1)).isEqualTo(100);
+        assertThat(localPaths.keyAt(2)).isEqualTo(1001);
+        assertThat(localPaths.valueAt(2)).isEqualTo(-1);
+    }
+
+    @Test
+    public void testCalculateLocalPaths_similarPointEnd() {
+        SparseIntArray paths = new SparseIntArray();
+        paths.append(0, 100);
+        paths.append(499, 51);
+        paths.append(500, 50); // This point should be kept: it's the last one.
+        paths.append(501, -1);
+
+        SparseIntArray localPaths = new SparseIntArray();
+        mGraph.calculateLocalPaths(paths, localPaths);
+
+        assertThat(localPaths.size()).isEqualTo(4);
+        assertThat(localPaths.keyAt(0)).isEqualTo(0);
+        assertThat(localPaths.valueAt(0)).isEqualTo(0);
+        assertThat(localPaths.keyAt(1)).isEqualTo(998);
+        assertThat(localPaths.valueAt(1)).isEqualTo(98);
+        assertThat(localPaths.keyAt(2)).isEqualTo(1000);
+        assertThat(localPaths.valueAt(2)).isEqualTo(100);
+        assertThat(localPaths.keyAt(3)).isEqualTo(1001);
+        assertThat(localPaths.valueAt(3)).isEqualTo(-1);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java
index 7d803f4..2716fc3 100644
--- a/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java
@@ -16,12 +16,17 @@
 
 package com.android.settings.inputmethod;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.hardware.input.InputManager;
 import android.view.InputDevice;
 
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -31,10 +36,9 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -105,4 +109,18 @@
 
         assertThat(mController.isAvailable()).isFalse();
     }
+
+    @Test
+    public void updateNonIndexableKeys_shouldIncludeCategoryAndPrefKeys() {
+        when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{});
+
+
+        final List<String> nonIndexables = new ArrayList<>();
+        mController.updateNonIndexableKeys(nonIndexables);
+
+        assertThat(mController.isAvailable()).isFalse();
+        assertThat(nonIndexables).containsExactlyElementsIn(Arrays.asList(
+                GameControllerPreferenceController.PREF_KEY,
+                mController.getPreferenceKey()));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java
new file mode 100644
index 0000000..7e21f12
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.testutils.shadow;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.view.accessibility.AccessibilityManager;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Implements(AccessibilityManager.class)
+public class ShadowAccessibilityManager {
+    private static final List<AccessibilityServiceInfo> mInstalledAccessibilityList =
+            new ArrayList<>();
+
+    public static void addAccessibilityService(String serviceName) {
+        AccessibilityServiceInfo serviceInfo = new AccessibilityServiceInfo();
+        serviceInfo.setComponentName(ComponentName.unflattenFromString(serviceName));
+        mInstalledAccessibilityList.add(serviceInfo);
+    }
+
+    @Implementation
+    public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
+        return mInstalledAccessibilityList;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityServiceInfoWrapperImpl.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityServiceInfoWrapperImpl.java
new file mode 100644
index 0000000..a6cb5d0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityServiceInfoWrapperImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.testutils.shadow;
+
+import android.content.ComponentName;
+
+import com.android.settings.applications.AccessibilityServiceInfoWrapperImpl;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+@Implements(AccessibilityServiceInfoWrapperImpl.class)
+public class ShadowAccessibilityServiceInfoWrapperImpl {
+    private static ComponentName sComponentName;
+
+    public static void setComponentName(String componentName) {
+        sComponentName = ComponentName.unflattenFromString(componentName);;
+    }
+
+    @Implementation
+    public ComponentName getComponentName() {
+        return sComponentName;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java
new file mode 100644
index 0000000..fecceb6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java
@@ -0,0 +1,24 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+
+import com.android.settings.datausage.DataUsageUtils;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(DataUsageUtils.class)
+public class ShadowDataUsageUtils {
+
+    public static boolean IS_MOBILE_DATA_SUPPORTED = true;
+    public static boolean IS_WIFI_SUPPORTED = true;
+
+    @Implementation
+    public static boolean hasMobileData(Context context) {
+        return IS_MOBILE_DATA_SUPPORTED;
+    }
+
+    @Implementation
+    public static boolean hasWifiRadio(Context context) {
+        return IS_WIFI_SUPPORTED;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogTest.java
new file mode 100644
index 0000000..00941ad
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogTest.java
@@ -0,0 +1,64 @@
+package com.android.settings.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+
+import com.android.settings.wifi.WifiDialog.WifiDialogListener;
+import com.android.settingslib.wifi.AccessPoint;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = ShadowEntityHeaderController.class)
+public class WifiDialogTest {
+    @Mock private AccessPoint mockAccessPoint;
+
+    private Context mContext = RuntimeEnvironment.application;
+
+    private WifiDialogListener mListener = new WifiDialogListener() {
+        @Override
+        public void onForget(WifiDialog dialog) {
+        }
+
+        @Override
+        public void onSubmit(WifiDialog dialog) {
+        }
+    };
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void createFullscreen_setsFullscreenTheme() {
+        WifiDialog fullscreen = WifiDialog.createFullscreen(mContext, mListener, mockAccessPoint,
+                WifiConfigUiBase.MODE_CONNECT);
+        assertThat(fullscreen.getContext().getThemeResId())
+                .isEqualTo(R.style.Theme_Settings_NoActionBar);
+    }
+
+    @Test
+    public void createModal_usesDefaultTheme() {
+        WifiDialog modal = WifiDialog
+                .createModal(mContext, mListener, mockAccessPoint, WifiConfigUiBase.MODE_CONNECT);
+
+        WifiDialog wifiDialog = new WifiDialog(mContext, mListener, mockAccessPoint,
+                WifiConfigUiBase.MODE_CONNECT, 0 /* style */, false /* hideSubmitButton */);
+        assertThat(modal.getContext().getThemeResId())
+                .isEqualTo(wifiDialog.getContext().getThemeResId());
+    }
+}