Merge "AOD setting availability depends on other user settings" into oc-dr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index da96c00..a5affc9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -772,25 +772,6 @@
                 android:value="true" />
         </activity>
 
-        <activity android:name="Settings$ZenModeAutomationSuggestionActivity"
-                android:label="@string/zen_mode_automation_settings_title"
-                android:icon="@drawable/ic_settings_notifications"
-                android:exported="true"
-                android:taskAffinity="">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.notification.ZenModeSettings" />
-            <meta-data android:name="com.android.settings.dismiss"
-                android:value="8,12,30" />
-            <meta-data android:name="com.android.settings.title"
-                android:resource="@string/zen_mode_automation_suggestion_title" />
-            <meta-data android:name="com.android.settings.summary"
-                android:resource="@string/zen_mode_automation_suggestion_summary" />
-        </activity>
-
         <activity android:name="Settings$WallpaperSettingsActivity"
                   android:label="@string/wallpaper_settings_fragment_title"
                   android:icon="@drawable/ic_wallpaper"
@@ -3160,10 +3141,6 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.GESTURE" />
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.dismiss"
                        android:value="4,8,30" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3182,10 +3159,6 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.GESTURE" />
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.dismiss"
                        android:value="4,8,30" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3204,10 +3177,6 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.GESTURE" />
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.dismiss"
                        android:value="9,13,30" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3226,10 +3195,6 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.GESTURE" />
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.dismiss"
                        android:value="9,13,30" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3248,10 +3213,6 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.GESTURE" />
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.dismiss"
                        android:value="9,13,30" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
diff --git a/res/layout/choose_lock_dialog_item.xml b/res/layout/choose_lock_dialog_item.xml
index 8e78f99..46ad539 100644
--- a/res/layout/choose_lock_dialog_item.xml
+++ b/res/layout/choose_lock_dialog_item.xml
@@ -25,5 +25,6 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:textAlignment="viewStart"
     android:textAppearance="@android:style/TextAppearance.Material.Subhead"
     android:textColor="?android:attr/textColorAlertDialogListItem" />
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 f629611..aa87101 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3131,13 +3131,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/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/Settings.java b/src/com/android/settings/Settings.java
index fc68f6d..ed5180b 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -141,7 +141,6 @@
     public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }
 
     public static class WifiCallingSuggestionActivity extends SettingsActivity { /* empty */ }
-    public static class ZenModeAutomationSuggestionActivity extends SettingsActivity { /* empty */ }
     public static class FingerprintEnrollSuggestionActivity extends FingerprintEnrollIntroduction {
         /* empty */
     }
diff --git a/src/com/android/settings/applications/AccessibilityManagerWrapperImpl.java b/src/com/android/settings/applications/AccessibilityManagerWrapperImpl.java
new file mode 100644
index 0000000..4ebaea7
--- /dev/null
+++ b/src/com/android/settings/applications/AccessibilityManagerWrapperImpl.java
@@ -0,0 +1,38 @@
+/*
+ * 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.view.accessibility.AccessibilityManager;
+
+/**
+ * This class replicates a subset of the {@link android.view.accessibility.AccessibilityManager}.
+ * The interface exists so that we can use a thin wrapper around the AccessibilityManager in
+ * production code and a mock in tests.
+ */
+public class AccessibilityManagerWrapperImpl {
+
+    /**
+     * Determines if the accessibility button within the system navigation area is supported.
+     *
+     * @return {@code true} if the accessibility button is supported on this device,
+     * {@code false} otherwise
+     * @hide
+     */
+    public static boolean isAccessibilityButtonSupported() {
+        return AccessibilityManager.isAccessibilityButtonSupported();
+    }
+}
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/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index a1b69d7..39e3255 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -1050,6 +1050,7 @@
         } else if (preference == mBatteryPreference) {
             if (isBatteryStatsAvailable()) {
                 BatteryEntry entry = new BatteryEntry(getContext(), null, mUserManager, mSipper);
+                entry.defaultPackageName = mPackageName;
                 AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(),
                         this, mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry,
                         mBatteryPercent, null /* mAnomalies */);
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java b/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
index 6ff0413..4bed89b 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
@@ -16,30 +16,24 @@
 
 package com.android.settings.dashboard.suggestions;
 
-import android.app.AutomaticZenRule;
 import android.app.KeyguardManager;
-import android.app.NotificationManager;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.hardware.fingerprint.FingerprintManager;
-import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
 
 import com.android.ims.ImsManager;
 import com.android.settings.Settings.FingerprintEnrollSuggestionActivity;
 import com.android.settings.Settings.ScreenLockSuggestionActivity;
 import com.android.settings.Settings.WifiCallingSuggestionActivity;
-import com.android.settings.Settings.ZenModeAutomationSuggestionActivity;
 import com.android.settings.Utils;
 import com.android.settings.fingerprint.FingerprintSuggestionActivity;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.wallpaper.WallpaperSuggestionActivity;
 import com.android.settingslib.drawer.Tile;
 
-import java.util.Collection;
-
 /**
  * The Home of all stupidly dynamic Settings Suggestions checks.
  */
@@ -58,9 +52,7 @@
     public boolean isSuggestionComplete(Tile suggestion) {
         ComponentName component = suggestion.intent.getComponent();
         String className = component.getClassName();
-        if (className.equals(ZenModeAutomationSuggestionActivity.class.getName())) {
-            return hasEnabledZenAutoRules();
-        } else if (className.equals(WallpaperSuggestionActivity.class.getName())) {
+        if (className.equals(WallpaperSuggestionActivity.class.getName())) {
             return hasWallpaperSet();
         } else if (className.equals(WifiCallingSuggestionActivity.class.getName())) {
             return isWifiCallingUnavailableOrEnabled();
@@ -103,17 +95,6 @@
                 && ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext);
     }
 
-    private boolean hasEnabledZenAutoRules() {
-        Collection<AutomaticZenRule> zenRules =
-                NotificationManager.from(mContext).getAutomaticZenRules().values();
-        for (AutomaticZenRule rule : zenRules) {
-            if (rule.isEnabled()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     @VisibleForTesting
     boolean hasWallpaperSet() {
         return mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM) > 0;
diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java
index 5a84d13..417d74b 100644
--- a/src/com/android/settings/datausage/DataUsageSummary.java
+++ b/src/com/android/settings/datausage/DataUsageSummary.java
@@ -72,11 +72,21 @@
     public static final String TEST_RADIOS_PROP = "test.radios";
 
     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_WIFI_USAGE_TITLE = "wifi_category";
+
+    // Mobile data keys
+    public static final String KEY_MOBILE_CATEGORY = "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;
@@ -471,16 +481,14 @@
                 resource.xmlResId = R.xml.data_usage;
                 resources.add(resource);
 
-                if (hasMobileData(context)) {
-                    resource = new SearchIndexableResource(context);
-                    resource.xmlResId = R.xml.data_usage_cellular;
-                    resources.add(resource);
-                }
-                if (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;
             }
 
@@ -488,12 +496,19 @@
             public List<String> getNonIndexableKeys(Context context) {
                 List<String> keys = super.getNonIndexableKeys(context);
 
-                if (hasMobileData(context)) {
-                    keys.add(KEY_RESTRICT_BACKGROUND);
+                if (!hasMobileData(context)) {
+                    keys.add(KEY_MOBILE_CATEGORY);
+                    keys.add(KEY_MOBILE_DATA_USAGE_TOGGLE);
+                    keys.add(KEY_MOBILE_DATA_USAGE);
+                    keys.add(KEY_MOBILE_BILLING_CYCLE);
                 }
-                if (hasWifiRadio(context)) {
+
+                if (!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/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 0b1d4a8..9a37879 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -137,7 +137,9 @@
             args.putString(EXTRA_PACKAGE_NAME, null);
         } else {
             // populate data for normal app
-            args.putString(EXTRA_PACKAGE_NAME, entry.defaultPackageName);
+            args.putString(EXTRA_PACKAGE_NAME, entry.defaultPackageName != null
+                    ? entry.defaultPackageName
+                    : sipper.mPackages[0]);
         }
 
         args.putInt(EXTRA_UID, sipper.getUid());
@@ -205,7 +207,7 @@
         mAnomalies = getArguments().getParcelableArrayList(EXTRA_ANOMALY_LIST);
         if (mAnomalies == null) {
             getLoaderManager().initLoader(ANOMALY_LOADER, Bundle.EMPTY, this);
-        } else if (mAnomalies != null){
+        } else if (mAnomalies != null) {
             mAnomalySummaryPreferenceController.updateAnomalySummaryPreference(mAnomalies);
         }
     }
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/search/ResultPayload.java b/src/com/android/settings/search/ResultPayload.java
index b008616..0d8c0ec 100644
--- a/src/com/android/settings/search/ResultPayload.java
+++ b/src/com/android/settings/search/ResultPayload.java
@@ -66,9 +66,11 @@
      * 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})
+            Availability.RESOURCE_CONTENTION,
+            Availability.INTENT_ONLY})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Availability {
         /**
@@ -77,9 +79,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 +94,16 @@
          * 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;
+
+        /**
+         * This setting is supported on the device but cannot be changed inline.
+         */
+        int INTENT_ONLY = 5;
     }
 
     @IntDef({SettingsSource.UNKNOWN, SettingsSource.SYSTEM, SettingsSource.SECURE,
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/dashboard/suggestions/SuggestionsChecksTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
index e775136..028df05 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
@@ -31,8 +31,8 @@
 import android.hardware.fingerprint.FingerprintManager;
 
 import com.android.settings.Settings;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.drawer.Tile;
 
 import org.junit.Before;
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
index 77e0fe9..e4ad5b5 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
@@ -27,6 +27,7 @@
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settings.testutils.shadow.ShadowConnectivityManager;
+import com.android.settings.testutils.shadow.ShadowDataUsageSummary;
 import com.android.settingslib.NetworkPolicyEditor;
 
 import org.junit.Before;
@@ -149,27 +150,50 @@
     }
 
     @Test
+    @Config(shadows = ShadowDataUsageSummary.class)
     public void testNonIndexableKeys_existInXmlLayout() {
         final Context context = RuntimeEnvironment.application;
+        ShadowDataUsageSummary.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageSummary.IS_MOBILE_DATA_SUPPORTED = true;
         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));
+        keys.addAll(XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.data_usage_cellular));
 
         assertThat(keys).containsAllIn(niks);
     }
 
     @Test
-    @Config(shadows = ShadowConnectivityManager.class)
-    public void testNonIndexableKeys_hasMobileData_restrictedAccessesAdded() {
-        ShadowConnectivityManager.setIsNetworkSupported(true);
+    @Config(shadows = ShadowDataUsageSummary.class)
+    public void testNonIndexableKeys_hasMobileData_hasWifi_allNonIndexableKeysAdded() {
+        ShadowDataUsageSummary.IS_WIFI_SUPPORTED = false;
+        ShadowDataUsageSummary.IS_MOBILE_DATA_SUPPORTED = false;
         List<String> keys = DataUsageSummary.SEARCH_INDEX_DATA_PROVIDER
                 .getNonIndexableKeys(mContext);
 
-        assertThat(keys).contains(DataUsageSummary.KEY_RESTRICT_BACKGROUND);
+        // Mobile data keys
+        assertThat(keys).contains(DataUsageSummary.KEY_MOBILE_CATEGORY);
+        assertThat(keys).contains(DataUsageSummary.KEY_MOBILE_DATA_USAGE_TOGGLE);
+        assertThat(keys).contains(DataUsageSummary.KEY_MOBILE_DATA_USAGE);
+        assertThat(keys).contains(DataUsageSummary.KEY_MOBILE_BILLING_CYCLE);
+
+        // Wifi keys
+        assertThat(keys).contains(DataUsageSummary.KEY_WIFI_DATA_USAGE);
         assertThat(keys).contains(DataUsageSummary.KEY_NETWORK_RESTRICTIONS);
-        ShadowConnectivityManager.setIsNetworkSupported(false);
+        assertThat(keys).contains(DataUsageSummary.KEY_WIFI_USAGE_TITLE);
+    }
+
+    @Test
+    @Config(shadows = ShadowDataUsageSummary.class)
+    public void testNonIndexableKeys_noMobile_noWifi_limitedNonIndexableKeys() {
+        ShadowDataUsageSummary.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageSummary.IS_MOBILE_DATA_SUPPORTED = true;
+        List<String> keys = DataUsageSummary.SEARCH_INDEX_DATA_PROVIDER
+                .getNonIndexableKeys(mContext);
+
+        assertThat(keys).containsExactly(DataUsageSummary.KEY_WIFI_USAGE_TITLE);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 7f2aeb6..61815f1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -355,6 +355,18 @@
     }
 
     @Test
+    public void testStartBatteryDetailPage_defaultPackageNull_choseFromBatterySipper() {
+        mBatteryEntry.defaultPackageName = null;
+        mBatteryEntry.sipper.mPackages = PACKAGE_NAME;
+
+        AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0,
+                mBatteryEntry, USAGE_PERCENT, null);
+
+        assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo(
+                PACKAGE_NAME[0]);
+    }
+
+    @Test
     public void testInitPreference_hasCorrectSummary() {
         Bundle bundle = new Bundle(4);
         bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, BACKGROUND_TIME_MS);
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/suggestions/SettingsSuggestionsTest.java b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
index 4a4c9c4..77ed4b0 100644
--- a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
+++ b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
@@ -16,13 +16,16 @@
 
 package com.android.settings.suggestions;
 
+import static com.android.settings.TestConfig.MANIFEST_PATH;
+import static com.google.common.truth.Truth.assertThat;
+
 import android.annotation.StringRes;
 import android.content.Context;
 
 import com.android.settings.R;
+import com.android.settings.TestConfig;
 import com.android.settings.fingerprint.FingerprintSuggestionActivity;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.TestConfig;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,9 +40,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static com.android.settings.TestConfig.MANIFEST_PATH;
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SettingsSuggestionsTest {
@@ -51,14 +51,6 @@
             "com.android.settings.suggested.category.SETTINGS_ONLY";
 
     @Test
-    public void zenModeAutomationSuggestion_isValid() {
-        assertSuggestionEquals("Settings$ZenModeAutomationSuggestionActivity",
-                CATEGORY_FIRST_IMPRESSION,
-                R.string.zen_mode_automation_suggestion_title,
-                R.string.zen_mode_automation_suggestion_summary);
-    }
-
-    @Test
     public void wallpaperSuggestion_isValid() {
         assertSuggestionEquals("com.android.settings.wallpaper.WallpaperSuggestionActivity",
                 CATEGORY_FIRST_IMPRESSION,
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/ShadowAccessibilityManagerWrapperImpl.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManagerWrapperImpl.java
new file mode 100644
index 0000000..95d5de5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManagerWrapperImpl.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.settings.applications.AccessibilityManagerWrapperImpl;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+/**
+ * This class provides shadow for API that is not supported in current roboletric
+ */
+@Implements(AccessibilityManagerWrapperImpl.class)
+public class ShadowAccessibilityManagerWrapperImpl {
+
+    @Implementation
+    public static boolean isAccessibilityButtonSupported() {
+        return true;
+    }
+}
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/ShadowDataUsageSummary.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageSummary.java
new file mode 100644
index 0000000..c5fc601
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageSummary.java
@@ -0,0 +1,24 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+
+import com.android.settings.datausage.DataUsageSummary;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(DataUsageSummary.class)
+public class ShadowDataUsageSummary {
+
+    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/testutils/shadow/ShadowSecureSettings.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java
index 64e188e..f815592 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSecureSettings.java
@@ -43,6 +43,13 @@
     }
 
     @Implementation
+    public static boolean putStringForUser(ContentResolver resolver, String name, String value,
+            int userHandle) {
+        mValueMap.put(name, value);
+        return true;
+    }
+
+    @Implementation
     public static String getString(ContentResolver resolver, String name) {
         return (String) mValueMap.get(name);
     }