Merge "Create 'See All Networks' Preference to hide additional networks."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e9f39a5..0501077 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2264,10 +2264,6 @@
             android:icon="@drawable/ic_settings_accounts"
             android:taskAffinity=""
             android:parentActivityName="Settings">
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.SYNC_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -2300,6 +2296,18 @@
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
         </activity>
+        <activity android:name="Settings$ManagedProfileSettingsActivity"
+            android:label="@string/managed_profile_settings_title"
+            android:taskAffinity=""
+            android:parentActivityName="Settings"
+            android:permission="android.permission.MANAGE_USERS">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.MANAGED_PROFILE_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.accounts.ManagedProfileSettings" />
+        </activity>
 
         <activity android:name="com.android.settings.accounts.AddAccountSettings"
             android:theme="@android:style/Theme.Translucent.NoTitleBar"
@@ -3135,6 +3143,10 @@
             <intent-filter android:priority="3">
                 <action android:name="com.android.settings.action.SETTINGS"/>
             </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.SYNC_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                        android:value="com.android.settings.accounts.UserAndAccountDashboardFragment"/>
             <meta-data android:name="com.android.settings.category"
diff --git a/res/layout/battery_header.xml b/res/layout/battery_header.xml
new file mode 100644
index 0000000..a2484c2
--- /dev/null
+++ b/res/layout/battery_header.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/app_snippet"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center"
+    android:orientation="horizontal"
+    android:paddingTop="24dp"
+    android:paddingBottom="24dp"
+    style="@style/EntityHeader">
+
+    <com.android.settings.fuelgauge.BatteryMeterView
+        android:id="@+id/battery_header_icon"
+        android:layout_width="@dimen/battery_meter_width"
+        android:layout_height="@dimen/battery_meter_height"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/time"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="12dp"
+            android:gravity="center"
+            android:textAppearance="@android:style/TextAppearance.Material.Medium"/>
+
+        <TextView
+            android:id="@+id/summary1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="12dp"
+            android:gravity="center"
+            android:textAppearance="@android:style/TextAppearance.Material.Small"
+            android:text="@string/estimated_time_left"/>
+
+        <TextView
+            android:id="@+id/summary2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="12dp"
+            android:gravity="center"
+            android:textAppearance="@android:style/TextAppearance.Material.Small"
+            android:text="@string/estimated_time_description"/>
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6b83516..2bc83c1 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -311,4 +311,8 @@
 
     <!-- Padding between the donut and the storage summary. -->
     <dimen name="storage_summary_padding_end">16dp</dimen>
+
+    <!-- Battery meter view size -->
+    <dimen name="battery_meter_width">66dp</dimen>
+    <dimen name="battery_meter_height">100dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 280c119..852e81d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2941,8 +2941,14 @@
     <string name="tether_settings_title_bluetooth">Bluetooth tethering</string>
     <!-- Tethering controls, item title to go into the tethering settings when USB and Bluetooth tethering are available [CHAR LIMIT=25]-->
     <string name="tether_settings_title_usb_bluetooth">Tethering</string>
-    <!-- Tethering controls, item title to go into the tethering settings when USB, Bluetooth and Wifi tethering are available [CHAR LIMIT=25]-->
+    <!-- Tethering controls, item title to go into the tethering settings when USB, Bluetooth and Wifi tethering are available [CHAR LIMIT=50]-->
     <string name="tether_settings_title_all">Hotspot &amp; Tethering</string>
+    <!-- Tethering setting summary when both Wi-Fi hotspot and tether are turned on [CHAR LIMIT=NONE]-->
+    <string name="tether_settings_summary_hotspot_on_tether_on">Hotspot on, tethering</string>
+    <!-- Tethering setting summary when Wi-Fi hotspot is on and tether is off [CHAR LIMIT=NONE]-->
+    <string name="tether_settings_summary_hotspot_on_tether_off">Hotspot on</string>
+    <!-- Tethering setting summary when Wi-Fi hotspot is off and tether is on [CHAR LIMIT=NONE]-->
+    <string name="tether_settings_summary_hotspot_off_tether_on">Tethering</string>
     <!-- Tethering controls, footer note displayed when tethering is disabled because Data Saver mode is on [CHAR LIMIT=none]-->
     <string name="tether_settings_disabled_on_data_saver">"Can\u2019t tether or use portable hotspots while Data Saver is on"</string>
 
@@ -4484,6 +4490,12 @@
     <!-- Description for battery usage detail information since last full charge. [CHAR LIMIT=120] -->
     <string name="battery_detail_since_full_charge">Usage breakdown since last full charge</string>
 
+    <!-- Description for battery time left, i.e. 50min Estimated time left. [CHAR LIMIT=80]-->
+    <string name="estimated_time_left">Estimated time left</string>
+
+    <!-- Description for estimated time. [CHAR LIMIT=80]-->
+    <string name="estimated_time_description">Estimation may change based on usage</string>
+
     <!-- Menu label for viewing battery usage since unplugged -->
     <string name="menu_stats_unplugged"><xliff:g id="unplugged">%1$s</xliff:g> since unplugged</string>
     <!-- Menu label for viewing battery usage since unplugged -->
@@ -5981,7 +5993,9 @@
     handle actions such as open web page, making phone calls, default SMS apps [CHAR  LIMIT=40]-->
     <string name="app_default_dashboard_title">Default apps</string>
     <!-- Summary text for system preference tile, showing important setting items under system setting [CHAR LIMIT=NONE]-->
-    <string name="system_dashboard_summary">Languages, backup, updates, about phone</string>
+    <string name="system_dashboard_summary" product="default">Languages, backup, updates, about phone</string>
+    <!-- Summary text for system preference tile, showing important setting items under system setting [CHAR LIMIT=NONE]-->
+    <string name="system_dashboard_summary" product="tablet">Languages, backup, updates, about device</string>
 
     <!-- Search strings -->
     <!-- Text to describe the search results fragment title [CHAR LIMIT=16] -->
diff --git a/res/xml/account_type_settings.xml b/res/xml/account_type_settings.xml
index 91e90fe..ab997a5 100644
--- a/res/xml/account_type_settings.xml
+++ b/res/xml/account_type_settings.xml
@@ -23,21 +23,22 @@
       android:key="account_header"
       android:layout="@layout/account_header"
       android:selectable="false"
-      android:order="0"/>
+      android:order="-10000"/>
 
     <Preference
         android:key="account_sync"
         android:title="@string/account_sync_title"
         android:icon="@drawable/ic_sync"
-        android:order="1"/>
+        android:order="-9999"/>
 
     <PreferenceCategory
       android:key="dashboard_tile_placeholder"
-      android:order="10"/>
+      android:order="-9998"/>
 
     <com.android.settings.applications.LayoutPreference
       android:key="remove_account"
       android:layout="@layout/remove_account_button"
-      android:order="100" />
+      android:order="1000"
+      android:selectable="false"/>
 
 </PreferenceScreen>
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 3faf9c8..0254b13 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -30,6 +30,7 @@
 
     <com.android.settings.applications.LayoutPreference
         android:key="change_storage_button"
+        android:selectable="false"
         android:layout="@layout/single_button_panel" />
 
     <PreferenceCategory
@@ -69,6 +70,7 @@
 
         <com.android.settings.applications.LayoutPreference
             android:key="clear_data_button"
+            android:selectable="false"
             android:layout="@layout/single_button_panel" />
     </PreferenceCategory>
 
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index b4ac7e2..b6808c0 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -20,8 +20,10 @@
     android:title="@string/power_usage_summary_title"
     settings:keywords="@string/keywords_battery">
 
-    <com.android.settings.fuelgauge.BatteryHistoryPreference
-        android:key="battery_history"/>
+    <com.android.settings.applications.LayoutPreference
+        android:key="battery_header"
+        android:selectable="true"
+        android:layout="@layout/battery_header"/>
 
     <PreferenceCategory
         android:key="power_management"
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index f6d6310..e08ca96 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -43,4 +43,10 @@
         android:key="pref_system"
         android:title="@string/storage_detail_system">
     </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
+    <Preference
+        android:key="manage_storage"
+        android:title="@string/storage_menu_manage"
+        android:icon="@drawable/ic_settings_storage"
+        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
+    </Preference>
 </PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index a5f9830..40972ac 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -366,13 +366,22 @@
             }
         }
 
+        /**
+         * Dialog setup.
+         * <p>
+         * To make it less likely that the dialog is dismissed accidentally, for example if the
+         * device is malfunctioning or if the device is in a pocket, we set
+         * {@code setCanceledOnTouchOutside(false)}.
+         */
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
-            return new AlertDialog.Builder(getActivity())
+            Dialog dialog = new AlertDialog.Builder(getActivity())
                     .setTitle(getArguments().getString(ARG_TITLE))
                     .setMessage(getArguments().getInt(ARG_MESSAGE))
                     .setPositiveButton(getArguments().getInt(ARG_BUTTON), null)
                     .create();
+            dialog.setCanceledOnTouchOutside(false);
+            return dialog;
         }
 
         @Override
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index 726bf0a..56ab34a 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -39,7 +39,9 @@
 import android.widget.ImageView;
 import android.widget.ListView;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.Settings.TetherSettingsActivity;
+import com.android.settings.overlay.FeatureFactory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -56,7 +58,8 @@
 
     @Override
     protected void onListItemClick(ListView l, View v, int position, long id) {
-        ListItem item = itemForPosition(position);
+        final ListItem item = itemForPosition(position);
+        logCreateShortcut(item.resolveInfo);
         setResult(RESULT_OK, createResultIntent(intentForPosition(position),
                 item.resolveInfo, item.label));
         finish();
@@ -89,6 +92,15 @@
         return intent;
     }
 
+    private void logCreateShortcut(ResolveInfo info) {
+        if (info == null || info.activityInfo == null) {
+            return;
+        }
+        FeatureFactory.getFactory(this).getMetricsFeatureProvider().action(
+                this, MetricsProto.MetricsEvent.ACTION_SETTINGS_CREATE_SHORTCUT,
+                info.activityInfo.name);
+    }
+
     private Bitmap createIcon(int resource) {
         Context context = new ContextThemeWrapper(this, android.R.style.Theme_Material);
         View view = LayoutInflater.from(context).inflate(R.layout.shortcut_badge, null);
@@ -165,7 +177,7 @@
                     continue;
                 }
                 updates.add(new ShortcutInfo.Builder(mContext, info.getId())
-                    .setShortLabel(ri.loadLabel(pm)).build());
+                        .setShortLabel(ri.loadLabel(pm)).build());
             }
             if (!updates.isEmpty()) {
                 sm.updateShortcuts(updates);
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index ddf0dec..eeb4779 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -1164,7 +1164,7 @@
 
     void setImsConfigProvisionedState(int configItem, boolean state) {
         if (phone != null && mImsManager != null) {
-            QueuedWork.queue(new Runnable() {
+            QueuedWork.singleThreadExecutor().submit(new Runnable() {
                 public void run() {
                     try {
                         mImsManager.getConfigInterface().setProvisionedValue(
@@ -1174,7 +1174,7 @@
                         Log.e(TAG, "setImsConfigProvisioned() exception:", e);
                     }
                 }
-            }, false);
+            });
         }
     }
 
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 179b31b..51613c7 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -69,7 +69,6 @@
 import com.android.settingslib.drawer.SettingsDrawerActivity;
 import com.android.settingslib.drawer.Tile;
 
-import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 910e1eb..253ed76 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -253,7 +253,8 @@
                     new NfcPreferenceController(context).updateNonIndexableKeys(result);
                     new MobilePlanPreferenceController(context, null /* MobilePlanClickHandler */)
                             .updateNonIndexableKeys(result);
-                    new MobileNetworkPreferenceController(context).updateNonIndexableKeys(result);
+                    new MobileNetworkPreferenceController(context)
+                            .updateNonIndexableKeys(result);
 
                     // Remove Airplane Mode settings if it's a stationary device such as a TV.
                     new AirplaneModePreferenceController(context, null /* fragment */)
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 8143e96..801a20b 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -24,6 +24,7 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 
+import android.support.v7.preference.PreferenceScreen;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.Utils;
@@ -84,7 +85,7 @@
         if (mAccountLabel != null) {
             getActivity().setTitle(mAccountLabel);
         }
-        updateAccountHeader();
+        updateUi();
     }
 
     @Override
@@ -125,7 +126,7 @@
     }
 
     @VisibleForTesting
-    void updateAccountHeader() {
+    void updateUi() {
         final Preference headerPreference = findPreference(KEY_ACCOUNT_HEADER);
         headerPreference.setTitle(mAccount.name);
         final Context context = getContext();
@@ -136,6 +137,13 @@
         }
         final AuthenticatorHelper helper = new AuthenticatorHelper(context, userHandle, null);
         headerPreference.setIcon(helper.getDrawableForType(context, mAccountType));
+        final AccountTypePreferenceLoader accountTypePreferenceLoader =
+            new AccountTypePreferenceLoader(this, helper, userHandle);
+        PreferenceScreen prefs =
+            accountTypePreferenceLoader.addPreferencesForType(mAccountType, getPreferenceScreen());
+        if (prefs != null) {
+            accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
+        }
     }
 
 }
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/AccountPreferenceBase.java b/src/com/android/settings/accounts/AccountPreferenceBase.java
index aa5c518..605688e 100644
--- a/src/com/android/settings/accounts/AccountPreferenceBase.java
+++ b/src/com/android/settings/accounts/AccountPreferenceBase.java
@@ -58,6 +58,7 @@
     private Object mStatusChangeListenerHandle;
     protected AuthenticatorHelper mAuthenticatorHelper;
     protected UserHandle mUserHandle;
+    protected AccountTypePreferenceLoader mAccountTypePreferenceLoader;
 
     private java.text.DateFormat mDateFormat;
     private java.text.DateFormat mTimeFormat;
@@ -70,6 +71,8 @@
         mUserHandle = Utils.getSecureTargetUser(activity.getActivityToken(), mUm, getArguments(),
                 activity.getIntent().getExtras());
         mAuthenticatorHelper = new AuthenticatorHelper(activity, mUserHandle, this);
+        mAccountTypePreferenceLoader =
+            new AccountTypePreferenceLoader(this, mAuthenticatorHelper, mUserHandle);
     }
 
     /**
@@ -142,35 +145,7 @@
      */
     public PreferenceScreen addPreferencesForType(final String accountType,
             PreferenceScreen parent) {
-        PreferenceScreen prefs = null;
-        if (mAuthenticatorHelper.containsAccountType(accountType)) {
-            AuthenticatorDescription desc = null;
-            try {
-                desc = mAuthenticatorHelper.getAccountTypeDescription(accountType);
-                if (desc != null && desc.accountPreferencesId != 0) {
-                    // Load the context of the target package, then apply the
-                    // base Settings theme (no references to local resources)
-                    // and create a context theme wrapper so that we get the
-                    // correct text colors. Control colors will still be wrong,
-                    // but there's not much we can do about it since we can't
-                    // reference local color resources.
-                    final Context targetCtx = getActivity().createPackageContextAsUser(
-                            desc.packageName, 0, mUserHandle);
-                    final Theme baseTheme = getResources().newTheme();
-                    baseTheme.applyStyle(com.android.settings.R.style.Theme_SettingsBase, true);
-                    final Context themedCtx =
-                            new LocalClassLoaderContextThemeWrapper(getClass(), targetCtx, 0);
-                    themedCtx.getTheme().setTo(baseTheme);
-                    prefs = getPreferenceManager().inflateFromResource(themedCtx,
-                            desc.accountPreferencesId, parent);
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
-            } catch (Resources.NotFoundException e) {
-                Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
-            }
-        }
-        return prefs;
+        return mAccountTypePreferenceLoader.addPreferencesForType(accountType, parent);
     }
 
     public void updateAuthDescriptions() {
diff --git a/src/com/android/settings/accounts/AccountTypePreferenceLoader.java b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
new file mode 100644
index 0000000..87f9c77
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountTypePreferenceLoader.java
@@ -0,0 +1,245 @@
+/*
+
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.accounts.AuthenticatorDescription;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.os.UserHandle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceScreen;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.location.LocationSettings;
+import com.android.settings.utils.LocalClassLoaderContextThemeWrapper;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+
+/**
+ * Class to load the preference screen to be added to the settings page for the specific account
+ * type as specified in the account-authenticator.
+ */
+public class AccountTypePreferenceLoader {
+
+    private static final String TAG = "AccountTypePrefLoader";
+    private static final String ACCOUNT_KEY = "account"; // to pass to auth settings
+    // Action name for the broadcast intent when the Google account preferences page is launching
+    // the location settings.
+    private static final String LAUNCHING_LOCATION_SETTINGS =
+        "com.android.settings.accounts.LAUNCHING_LOCATION_SETTINGS";
+
+
+    private AuthenticatorHelper mAuthenticatorHelper;
+    private UserHandle mUserHandle;
+    private PreferenceFragment mFragment;
+
+    public AccountTypePreferenceLoader(PreferenceFragment fragment,
+            AuthenticatorHelper authenticatorHelper, UserHandle userHandle) {
+        mFragment = fragment;
+        mAuthenticatorHelper = authenticatorHelper;
+        mUserHandle = userHandle;
+    }
+
+    /**
+     * Gets the preferences.xml file associated with a particular account type.
+     * @param accountType the type of account
+     * @return a PreferenceScreen inflated from accountPreferenceId.
+     */
+    public PreferenceScreen addPreferencesForType(final String accountType,
+            PreferenceScreen parent) {
+        PreferenceScreen prefs = null;
+        if (mAuthenticatorHelper.containsAccountType(accountType)) {
+            AuthenticatorDescription desc = null;
+            try {
+                desc = mAuthenticatorHelper.getAccountTypeDescription(accountType);
+                if (desc != null && desc.accountPreferencesId != 0) {
+                    // Load the context of the target package, then apply the
+                    // base Settings theme (no references to local resources)
+                    // and create a context theme wrapper so that we get the
+                    // correct text colors. Control colors will still be wrong,
+                    // but there's not much we can do about it since we can't
+                    // reference local color resources.
+                    final Context targetCtx = mFragment.getActivity().createPackageContextAsUser(
+                            desc.packageName, 0, mUserHandle);
+                    final Theme baseTheme = mFragment.getResources().newTheme();
+                    baseTheme.applyStyle(R.style.Theme_SettingsBase, true);
+                    final Context themedCtx =
+                            new LocalClassLoaderContextThemeWrapper(getClass(), targetCtx, 0);
+                    themedCtx.getTheme().setTo(baseTheme);
+                    prefs = mFragment.getPreferenceManager().inflateFromResource(themedCtx,
+                            desc.accountPreferencesId, parent);
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
+            } catch (Resources.NotFoundException e) {
+                Log.w(TAG, "Couldn't load preferences.xml file from " + desc.packageName);
+            }
+        }
+        return prefs;
+    }
+
+    /**
+     * Recursively filters through the preference list provided by GoogleLoginService.
+     *
+     * This method removes all the invalid intent from the list, adds account name as extra into the
+     * intent, and hack the location settings to start it as a fragment.
+     */
+    public void updatePreferenceIntents(PreferenceGroup prefs, final String acccountType,
+            Account account) {
+        final PackageManager pm = mFragment.getActivity().getPackageManager();
+        for (int i = 0; i < prefs.getPreferenceCount(); ) {
+            Preference pref = prefs.getPreference(i);
+            if (pref instanceof PreferenceGroup) {
+                updatePreferenceIntents((PreferenceGroup) pref, acccountType, account);
+            }
+            Intent intent = pref.getIntent();
+            if (intent != null) {
+                // Hack. Launch "Location" as fragment instead of as activity.
+                //
+                // When "Location" is launched as activity via Intent, there's no "Up" button at the
+                // top left, and if there's another running instance of "Location" activity, the
+                // back stack would usually point to some other place so the user won't be able to
+                // go back to the previous page by "back" key. Using fragment is a much easier
+                // solution to those problems.
+                //
+                // If we set Intent to null and assign a fragment to the PreferenceScreen item here,
+                // in order to make it work as expected, we still need to modify the container
+                // PreferenceActivity, override onPreferenceStartFragment() and call
+                // startPreferencePanel() there. In order to inject the title string there, more
+                // dirty further hack is still needed. It's much easier and cleaner to listen to
+                // preference click event here directly.
+                if (intent.getAction().equals(
+                    android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)) {
+                    // The OnPreferenceClickListener overrides the click event completely. No intent
+                    // will get fired.
+                    pref.setOnPreferenceClickListener(new FragmentStarter(
+                        LocationSettings.class.getName(), R.string.location_settings_title));
+                } else {
+                    ResolveInfo ri = pm.resolveActivityAsUser(intent,
+                        PackageManager.MATCH_DEFAULT_ONLY, mUserHandle.getIdentifier());
+                    if (ri == null) {
+                        prefs.removePreference(pref);
+                        continue;
+                    }
+                    intent.putExtra(ACCOUNT_KEY, account);
+                    intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+                    pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                        @Override
+                        public boolean onPreferenceClick(Preference preference) {
+                            Intent prefIntent = preference.getIntent();
+                                /*
+                                 * Check the intent to see if it resolves to a exported=false
+                                 * activity that doesn't share a uid with the authenticator.
+                                 *
+                                 * Otherwise the intent is considered unsafe in that it will be
+                                 * exploiting the fact that settings has system privileges.
+                                 */
+                            if (isSafeIntent(pm, prefIntent, acccountType)) {
+                                mFragment.getActivity().startActivityAsUser(
+                                    prefIntent, mUserHandle);
+                            } else {
+                                Log.e(TAG,
+                                    "Refusing to launch authenticator intent because"
+                                        + "it exploits Settings permissions: "
+                                        + prefIntent);
+                            }
+                            return true;
+                        }
+                    });
+                }
+            }
+            i++;
+        }
+    }
+
+    /**
+     * Determines if the supplied Intent is safe. A safe intent is one that is
+     * will launch a exported=true activity or owned by the same uid as the
+     * authenticator supplying the intent.
+     */
+    private boolean isSafeIntent(PackageManager pm, Intent intent, String acccountType) {
+        AuthenticatorDescription authDesc =
+            mAuthenticatorHelper.getAccountTypeDescription(acccountType);
+        ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mUserHandle.getIdentifier());
+        if (resolveInfo == null) {
+            return false;
+        }
+        ActivityInfo resolvedActivityInfo = resolveInfo.activityInfo;
+        ApplicationInfo resolvedAppInfo = resolvedActivityInfo.applicationInfo;
+        try {
+            if (resolvedActivityInfo.exported) {
+                if (resolvedActivityInfo.permission == null) {
+                    return true; // exported activity without permission.
+                } else if (pm.checkPermission(resolvedActivityInfo.permission,
+                    authDesc.packageName) == PackageManager.PERMISSION_GRANTED) {
+                    return true;
+                }
+            }
+            ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0);
+            return resolvedAppInfo.uid == authenticatorAppInf.uid;
+        } catch (NameNotFoundException e) {
+            Log.e(TAG,
+                "Intent considered unsafe due to exception.",
+                e);
+            return false;
+        }
+    }
+
+    /** Listens to a preference click event and starts a fragment */
+    private class FragmentStarter
+        implements Preference.OnPreferenceClickListener {
+        private final String mClass;
+        private final int mTitleRes;
+
+        /**
+         * @param className the class name of the fragment to be started.
+         * @param title the title resource id of the started preference panel.
+         */
+        public FragmentStarter(String className, int title) {
+            mClass = className;
+            mTitleRes = title;
+        }
+
+        @Override
+        public boolean onPreferenceClick(Preference preference) {
+            ((SettingsActivity) mFragment.getActivity()).startPreferencePanel(
+                mClass, null, mTitleRes, null, null, 0);
+            // Hack: announce that the Google account preferences page is launching the location
+            // settings
+            if (mClass.equals(LocationSettings.class.getName())) {
+                Intent intent = new Intent(LAUNCHING_LOCATION_SETTINGS);
+                mFragment.getActivity().sendBroadcast(
+                    intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
+            }
+            return true;
+        }
+    }
+
+}
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index ce717e2..7c5ee00 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -18,25 +18,17 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AuthenticatorDescription;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.ContentResolver;
-import android.content.Intent;
 import android.content.SyncAdapterType;
 import android.content.SyncInfo;
 import android.content.SyncStatusInfo;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
 import android.support.v7.preference.PreferenceScreen;
 import android.util.ArraySet;
 import android.util.Log;
@@ -52,7 +44,6 @@
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
-import com.android.settings.location.LocationSettings;
 import com.android.settingslib.accounts.AuthenticatorHelper;
 
 import java.util.ArrayList;
@@ -65,15 +56,9 @@
 /** Manages settings for Google Account. */
 public class ManageAccountsSettings extends AccountPreferenceBase
         implements AuthenticatorHelper.OnAccountsUpdateListener {
-    private static final String ACCOUNT_KEY = "account"; // to pass to auth settings
     public static final String KEY_ACCOUNT_TYPE = "account_type";
     public static final String KEY_ACCOUNT_LABEL = "account_label";
 
-    // Action name for the broadcast intent when the Google account preferences page is launching
-    // the location settings.
-    private static final String LAUNCHING_LOCATION_SETTINGS =
-            "com.android.settings.accounts.LAUNCHING_LOCATION_SETTINGS";
-
     private static final int MENU_SYNC_NOW_ID = Menu.FIRST;
     private static final int MENU_SYNC_CANCEL_ID = Menu.FIRST + 1;
 
@@ -84,7 +69,7 @@
 
     // If an account type is set, then show only accounts of that type
     private String mAccountType;
-    // Temporary hack, to deal with backward compatibility 
+    // Temporary hack, to deal with backward compatibility
     // mFirstAccount is used for the injected preferences
     private Account mFirstAccount;
 
@@ -413,134 +398,7 @@
     private void addAuthenticatorSettings() {
         PreferenceScreen prefs = addPreferencesForType(mAccountType, getPreferenceScreen());
         if (prefs != null) {
-            updatePreferenceIntents(prefs);
-        }
-    }
-
-    /** Listens to a preference click event and starts a fragment */
-    private class FragmentStarter
-            implements Preference.OnPreferenceClickListener {
-        private final String mClass;
-        private final int mTitleRes;
-
-        /**
-         * @param className the class name of the fragment to be started.
-         * @param title the title resource id of the started preference panel.
-         */
-        public FragmentStarter(String className, int title) {
-            mClass = className;
-            mTitleRes = title;
-        }
-
-        @Override
-        public boolean onPreferenceClick(Preference preference) {
-            ((SettingsActivity) getActivity()).startPreferencePanel(
-                    mClass, null, mTitleRes, null, null, 0);
-            // Hack: announce that the Google account preferences page is launching the location
-            // settings
-            if (mClass.equals(LocationSettings.class.getName())) {
-                Intent intent = new Intent(LAUNCHING_LOCATION_SETTINGS);
-                getActivity().sendBroadcast(
-                        intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Filters through the preference list provided by GoogleLoginService.
-     *
-     * This method removes all the invalid intent from the list, adds account name as extra into the
-     * intent, and hack the location settings to start it as a fragment.
-     */
-    private void updatePreferenceIntents(PreferenceScreen prefs) {
-        final PackageManager pm = getActivity().getPackageManager();
-        for (int i = 0; i < prefs.getPreferenceCount(); ) {
-            Preference pref = prefs.getPreference(i);
-            Intent intent = pref.getIntent();
-            if (intent != null) {
-                // Hack. Launch "Location" as fragment instead of as activity.
-                //
-                // When "Location" is launched as activity via Intent, there's no "Up" button at the
-                // top left, and if there's another running instance of "Location" activity, the
-                // back stack would usually point to some other place so the user won't be able to
-                // go back to the previous page by "back" key. Using fragment is a much easier
-                // solution to those problems.
-                //
-                // If we set Intent to null and assign a fragment to the PreferenceScreen item here,
-                // in order to make it work as expected, we still need to modify the container
-                // PreferenceActivity, override onPreferenceStartFragment() and call
-                // startPreferencePanel() there. In order to inject the title string there, more
-                // dirty further hack is still needed. It's much easier and cleaner to listen to
-                // preference click event here directly.
-                if (intent.getAction().equals(
-                        android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)) {
-                    // The OnPreferenceClickListener overrides the click event completely. No intent
-                    // will get fired.
-                    pref.setOnPreferenceClickListener(new FragmentStarter(
-                            LocationSettings.class.getName(),
-                            R.string.location_settings_title));
-                } else {
-                    ResolveInfo ri = pm.resolveActivityAsUser(intent,
-                            PackageManager.MATCH_DEFAULT_ONLY, mUserHandle.getIdentifier());
-                    if (ri == null) {
-                        prefs.removePreference(pref);
-                        continue;
-                    } else {
-                        intent.putExtra(ACCOUNT_KEY, mFirstAccount);
-                        intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
-                        pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-                            @Override
-                            public boolean onPreferenceClick(Preference preference) {
-                                Intent prefIntent = preference.getIntent();
-                                /*
-                                 * Check the intent to see if it resolves to a exported=false
-                                 * activity that doesn't share a uid with the authenticator.
-                                 *
-                                 * Otherwise the intent is considered unsafe in that it will be
-                                 * exploiting the fact that settings has system privileges.
-                                 */
-                                if (isSafeIntent(pm, prefIntent)) {
-                                    getActivity().startActivityAsUser(prefIntent, mUserHandle);
-                                } else {
-                                    Log.e(TAG,
-                                            "Refusing to launch authenticator intent because"
-                                                    + "it exploits Settings permissions: "
-                                                    + prefIntent);
-                                }
-                                return true;
-                            }
-                        });
-                    }
-                }
-            }
-            i++;
-        }
-    }
-
-    /**
-     * Determines if the supplied Intent is safe. A safe intent is one that is
-     * will launch a exported=true activity or owned by the same uid as the
-     * authenticator supplying the intent.
-     */
-    private boolean isSafeIntent(PackageManager pm, Intent intent) {
-        AuthenticatorDescription authDesc =
-                mAuthenticatorHelper.getAccountTypeDescription(mAccountType);
-        ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
-        if (resolveInfo == null) {
-            return false;
-        }
-        ActivityInfo resolvedActivityInfo = resolveInfo.activityInfo;
-        ApplicationInfo resolvedAppInfo = resolvedActivityInfo.applicationInfo;
-        try {
-            ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0);
-            return resolvedActivityInfo.exported
-                    || resolvedAppInfo.uid == authenticatorAppInf.uid;
-        } catch (NameNotFoundException e) {
-            Log.e(TAG,
-                    "Intent considered unsafe due to exception.",
-                    e);
-            return false;
+            mAccountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mFirstAccount);
         }
     }
 
diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java
index 8c00be9..156631c 100644
--- a/src/com/android/settings/accounts/ManagedProfileSettings.java
+++ b/src/com/android/settings/accounts/ManagedProfileSettings.java
@@ -31,6 +31,7 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedSwitchPreference;
 
@@ -97,7 +98,8 @@
                 }
             }
         }
-        return null;
+        // Return default managed profile for the current user.
+        return Utils.getManagedProfile(mUserManager);
     }
 
     private void loadDataAndPopulateUi() {
diff --git a/src/com/android/settings/applications/LayoutPreference.java b/src/com/android/settings/applications/LayoutPreference.java
index 1b5a8b5..b958b3a 100644
--- a/src/com/android/settings/applications/LayoutPreference.java
+++ b/src/com/android/settings/applications/LayoutPreference.java
@@ -59,7 +59,6 @@
 
     private void setView(View view) {
         setLayoutResource(R.layout.layout_preference_frame);
-        setSelectable(false);
         final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
         if (allDetails != null) {
             Utils.forceCustomPadding(allDetails, true /* additive padding */);
@@ -70,6 +69,7 @@
 
     @Override
     public void onBindViewHolder(PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
         FrameLayout layout = (FrameLayout) view.itemView;
         layout.removeAllViews();
         ViewGroup parent = (ViewGroup) mRootView.getParent();
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 146e1ff..d5f7f78 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -381,6 +381,8 @@
             AppFilter filter = new VolumeFilter(mVolumeUuid);
             if (mStorageType == STORAGE_TYPE_MUSIC) {
                 filter = new CompoundFilter(ApplicationsState.FILTER_AUDIO, filter);
+            } else {
+                filter = new CompoundFilter(ApplicationsState.FILTER_OTHER_APPS, filter);
             }
             mApplications.setOverrideFilter(filter);
         }
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 372a353..b6285ad 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -15,6 +15,7 @@
  */
 package com.android.settings.dashboard;
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.TypedArray;
@@ -28,7 +29,6 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -61,15 +61,17 @@
     private final IconCache mCache;
     private final Context mContext;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
+    private final DashboardFeatureProvider mDashboardFeatureProvider;
     private SuggestionParser mSuggestionParser;
 
-    @VisibleForTesting DashboardData mDashboardData;
+    @VisibleForTesting
+    DashboardData mDashboardData;
 
     private View.OnClickListener mTileClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             //TODO: get rid of setTag/getTag
-            ((SettingsActivity) mContext).openTile((Tile) v.getTag());
+            mDashboardFeatureProvider.openTileIntent((Activity) mContext, (Tile) v.getTag());
         }
     };
 
@@ -105,6 +107,8 @@
 
         mContext = context;
         mMetricsFeatureProvider = metricsFeatureProvider;
+        mDashboardFeatureProvider = FeatureFactory.getFactory(context)
+                .getDashboardFeatureProvider(context);
         mCache = new IconCache(context);
         mSuggestionParser = parser;
 
@@ -132,9 +136,9 @@
     public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
             List<Tile> suggestions) {
         // TODO: Better place for tinting?
-        final TypedArray a = mContext.obtainStyledAttributes(new int[] {
-            FeatureFactory.getFactory(mContext).getDashboardFeatureProvider(mContext).isEnabled()
-                ? android.R.attr.colorControlNormal : android.R.attr.colorAccent });
+        final TypedArray a = mContext.obtainStyledAttributes(new int[]{
+                mDashboardFeatureProvider.isEnabled()
+                        ? android.R.attr.colorControlNormal : android.R.attr.colorAccent});
         int tintColor = a.getColor(0, mContext.getColor(android.R.color.white));
         a.recycle();
         for (int i = 0; i < categories.size(); i++) {
@@ -405,12 +409,10 @@
         final List<Tile> suggestions = mDashboardData.getSuggestions();
         final List<DashboardCategory> categories = mDashboardData.getCategories();
         if (suggestions != null) {
-            outState.putParcelableArrayList(STATE_SUGGESTION_LIST,
-                    new ArrayList<Tile>(suggestions));
+            outState.putParcelableArrayList(STATE_SUGGESTION_LIST, new ArrayList<>(suggestions));
         }
         if (categories != null) {
-            outState.putParcelableArrayList(STATE_CATEGORY_LIST,
-                    new ArrayList<DashboardCategory>(categories));
+            outState.putParcelableArrayList(STATE_CATEGORY_LIST, new ArrayList<>(categories));
         }
         outState.putInt(STATE_SUGGESTION_MODE, mDashboardData.getSuggestionMode());
     }
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProvider.java b/src/com/android/settings/dashboard/DashboardFeatureProvider.java
index 2a5e800..7f91d16 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProvider.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProvider.java
@@ -93,4 +93,9 @@
      */
     String getExtraIntentAction();
 
+    /**
+     * Opens a tile to its destination intent.
+     */
+    void openTileIntent(Activity activity, Tile tile);
+
 }
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 08372b0..223d050 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -21,15 +21,20 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.SettingsActivity;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.drawer.CategoryManager;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.ProfileSelectDialog;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
 import com.android.settingslib.drawer.Tile;
 
 import java.util.ArrayList;
@@ -47,18 +52,20 @@
 
 
     protected final Context mContext;
-
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
     private final CategoryManager mCategoryManager;
 
     public DashboardFeatureProviderImpl(Context context) {
         mContext = context.getApplicationContext();
         mCategoryManager = CategoryManager.get(context, getExtraIntentAction());
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
     @VisibleForTesting
     DashboardFeatureProviderImpl(Context context, CategoryManager categoryManager) {
         mContext = context.getApplicationContext();
         mCategoryManager = categoryManager;
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
     @Override
@@ -149,14 +156,7 @@
                 intent.setAction(action);
             }
             pref.setOnPreferenceClickListener(preference -> {
-                ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
-                if (tile.userHandle == null) {
-                    activity.startActivityForResult(intent, 0);
-                } else if (tile.userHandle.size() == 1) {
-                    activity.startActivityForResultAsUser(intent, 0, tile.userHandle.get(0));
-                } else {
-                    ProfileSelectDialog.show(activity.getFragmentManager(), tile);
-                }
+                launchIntentOrSelectProfile(activity, tile, intent);
                 return true;
             });
         }
@@ -188,4 +188,48 @@
     public String getExtraIntentAction() {
         return null;
     }
+
+    @Override
+    public void openTileIntent(Activity activity, Tile tile) {
+        if (tile == null) {
+            Intent intent = new Intent(Settings.ACTION_SETTINGS).addFlags(
+                    Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            mContext.startActivity(intent);
+            return;
+        }
+
+        if (tile.intent == null) {
+            return;
+        }
+        final Intent intent = new Intent(tile.intent)
+                .putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true)
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        launchIntentOrSelectProfile(activity, tile, intent);
+    }
+
+    private void launchIntentOrSelectProfile(Activity activity, Tile tile, Intent intent) {
+        ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
+        if (tile.userHandle == null) {
+            logStartActivity(intent);
+            activity.startActivityForResult(intent, 0);
+        } else if (tile.userHandle.size() == 1) {
+            logStartActivity(intent);
+            activity.startActivityForResultAsUser(intent, 0, tile.userHandle.get(0));
+        } else {
+            ProfileSelectDialog.show(activity.getFragmentManager(), tile);
+        }
+    }
+
+    private void logStartActivity(Intent intent) {
+        if (intent == null) {
+            return;
+        }
+        final ComponentName cn = intent.getComponent();
+        if (cn == null) {
+            return;
+        }
+        mMetricsFeatureProvider.action(mContext,
+                MetricsProto.MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                cn.flattenToString());
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
index 3170a87..769b69b 100644
--- a/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/ManageStoragePreferenceController.java
@@ -16,14 +16,13 @@
 package com.android.settings.deviceinfo;
 
 import android.content.Context;
-import android.support.v7.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 
 public class ManageStoragePreferenceController extends PreferenceController {
 
-    public static final String KEY_MANAGE_STORAGE = "footer_preference";
+    public static final String KEY_MANAGE_STORAGE = "manage_storage";
 
     public ManageStoragePreferenceController(Context context) {
         super(context);
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 6ec1b73..914a8fe 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -32,7 +32,6 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.widget.FooterPreference;
 import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
 
 import java.util.ArrayList;
@@ -84,13 +83,6 @@
         mSummaryController.updateBytes(usedBytes, totalSize);
         mPreferenceController.setVolume(mVolume);
         mPreferenceController.setSystemSize(systemSize);
-
-        // Initialize the footer preference to go to the smart storage management.
-        final FooterPreference pref = mFooterPreferenceMixin.createFooterPreference();
-        pref.setTitle(R.string.storage_menu_manage);
-        pref.setFragment("com.android.settings.deletionhelper.AutomaticStorageManagerSettings");
-        pref.setIcon(R.drawable.ic_settings_storage);
-        pref.setEnabled(true);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java b/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
index ef94158..7d3e1d1 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
@@ -37,6 +37,7 @@
 public class BatteryHistoryDetail extends SettingsPreferenceFragment {
     public static final String EXTRA_STATS = "stats";
     public static final String EXTRA_BROADCAST = "broadcast";
+    public static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
 
     private BatteryStats mStats;
     private Intent mBatteryBroadcast;
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index 7cf0780..1a349f7 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -33,43 +33,18 @@
 /**
  * Custom preference for displaying power consumption as a bar and an icon on the left for the
  * subsystem/app type.
- *
  */
 public class BatteryHistoryPreference extends Preference {
 
-    protected static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
-
-    private BatteryStatsHelper mHelper;
     private BatteryInfo mBatteryInfo;
 
     public BatteryHistoryPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         setLayoutResource(R.layout.battery_usage_graph);
-        setSelectable(true);
-    }
-
-    @Override
-    public void performClick() {
-        // TODO(b/34890746): remove this since history graph is not clickable
-        final Context context = getContext();
-        final PowerUsageFeatureProvider featureProvider = FeatureFactory.getFactory(context)
-                .getPowerUsageFeatureProvider(context);
-
-        if (featureProvider.isAdvancedUiEnabled()) {
-            Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
-                    null, 0, R.string.advanced_battery_title, null);
-        } else {
-            mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
-            Bundle args = new Bundle();
-            args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
-            args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
-            Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
-                    null, 0, R.string.history_details_title, null);
-        }
+        setSelectable(false);
     }
 
     public void setStats(BatteryStatsHelper batteryStats) {
-        mHelper = batteryStats;
         final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
         mBatteryInfo = BatteryInfo.getBatteryInfo(getContext(), batteryStats.getBatteryBroadcast(),
                 batteryStats.getStats(), elapsedRealtimeUs);
diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java
new file mode 100644
index 0000000..9127782
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -0,0 +1,86 @@
+/*
+ * 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.fuelgauge;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settingslib.graph.BatteryMeterDrawableBase;
+
+public class BatteryMeterView extends ImageView {
+    private BatteryMeterDrawable mDrawable;
+
+    public BatteryMeterView(Context context) {
+        this(context, null, 0);
+    }
+
+    public BatteryMeterView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public BatteryMeterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        final int frameColor = context.getColor(R.color.batterymeter_frame_color);
+        final int tintColor = Utils.getColorAttr(context, android.R.attr.colorAccent);
+
+        mDrawable = new BatteryMeterDrawable(context, frameColor);
+        mDrawable.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
+        mDrawable.setShowPercent(true);
+        setImageDrawable(mDrawable);
+    }
+
+    public void setBatteryInfo(int level) {
+        mDrawable.setBatteryLevel(level);
+    }
+
+    @VisibleForTesting
+    void setBatteryDrawable(BatteryMeterDrawable drawable) {
+        mDrawable = drawable;
+    }
+
+    public static class BatteryMeterDrawable extends BatteryMeterDrawableBase {
+        private final int mIntrinsicWidth;
+        private final int mIntrinsicHeight;
+
+        public BatteryMeterDrawable(Context context, int frameColor) {
+            super(context, frameColor);
+
+            mIntrinsicWidth = context.getResources()
+                    .getDimensionPixelSize(R.dimen.battery_meter_width);
+            mIntrinsicHeight = context.getResources()
+                    .getDimensionPixelSize(R.dimen.battery_meter_height);
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return mIntrinsicWidth;
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mIntrinsicHeight;
+        }
+    }
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index 60d1ecd..3d27d22 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -72,7 +72,7 @@
     @Override
     public void onResume() {
         super.onResume();
-        BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryPreference.BATTERY_HISTORY_FILE);
+        BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryDetail.BATTERY_HISTORY_FILE);
         updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver,
                 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
         if (mHandler.hasMessages(MSG_REFRESH_STATS)) {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 309830b..7b64ddf 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -38,7 +38,9 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatterySipper.DrainType;
@@ -47,6 +49,7 @@
 import com.android.settings.Settings.HighPowerApplicationsActivity;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
+import com.android.settings.applications.LayoutPreference;
 import com.android.settings.applications.ManageApplications;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.SummaryLoader;
@@ -75,7 +78,7 @@
     static final String TAG = "PowerUsageSummary";
 
     private static final String KEY_APP_LIST = "app_list";
-    private static final String KEY_BATTERY_HISTORY = "battery_history";
+    private static final String KEY_BATTERY_HEADER = "battery_header";
 
     private static final int MENU_STATS_TYPE = Menu.FIRST;
     private static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
@@ -83,7 +86,7 @@
     static final int MENU_ADDITIONAL_BATTERY_INFO = Menu.FIRST + 4;
     private static final int MENU_HELP = Menu.FIRST + 5;
 
-    private BatteryHistoryPreference mHistPref;
+    private LayoutPreference mBatteryLayoutPref;
     private PreferenceGroup mAppListGroup;
 
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
@@ -98,7 +101,7 @@
         super.onCreate(icicle);
         setAnimationAllowed(true);
 
-        mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_HISTORY);
+        mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);
         mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
     }
 
@@ -130,7 +133,10 @@
 
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
-        if (!(preference instanceof PowerGaugePreference)) {
+        if (KEY_BATTERY_HEADER.equals(preference.getKey())) {
+            performBatteryHeaderClick();
+            return true;
+        } else if (!(preference instanceof PowerGaugePreference)) {
             return super.onPreferenceTreeClick(preference);
         }
         PowerGaugePreference pgp = (PowerGaugePreference) preference;
@@ -224,6 +230,26 @@
         }
     }
 
+    private void performBatteryHeaderClick() {
+        final Context context = getContext();
+        final PowerUsageFeatureProvider featureProvider = FeatureFactory.getFactory(context)
+                .getPowerUsageFeatureProvider(context);
+
+        if (featureProvider.isAdvancedUiEnabled()) {
+            Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
+                    null, 0, R.string.advanced_battery_title, null);
+        } else {
+            mStatsHelper.storeStatsHistoryInFile(BatteryHistoryDetail.BATTERY_HISTORY_FILE);
+            Bundle args = new Bundle(2);
+            args.putString(BatteryHistoryDetail.EXTRA_STATS,
+                    BatteryHistoryDetail.BATTERY_HISTORY_FILE);
+            args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
+                    mStatsHelper.getBatteryBroadcast());
+            Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
+                    null, 0, R.string.history_details_title, null);
+        }
+    }
+
     private static boolean isSharedGid(int uid) {
         return UserHandle.getAppIdFromSharedAppGid(uid) > 0;
     }
@@ -325,7 +351,14 @@
 
     protected void refreshStats() {
         super.refreshStats();
-        updatePreference(mHistPref);
+
+        BatteryInfo.getBatteryInfo(getContext(), new BatteryInfo.Callback() {
+            @Override
+            public void onBatteryInfoLoaded(BatteryInfo info) {
+                updateHeaderPreference(info);
+            }
+        });
+
         cacheRemoveAllPrefs(mAppListGroup);
         mAppListGroup.setOrderingAsAdded(false);
         boolean addedSome = false;
@@ -434,6 +467,27 @@
     }
 
     @VisibleForTesting
+    void updateHeaderPreference(BatteryInfo info) {
+        final BatteryMeterView batteryView = (BatteryMeterView) mBatteryLayoutPref
+                .findViewById(R.id.battery_header_icon);
+        final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.time);
+        final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
+        final TextView summary2 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary2);
+        final int visible = info.mBatteryLevel != 100 ? View.VISIBLE : View.INVISIBLE;
+
+        if (info.remainingTimeUs != 0) {
+            timeText.setText(Utils.formatElapsedTime(getContext(),
+                    info.remainingTimeUs / 1000, false));
+        } else {
+            timeText.setText(info.remainingLabel != null ?
+                    info.remainingLabel : info.batteryPercentString);
+        }
+        summary1.setVisibility(visible);
+        summary2.setVisibility(visible);
+        batteryView.setBatteryInfo(info.mBatteryLevel);
+    }
+
+    @VisibleForTesting
     void setUsageSummary(Preference preference, String usedTimePrefix, long usageTimeMs) {
         // Only show summary when usage time is longer than one minute
         if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
@@ -481,6 +535,11 @@
         return totalPowerMah;
     }
 
+    @VisibleForTesting
+    void setBatteryLayoutPreference(LayoutPreference layoutPreference) {
+        mBatteryLayoutPref = layoutPreference;
+    }
+
     private static List<BatterySipper> getFakeStats() {
         ArrayList<BatterySipper> stats = new ArrayList<>();
         float use = 5;
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index 7c8cd40..c7abf90 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -17,25 +17,39 @@
 
 import android.content.Context;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
 
 import com.android.settings.Utils;
 import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
 
 import static android.os.UserHandle.myUserId;
 import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
 import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
 
-public class MobileNetworkPreferenceController extends PreferenceController {
+public class MobileNetworkPreferenceController extends PreferenceController implements
+        LifecycleObserver, OnResume, OnPause {
 
     private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
 
     private final UserManager mUserManager;
     private final boolean mIsSecondaryUser;
+    private final TelephonyManager mTelephonyManager;
+    private Preference mPreference;
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    PhoneStateListener mPhoneStateListener;
 
     public MobileNetworkPreferenceController(Context context) {
         super(context);
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         mIsSecondaryUser = !mUserManager.isAdminUser();
     }
 
@@ -47,7 +61,39 @@
     }
 
     @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            mPreference = screen.findPreference(getPreferenceKey());
+        }
+    }
+
+    @Override
     public String getPreferenceKey() {
         return KEY_MOBILE_NETWORK_SETTINGS;
     }
+
+    @Override
+    public void onResume() {
+        if (isAvailable()) {
+            if (mPhoneStateListener == null) {
+                mPhoneStateListener = new PhoneStateListener() {
+                    @Override
+                    public void onServiceStateChanged(ServiceState serviceState) {
+                        if (mPreference != null) {
+                            mPreference.setSummary(mTelephonyManager.getNetworkOperatorName());
+                        }
+                    }
+                };
+            }
+            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mPhoneStateListener != null) {
+            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+        }
+    }
 }
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index d2b0621..f52230b 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -81,16 +81,22 @@
                 new MobilePlanPreferenceController(context, this);
         final WifiMasterSwitchPreferenceController wifiPreferenceController =
                 new WifiMasterSwitchPreferenceController(context, mMetricsFeatureProvider);
+        final MobileNetworkPreferenceController mobileNetworkPreferenceController =
+                new MobileNetworkPreferenceController(context);
+        final VpnPreferenceController vpnPreferenceController =
+                new VpnPreferenceController(context);
         final Lifecycle lifecycle = getLifecycle();
         lifecycle.addObserver(airplaneModePreferenceController);
         lifecycle.addObserver(mobilePlanPreferenceController);
         lifecycle.addObserver(wifiPreferenceController);
+        lifecycle.addObserver(mobileNetworkPreferenceController);
+        lifecycle.addObserver(vpnPreferenceController);
 
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(airplaneModePreferenceController);
-        controllers.add(new MobileNetworkPreferenceController(context));
+        controllers.add(mobileNetworkPreferenceController);
         controllers.add(new TetherPreferenceController(context));
-        controllers.add(new VpnPreferenceController(context));
+        controllers.add(vpnPreferenceController);
         controllers.add(new ProxyPreferenceController(context));
         controllers.add(mobilePlanPreferenceController);
         controllers.add(wifiPreferenceController);
diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java
index e24c873..236fa96 100644
--- a/src/com/android/settings/network/TetherPreferenceController.java
+++ b/src/com/android/settings/network/TetherPreferenceController.java
@@ -15,17 +15,23 @@
  */
 package com.android.settings.network;
 
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 
+import com.android.settings.R;
 import com.android.settings.TetherSettings;
 import com.android.settings.core.PreferenceController;
 
 import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
 import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
@@ -36,28 +42,60 @@
     private static final String KEY_TETHER_SETTINGS = "tether_settings";
 
     private final boolean mAdminDisallowedTetherConfig;
+    private final AtomicReference<BluetoothPan> mBluetoothPan;
     private final ConnectivityManager mConnectivityManager;
+    private final BluetoothAdapter mBluetoothAdapter;
     private final UserManager mUserManager;
 
+    private final BluetoothProfile.ServiceListener mBtProfileServiceListener =
+            new android.bluetooth.BluetoothProfile.ServiceListener() {
+                public void onServiceConnected(int profile, BluetoothProfile proxy) {
+                    mBluetoothPan.set((BluetoothPan) proxy);
+                    updateSummary();
+                }
+
+                public void onServiceDisconnected(int profile) {
+                    mBluetoothPan.set(null);
+                }
+            };
+
+    private Preference mPreference;
+
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    TetherPreferenceController() {
+        super(null);
+        mAdminDisallowedTetherConfig = false;
+        mBluetoothPan = null;
+        mConnectivityManager = null;
+        mBluetoothAdapter = null;
+        mUserManager = null;
+    }
+
     public TetherPreferenceController(Context context) {
         super(context);
+        mBluetoothPan = new AtomicReference<>();
         mAdminDisallowedTetherConfig = checkIfRestrictionEnforced(
                 context, DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null;
         mConnectivityManager =
                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        if (mBluetoothAdapter != null) {
+            mBluetoothAdapter.getProfileProxy(context, mBtProfileServiceListener,
+                    BluetoothProfile.PAN);
+        }
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        final Preference preference = screen.findPreference(KEY_TETHER_SETTINGS);
-        if (preference != null && !mAdminDisallowedTetherConfig) {
-            preference.setTitle(
+        mPreference = screen.findPreference(KEY_TETHER_SETTINGS);
+        if (mPreference != null && !mAdminDisallowedTetherConfig) {
+            mPreference.setTitle(
                     com.android.settingslib.Utils.getTetheringLabel(mConnectivityManager));
 
             // Grey out if provisioning is not available.
-            preference.setEnabled(!TetherSettings.isProvisioningNeededButUnavailable(mContext));
+            mPreference.setEnabled(!TetherSettings.isProvisioningNeededButUnavailable(mContext));
         }
     }
 
@@ -71,6 +109,11 @@
     }
 
     @Override
+    public void updateState(Preference preference) {
+        updateSummary();
+    }
+
+    @Override
     public void updateNonIndexableKeys(List<String> keys) {
         if (!mUserManager.isAdminUser() || !mConnectivityManager.isTetheringSupported()) {
             keys.add(KEY_TETHER_SETTINGS);
@@ -81,4 +124,60 @@
     public String getPreferenceKey() {
         return KEY_TETHER_SETTINGS;
     }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    void updateSummary() {
+        if (mPreference == null) {
+            // Preference is not ready yet.
+            return;
+        }
+        String[] allTethered = mConnectivityManager.getTetheredIfaces();
+        String[] wifiTetherRegex = mConnectivityManager.getTetherableWifiRegexs();
+        String[] bluetoothRegex = mConnectivityManager.getTetherableBluetoothRegexs();
+
+        boolean hotSpotOn = false;
+        boolean tetherOn = false;
+        if (allTethered != null) {
+            if (wifiTetherRegex != null) {
+                for (String tethered : allTethered) {
+                    for (String regex : wifiTetherRegex) {
+                        if (tethered.matches(regex)) {
+                            hotSpotOn = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (allTethered.length > 1) {
+                // We have more than 1 tethered connection
+                tetherOn = true;
+            } else if (allTethered.length == 1) {
+                // We have more than 1 tethered, it's either wifiTether (hotspot), or other type of
+                // tether.
+                tetherOn = !hotSpotOn;
+            } else {
+                // No tethered connection.
+                tetherOn = false;
+            }
+        }
+        if (!tetherOn
+                && bluetoothRegex != null && bluetoothRegex.length > 0
+                && mBluetoothAdapter != null
+                && mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
+            // Check bluetooth state. It's not included in mConnectivityManager.getTetheredIfaces.
+            final BluetoothPan pan = mBluetoothPan.get();
+            tetherOn = pan != null && pan.isTetheringOn();
+        }
+        if (!hotSpotOn && !tetherOn) {
+            // Both off
+            mPreference.setSummary(R.string.switch_off_text);
+        } else if (hotSpotOn && tetherOn) {
+            // Both on
+            mPreference.setSummary(R.string.tether_settings_summary_hotspot_on_tether_on);
+        } else if (hotSpotOn) {
+            mPreference.setSummary(R.string.tether_settings_summary_hotspot_on_tether_off);
+        } else {
+            mPreference.setSummary(R.string.tether_settings_summary_hotspot_off_tether_on);
+        }
+    }
 }
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index f7e230f..86ff175 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -16,38 +16,74 @@
 package com.android.settings.network;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
+import android.util.Log;
+import android.util.SparseArray;
 
+import com.android.internal.net.LegacyVpnInfo;
+import com.android.internal.net.VpnConfig;
+import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
 import com.android.settingslib.RestrictedLockUtils;
 
+import java.util.List;
 
-public class VpnPreferenceController extends PreferenceController {
+
+public class VpnPreferenceController extends PreferenceController implements LifecycleObserver,
+        OnResume, OnPause {
 
     private static final String KEY_VPN_SETTINGS = "vpn_settings";
+    private static final NetworkRequest REQUEST = new NetworkRequest.Builder()
+            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+            .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+            .build();
+    private static final String TAG = "VpnPreferenceController";
 
     private final String mToggleable;
-    private final boolean mIsSecondaryUser;
+    private final UserManager mUserManager;
+    private final ConnectivityManager mConnectivityManager;
+    private final IConnectivityManager mConnectivityManagerService;
+    private Preference mPreference;
 
     public VpnPreferenceController(Context context) {
         super(context);
         mToggleable = Settings.Global.getString(context.getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
-        mIsSecondaryUser = !UserManager.get(context).isAdminUser();
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mConnectivityManager =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mConnectivityManagerService = IConnectivityManager.Stub.asInterface(
+                ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
+        mPreference = screen.findPreference(KEY_VPN_SETTINGS);
         // Manually set dependencies for Wifi when not toggleable.
         if (mToggleable == null || !mToggleable.contains(Settings.Global.RADIO_WIFI)) {
-            final Preference pref = screen.findPreference(KEY_VPN_SETTINGS);
-            if (pref != null) {
-                pref.setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
+            if (mPreference != null) {
+                mPreference.setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
             }
         }
     }
@@ -62,4 +98,96 @@
     public String getPreferenceKey() {
         return KEY_VPN_SETTINGS;
     }
+
+    @Override
+    public void onPause() {
+        if (isAvailable()) {
+            mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        if (isAvailable()) {
+            mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
+        }
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    void updateSummary() {
+        if (mPreference == null) {
+            return;
+        }
+        // Copied from SystemUI::SecurityControllerImpl
+        SparseArray<VpnConfig> vpns = new SparseArray<>();
+        try {
+            final List<UserInfo> users = mUserManager.getUsers();
+            for (UserInfo user : users) {
+                VpnConfig cfg = mConnectivityManagerService.getVpnConfig(user.id);
+                if (cfg == null) {
+                    continue;
+                } else if (cfg.legacy) {
+                    // Legacy VPNs should do nothing if the network is disconnected. Third-party
+                    // VPN warnings need to continue as traffic can still go to the app.
+                    final LegacyVpnInfo legacyVpn =
+                            mConnectivityManagerService.getLegacyVpnInfo(user.id);
+                    if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) {
+                        continue;
+                    }
+                }
+                vpns.put(user.id, cfg);
+            }
+        } catch (RemoteException rme) {
+            // Roll back to previous state
+            Log.e(TAG, "Unable to list active VPNs", rme);
+            return;
+        }
+        final UserInfo userInfo = mUserManager.getUserInfo(UserHandle.myUserId());
+        final int uid;
+        if (userInfo.isRestricted()) {
+            uid = userInfo.restrictedProfileParentId;
+        } else {
+            uid = userInfo.id;
+        }
+        VpnConfig vpn = vpns.get(uid);
+        final String vpnName;
+        if (vpn == null) {
+            vpnName = null;
+        } else {
+            vpnName = getNameForVpnConfig(vpn, UserHandle.of(uid));
+        }
+        new Handler(Looper.getMainLooper()).post(() -> mPreference.setSummary(vpnName));
+    }
+
+    private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) {
+        if (cfg.legacy) {
+            return mContext.getString(R.string.bluetooth_connected);
+        }
+        // The package name for an active VPN is stored in the 'user' field of its VpnConfig
+        final String vpnPackage = cfg.user;
+        try {
+            Context userContext = mContext.createPackageContextAsUser(mContext.getPackageName(),
+                    0 /* flags */, user);
+            return VpnConfig.getVpnLabel(userContext, vpnPackage).toString();
+        } catch (PackageManager.NameNotFoundException nnfe) {
+            Log.e(TAG, "Package " + vpnPackage + " is not present", nnfe);
+            return null;
+        }
+    }
+
+    // Copied from SystemUI::SecurityControllerImpl
+    private final ConnectivityManager.NetworkCallback
+            mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+        @Override
+        public void onAvailable(Network network) {
+            Log.d(TAG, "onAvailable " + network.netId);
+            updateSummary();
+        }
+
+        @Override
+        public void onLost(Network network) {
+            Log.d(TAG, "onLost " + network.netId);
+            updateSummary();
+        }
+    };
 }
diff --git a/src/com/android/settings/search/DynamicIndexableContentMonitor.java b/src/com/android/settings/search/DynamicIndexableContentMonitor.java
index c5125bd..0cc2688 100644
--- a/src/com/android/settings/search/DynamicIndexableContentMonitor.java
+++ b/src/com/android/settings/search/DynamicIndexableContentMonitor.java
@@ -129,7 +129,7 @@
         mContext = context;
         mIndex = index;
 
-        PACKAGE_CHANGE_MONITOR.register(context);
+        PACKAGE_CHANGE_MONITOR.registerMonitor(context);
         mHasFeaturePrinting = context.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_PRINTING);
         if (mHasFeaturePrinting) {
@@ -154,7 +154,7 @@
     public void unregister(Activity activity, int loaderId) {
         if (mIndex == null) return;
 
-        PACKAGE_CHANGE_MONITOR.unregister();
+        PACKAGE_CHANGE_MONITOR.unregisterMonitor();
         if (mHasFeaturePrinting) {
             activity.getLoaderManager().destroyLoader(loaderId);
         }
@@ -240,15 +240,31 @@
     private static class PackageChangeMonitor extends PackageMonitor {
         private static final String TAG = PackageChangeMonitor.class.getSimpleName();
 
-        // Null if not initialized.
+        // Null if not initialized. Guarded by {@link #mLock}.
         @Nullable private PackageManager mPackageManager;
+        private final Object mLock = new Object();
 
-        public void register(Context context) {
-            mPackageManager = context.getPackageManager();
+        public void registerMonitor(Context context) {
+            synchronized (mLock) {
+                if (mPackageManager != null) {
+                    return;
+                }
+                mPackageManager = context.getPackageManager();
 
-            // Start tracking packages. Use background thread for monitoring. Note that no need to
-            // unregister this monitor. This should be alive while Settings app is running.
-            register(context, null /* thread */, UserHandle.CURRENT, false);
+                // Start tracking packages. Use background thread for monitoring. Note that no need
+                // to unregister this monitor. This should be alive while Settings app is running.
+                super.register(context, null /* thread */, UserHandle.CURRENT, false);
+            }
+        }
+
+        public void unregisterMonitor() {
+            synchronized (mLock) {
+                if (mPackageManager == null) {
+                    return;
+                }
+                super.unregister();
+                mPackageManager = null;
+            }
         }
 
         // Covers installed, appeared external storage with the package, upgraded.
diff --git a/tests/app/src/com/android/settings/deviceinfo/StorageDashboardFragmentEspressoTest.java b/tests/app/src/com/android/settings/deviceinfo/StorageDashboardFragmentEspressoTest.java
new file mode 100644
index 0000000..b43a5ba
--- /dev/null
+++ b/tests/app/src/com/android/settings/deviceinfo/StorageDashboardFragmentEspressoTest.java
@@ -0,0 +1,40 @@
+package com.android.settings.deviceinfo;
+
+import android.support.test.espresso.intent.rule.IntentsTestRule;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnitRunner;
+import com.android.settings.R;
+import com.android.settings.Settings.StorageDashboardActivity;
+import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.intent.Intents.intended;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+
+@SmallTest
+public class StorageDashboardFragmentEspressoTest {
+
+    public static final String EXTRA_KEY = ":settings:show_fragment";
+
+    @Rule
+    public IntentsTestRule<StorageDashboardActivity> mActivityRule =
+            new IntentsTestRule<>(StorageDashboardActivity.class, true, true);
+
+    @Test
+    public void testStorageManagePreference_canClickTextView() throws InterruptedException {
+        // Click on the actual textbox instead of just somewhere in the preference
+        onView(withText(R.string.storage_menu_manage)).perform(click());
+
+        // Check that it worked by seeing if we switched screens
+        intended(hasExtra(equalTo(EXTRA_KEY),
+                containsString(AutomaticStorageManagerSettings.class.getName())));
+
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
index 31090be..fd0ab4b 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
@@ -22,6 +22,7 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
@@ -61,6 +62,8 @@
     private AccountManager mAccountManager;
     @Mock
     private Preference mPreference;
+    @Mock
+    private PreferenceScreen mScreen;
 
     private AccountDetailDashboardFragment mFragment;
     private Context mContext;
@@ -125,9 +128,10 @@
             new AuthenticatorDescription[0]);
         when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
         when(mFragment.getContext()).thenReturn(mContext);
+        doReturn(mScreen).when(mFragment).getPreferenceScreen();
         doReturn(mPreference).when(mFragment).findPreference(PREF_ACCOUNT_HEADER);
 
-        mFragment.updateAccountHeader();
+        mFragment.updateUi();
 
         verify(mPreference).setTitle("name1@abc.com");
     }
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountTypePreferenceLoaderTest.java b/tests/robotests/src/com/android/settings/accounts/AccountTypePreferenceLoaderTest.java
new file mode 100644
index 0000000..29f254d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/AccountTypePreferenceLoaderTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowAccountManager;
+import com.android.settings.testutils.shadow.ShadowContentResolver;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AccountTypePreferenceLoaderTest {
+
+    @Mock(answer = RETURNS_DEEP_STUBS)
+    private AccountManager mAccountManager;
+    @Mock(answer = RETURNS_DEEP_STUBS)
+    private PreferenceFragment mPreferenceFragment;
+    @Mock
+    private PackageManager mPackageManager;
+
+    private Context mContext;
+    private Account mAccount;
+    private AccountTypePreferenceLoader mPrefLoader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowContext = ShadowApplication.getInstance();
+        shadowContext.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager);
+        when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
+            new AuthenticatorDescription[0]);
+        when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
+        when(mPreferenceFragment.getActivity().getPackageManager()).thenReturn(mPackageManager);
+        mContext = shadowContext.getApplicationContext();
+        mAccount = new Account("name", "type");
+        final AuthenticatorHelper helper = new AuthenticatorHelper(mContext, UserHandle.CURRENT,
+            null /* OnAccountsUpdateListener */);
+        mPrefLoader = spy(new AccountTypePreferenceLoader(mPreferenceFragment, helper,
+            UserHandle.CURRENT));
+    }
+
+    @Test
+    @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
+    public void updatePreferenceIntents_shouldRunRecursively() {
+        final PreferenceManager preferenceManager = mock(PreferenceManager.class);
+        // Top level
+        PreferenceGroup prefRoot = spy(new PreferenceScreen(mContext, null));
+        when(prefRoot.getPreferenceManager()).thenReturn(preferenceManager);
+        Preference pref1 = mock(Preference.class);
+        PreferenceGroup prefGroup2 = spy(new PreferenceScreen(mContext, null));
+        when(prefGroup2.getPreferenceManager()).thenReturn(preferenceManager);
+        Preference pref3 = mock(Preference.class);
+        PreferenceGroup prefGroup4 = spy(new PreferenceScreen(mContext, null));
+        when(prefGroup4.getPreferenceManager()).thenReturn(preferenceManager);
+        prefRoot.addPreference(pref1);
+        prefRoot.addPreference(prefGroup2);
+        prefRoot.addPreference(pref3);
+        prefRoot.addPreference(prefGroup4);
+
+        // 2nd level
+        Preference pref21 = mock(Preference.class);
+        Preference pref22 = mock(Preference.class);
+        prefGroup2.addPreference(pref21);
+        prefGroup2.addPreference(pref22);
+        PreferenceGroup prefGroup41 = spy(new PreferenceScreen(mContext, null));
+        when(prefGroup41.getPreferenceManager()).thenReturn(preferenceManager);
+        Preference pref42 = mock(Preference.class);
+        prefGroup4.addPreference(prefGroup41);
+        prefGroup4.addPreference(pref42);
+
+        // 3rd level
+        Preference pref411 = mock(Preference.class);
+        Preference pref412 = mock(Preference.class);
+        prefGroup41.addPreference(pref411);
+        prefGroup41.addPreference(pref412);
+
+        final String acctType = "testType";
+        mPrefLoader.updatePreferenceIntents(prefRoot, acctType, mAccount);
+
+        verify(mPrefLoader).updatePreferenceIntents(prefGroup2, acctType, mAccount);
+        verify(mPrefLoader).updatePreferenceIntents(prefGroup4, acctType, mAccount);
+        verify(mPrefLoader).updatePreferenceIntents(prefGroup41, acctType, mAccount);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index 917c336..af720cb 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -27,9 +27,11 @@
 import android.os.UserManager;
 import android.support.v7.preference.Preference;
 
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.CategoryManager;
 import com.android.settingslib.drawer.DashboardCategory;
@@ -50,6 +52,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -67,12 +70,15 @@
     private UserManager mUserManager;
     @Mock
     private CategoryManager mCategoryManager;
+    private FakeFeatureFactory mFeatureFactory;
 
     private DashboardFeatureProviderImpl mImpl;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mActivity);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mActivity);
         mImpl = new DashboardFeatureProviderImpl(mActivity);
     }
 
@@ -141,6 +147,30 @@
     }
 
     @Test
+    public void bindPreference_noFragmentMetadataSingleUser_shouldBindToDirectLaunchIntent() {
+        final Preference preference = new Preference(
+                ShadowApplication.getInstance().getApplicationContext());
+        final Tile tile = new Tile();
+        tile.metaData = new Bundle();
+        tile.userHandle = new ArrayList<>();
+        tile.userHandle.add(mock(UserHandle.class));
+        tile.intent = new Intent();
+        tile.intent.setComponent(new ComponentName("pkg", "class"));
+
+        when(mActivity.getSystemService(Context.USER_SERVICE))
+                .thenReturn(mUserManager);
+
+        mImpl.bindPreferenceToTile(mActivity, preference, tile, "123", Preference.DEFAULT_ORDER);
+        preference.getOnPreferenceClickListener().onPreferenceClick(null);
+        verify(mFeatureFactory.metricsFeatureProvider).action(
+                any(Context.class),
+                eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
+                eq(tile.intent.getComponent().flattenToString()));
+        verify(mActivity)
+                .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
+    }
+
+    @Test
     public void bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority() {
         final Preference preference = new Preference(
                 ShadowApplication.getInstance().getApplicationContext());
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
new file mode 100644
index 0000000..85b893a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.fuelgauge;
+
+import android.content.Context;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
+import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
+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;
+
+import static org.mockito.Mockito.verify;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+// TODO: Consider making the shadow class set global using a robolectric.properties file.
+@Config(manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class,
+                SettingsShadowTheme.class,
+                ShadowDynamicIndexableContentMonitor.class
+        })
+public class BatteryMeterViewTest {
+    private static final int BATTERY_LEVEL = 100;
+    @Mock
+    private BatteryMeterView.BatteryMeterDrawable mDrawable;
+    private Context mContext;
+    private BatteryMeterView mBatteryMeterView;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mBatteryMeterView = new BatteryMeterView(mContext);
+        mBatteryMeterView.setBatteryDrawable(mDrawable);
+    }
+
+    @Test
+    public void testSetBatteryInfo_SetCorrectly() {
+        mBatteryMeterView.setBatteryInfo(BATTERY_LEVEL);
+
+        verify(mDrawable).setBatteryLevel(BATTERY_LEVEL);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 60e1f50..f828238 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -23,11 +23,15 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.settings.R;
 import com.android.settings.TestConfig;
+import com.android.settings.applications.LayoutPreference;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.BatteryInfo;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -36,6 +40,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -57,8 +62,11 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class PowerUsageSummaryTest {
     private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
+    private static final String TIME_LEFT = "2h30min";
     private static final int UID = 123;
     private static final int POWER_MAH = 100;
+    private static final int BATTERY_LEVEL_FULL = 100;
+    private static final int BATTERY_LEVEL_HALF = 50;
     private static final double BATTERY_SCREEN_USAGE = 300;
     private static final double BATTERY_SYSTEM_USAGE = 600;
     private static final double PRECISION = 0.001;
@@ -83,6 +91,18 @@
     private BatterySipper mSystemBatterySipper;
     @Mock
     private PowerGaugePreference mPreference;
+    @Mock
+    private LayoutPreference mBatteryLayoutPref;
+    @Mock
+    private BatteryMeterView mBatteryMeterView;
+    @Mock
+    private TextView mTimeText;
+    @Mock
+    private TextView mSummary1;
+    @Mock
+    private TextView mSummary2;
+    @Mock
+    private BatteryInfo mBatteryInfo;
 
     private TestFragment mFragment;
     private FakeFeatureFactory mFeatureFactory;
@@ -113,6 +133,12 @@
         when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
         when(mNormalBatterySipper.getUid()).thenReturn(UID);
         mNormalBatterySipper.totalPowerMah = POWER_MAH;
+        when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1);
+        when(mBatteryLayoutPref.findViewById(R.id.summary2)).thenReturn(mSummary2);
+        when(mBatteryLayoutPref.findViewById(R.id.time)).thenReturn(mTimeText);
+        when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
+                .thenReturn(mBatteryMeterView);
+        mPowerUsageSummary.setBatteryLayoutPreference(mBatteryLayoutPref);
 
         mScreenBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
         mScreenBatterySipper.totalPowerMah = BATTERY_SCREEN_USAGE;
@@ -242,6 +268,28 @@
         verify(mPreference).setSummary(anyString());
     }
 
+    @Test
+    public void testUpdatePreference_BatteryFull_DoNotShowSummary() {
+        mBatteryInfo.mBatteryLevel = BATTERY_LEVEL_FULL;
+        mBatteryInfo.remainingLabel = TIME_LEFT;
+        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+
+        verify(mSummary1).setVisibility(View.INVISIBLE);
+        verify(mSummary2).setVisibility(View.INVISIBLE);
+        verify(mTimeText).setText(mBatteryInfo.remainingLabel);
+    }
+
+    @Test
+    public void testUpdatePreference_BatteryNotFull_ShowSummary() {
+        mBatteryInfo.mBatteryLevel = BATTERY_LEVEL_HALF;
+        mBatteryInfo.remainingLabel = TIME_LEFT;
+        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+
+        verify(mSummary1).setVisibility(View.VISIBLE);
+        verify(mSummary2).setVisibility(View.VISIBLE);
+        verify(mTimeText).setText(mBatteryInfo.remainingLabel);
+    }
+
     public static class TestFragment extends PowerUsageSummary {
 
         private Context mContext;
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
index d3d6836..1ae40aa 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
@@ -19,8 +19,15 @@
 import android.net.ConnectivityManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.core.lifecycle.Lifecycle;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -32,6 +39,10 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
@@ -44,15 +55,23 @@
     private UserManager mUserManager;
     @Mock
     private ConnectivityManager mConnectivityManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private PreferenceScreen mScreen;
 
+    private Lifecycle mLifecycle;
     private MobileNetworkPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mLifecycle = new Lifecycle();
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(mConnectivityManager);
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE))
+                .thenReturn(mTelephonyManager);
     }
 
     @Test
@@ -78,4 +97,45 @@
         mController = new MobileNetworkPreferenceController(mContext);
         assertThat(mController.isAvailable()).isFalse();
     }
+
+    @Test
+    public void goThroughLifecycle_isAvailable_shouldListenToServiceChange() {
+        mController = spy(new MobileNetworkPreferenceController(mContext));
+        mLifecycle.addObserver(mController);
+        doReturn(true).when(mController).isAvailable();
+
+        mLifecycle.onResume();
+        verify(mTelephonyManager).listen(mController.mPhoneStateListener,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
+
+        mLifecycle.onPause();
+        verify(mTelephonyManager).listen(mController.mPhoneStateListener,
+                PhoneStateListener.LISTEN_NONE);
+    }
+
+    @Test
+    public void serviceStateChange_shouldUpdatePrefSummary() {
+        final String testCarrierName = "test";
+        final Preference mPreference = mock(Preference.class);
+        mController = spy(new MobileNetworkPreferenceController(mContext));
+        mLifecycle.addObserver(mController);
+
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        doReturn(true).when(mController).isAvailable();
+
+        // Display pref and go through lifecycle to set up listener.
+        mController.displayPreference(mScreen);
+        mLifecycle.onResume();
+        verify(mController).onResume();
+        verify(mTelephonyManager).listen(mController.mPhoneStateListener,
+                PhoneStateListener.LISTEN_SERVICE_STATE);
+
+        // Trigger listener update
+        when(mTelephonyManager.getNetworkOperatorName()).thenReturn(testCarrierName);
+        mController.mPhoneStateListener.onServiceStateChanged(null);
+
+        // Carrier name should be set.
+        verify(mPreference).setSummary(testCarrierName);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
new file mode 100644
index 0000000..3d6a233
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.network;
+
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class TetherPreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private BluetoothAdapter mBluetoothAdapter;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private Preference mPreference;
+
+    private TetherPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = spy(TetherPreferenceController.class);
+        ReflectionHelpers.setField(mController, "mContext", mContext);
+        ReflectionHelpers.setField(mController, "mConnectivityManager", mConnectivityManager);
+        ReflectionHelpers.setField(mController, "mBluetoothAdapter", mBluetoothAdapter);
+        ReflectionHelpers.setField(mController, "mUserManager", mUserManager);
+    }
+
+    @Test
+    public void updateSummary_noPreference_noInteractionWithConnectivityManager() {
+        mController.updateSummary();
+        verifyNoMoreInteractions(mConnectivityManager);
+    }
+
+    @Test
+    public void updateSummary_wifiTethered_shouldShowHotspotMessage() {
+        ReflectionHelpers.setField(mController, "mPreference", mPreference);
+        when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"});
+        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"123"});
+
+        mController.updateSummary();
+        verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_on_tether_off);
+    }
+
+    @Test
+    public void updateSummary_btThetherOn_shouldShowTetherMessage() {
+        ReflectionHelpers.setField(mController, "mPreference", mPreference);
+        when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"});
+        when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"});
+
+        mController.updateSummary();
+        verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_off_tether_on);
+    }
+
+    @Test
+    public void updateSummary_tetherOff_shouldShowTetherOffMessage() {
+        ReflectionHelpers.setField(mController, "mPreference", mPreference);
+        when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"});
+        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"});
+
+        mController.updateSummary();
+        verify(mPreference).setSummary(R.string.switch_off_text);
+    }
+
+    @Test
+    public void updateSummary_wifiBtTetherOn_shouldShowHotspotAndTetherMessage() {
+        ReflectionHelpers.setField(mController, "mPreference", mPreference);
+        when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123", "456"});
+        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"});
+        when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"23"});
+
+        mController.updateSummary();
+        verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_on_tether_on);
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
new file mode 100644
index 0000000..2a0b873
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.network;
+
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.net.NetworkRequest;
+import android.os.IBinder;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowServiceManager;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VpnPreferenceControllerTest {
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private IBinder mBinder;
+    @Mock
+    private IConnectivityManager mConnectivityManagerService;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private Preference mPreference;
+    private VpnPreferenceController mController;
+    private Lifecycle mLifecycle;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+                .thenReturn(mConnectivityManager);
+        when(mBinder.queryLocalInterface("android.net.IConnectivityManager"))
+                .thenReturn(mConnectivityManagerService);
+        ShadowServiceManager.addService(Context.CONNECTIVITY_SERVICE, mBinder);
+        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+
+        mController = spy(new VpnPreferenceController(mContext));
+        mLifecycle = new Lifecycle();
+        mLifecycle.addObserver(mController);
+    }
+
+    @Test
+    public void displayPreference_available_shouldSetDependency() {
+
+        doReturn(true).when(mController).isAvailable();
+        mController.displayPreference(mScreen);
+
+        verify(mPreference).setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
+    }
+
+    @Test
+    public void goThroughLifecycle_shouldRegisterUnregisterListener() {
+        doReturn(true).when(mController).isAvailable();
+
+        mLifecycle.onResume();
+        verify(mConnectivityManager).registerNetworkCallback(
+                any(NetworkRequest.class), any(ConnectivityManager.NetworkCallback.class));
+
+        mLifecycle.onPause();
+        verify(mConnectivityManager).unregisterNetworkCallback(
+                any(ConnectivityManager.NetworkCallback.class));
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
index 3a1e0b7..cc55a4e 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
@@ -7,6 +7,7 @@
 import android.content.res.TypedArray;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ArrayRes;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import org.robolectric.RuntimeEnvironment;
@@ -59,6 +60,16 @@
         return super.loadDrawable(value, id, theme);
     }
 
+    @Implementation
+    public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
+        // The Robolectric isn't aware of resources in settingslib, so we need to stub it here
+        if (id == com.android.settings.R.array.batterymeter_bolt_points
+                || id == com.android.settings.R.array.batterymeter_plus_points) {
+            return new int[2];
+        }
+        return directlyOn(realResources, Resources.class).getIntArray(id);
+    }
+
     @Implements(Theme.class)
     public static class SettingsShadowTheme extends ShadowTheme {