Merge "Managed profile lock timeout"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 68cac15..8ce83b4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,6 +29,7 @@
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
     <uses-permission android:name="android.permission.ACCESS_WIMAX_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIMAX_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a01967f..851a925 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2108,6 +2108,11 @@
     <!-- Wifi hotspot footer info [CHAR LIMIT=NONE]-->
     <string name="wifi_hotspot_footer_info_local_only">Apps can create a hotspot to share content with nearby devices.</string>
 
+    <!-- Title for the toggle to turn off hotspot automatically [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_auto_off_title">Turn off hotspot automatically</string>
+    <!-- Summary for the toggle to turn off hotspot automatically [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_auto_off_summary">Wi\u2011Fi hotspot will turn off if no devices are connected</string>
+
     <!-- Summary text when turning hotspot on -->
     <string name="wifi_tether_starting">Turning hotspot on\u2026</string>
     <!-- Summary text when turning hotspot off -->
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 4c25da7..e3010a6 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -114,6 +114,21 @@
         <item name="android:windowAnimationStyle">@null</item>
     </style>
 
+    <style name="GlifV2Theme.Transparent">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:windowAnimationStyle">@null</item>
+    </style>
+
+    <style name="GlifV2Theme.Light.Transparent">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:windowAnimationStyle">@null</item>
+    </style>
+
+
     <style name="SuwSuggestionThemeGlif.Light" parent="SuwThemeGlif.Light">
         <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
     </style>
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 96fe905..f8ac192 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -20,19 +20,9 @@
         android:title="@string/location_settings_title"
         settings:keywords="@string/keywords_location">
 
-        <Preference
-            android:key="location_mode"
-            android:title="@string/location_mode_title"
-            settings:keywords="@string/keywords_location_mode"
-            android:summary="@string/summary_placeholder" />
-
-        <!-- This preference category gets removed if there is no managed profile -->
-        <com.android.settingslib.RestrictedSwitchPreference
-            android:key="managed_profile_location_switch"
-            android:title="@string/managed_profile_location_switch_title"
-            settings:useAdminDisabledSummary="true"
-            android:enabled="false"
-            android:selectable="true" />
+        <PreferenceCategory
+            android:key="recent_location_requests"
+            android:title="@string/location_category_recent_location_requests"/>
 
         <!-- This preference category gets removed if new_recent_location_ui is disabled -->
         <Preference
@@ -49,12 +39,21 @@
             android:title="@string/location_scanning_screen_title"
             android:fragment="com.android.settings.location.ScanningSettings"/>
 
-        <PreferenceCategory
-            android:key="recent_location_requests"
-            android:title="@string/location_category_recent_location_requests" />
+        <!-- This preference category gets removed if there is no managed profile -->
+        <com.android.settingslib.RestrictedSwitchPreference
+            android:key="managed_profile_location_switch"
+            android:title="@string/managed_profile_location_switch_title"
+            settings:useAdminDisabledSummary="true"
+            android:enabled="false"
+            android:selectable="true" />
 
         <PreferenceCategory
             android:key="location_services"
             android:title="@string/location_category_location_services" />
 
+        <Preference
+            android:key="location_mode"
+            android:title="@string/location_mode_title"
+            settings:keywords="@string/keywords_location_mode"
+            android:summary="@string/summary_placeholder" />
 </PreferenceScreen>
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index e58d319..6993f26 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -54,12 +54,6 @@
     </Preference>
 
     <Preference
-            android:key="wifi_calling_settings"
-            android:title="@string/wifi_calling_settings_title"
-            android:fragment="com.android.settings.WifiCallingSettings"
-            settings:keywords="@string/keywords_wifi_calling"/>
-
-    <Preference
             android:key="network_scorer_picker"
             android:title="@string/network_scorer_picker_title"
             android:fragment="com.android.settings.network.NetworkScorerPicker"/>
diff --git a/res/xml/wifi_tether_settings.xml b/res/xml/wifi_tether_settings.xml
index d6b8a25..bb9af88 100644
--- a/res/xml/wifi_tether_settings.xml
+++ b/res/xml/wifi_tether_settings.xml
@@ -17,7 +17,9 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:title="@string/wifi_hotspot_checkbox_text">
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/wifi_hotspot_checkbox_text"
+    settings:initialExpandedChildrenCount="2">
 
     <com.android.settings.widget.ValidatedEditTextPreference
         android:key="wifi_tether_network_name"
@@ -28,6 +30,11 @@
         android:key="wifi_tether_network_password"
         android:title="@string/wifi_hotspot_password_title" />
 
+    <SwitchPreference
+        android:key="wifi_tether_auto_turn_off"
+        android:title="@string/wifi_hotspot_auto_off_title"
+        android:summary="@string/wifi_hotspot_auto_off_summary"/>
+
     <ListPreference
         android:key="wifi_tether_network_ap_band"
         android:title="@string/wifi_hotspot_ap_band_title"
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index d53abae..e3e49eb 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -48,11 +48,16 @@
     }
 
     public static int getTransparentTheme(Intent intent) {
-        if (WizardManagerHelper.isLightTheme(intent, true)) {
-            return R.style.SetupWizardTheme_Light_Transparent;
-        } else {
-            return R.style.SetupWizardTheme_Transparent;
+        final int suwTheme = getTheme(intent);
+        int wifiDialogTheme = R.style.GlifV2Theme_Light_Transparent;
+        if (suwTheme == R.style.GlifV2Theme) {
+            wifiDialogTheme = R.style.GlifV2Theme_Transparent;
+        } else if (suwTheme == R.style.GlifTheme_Light) {
+            wifiDialogTheme = R.style.SetupWizardTheme_Light_Transparent;
+        } else if (suwTheme == R.style.GlifTheme) {
+            wifiDialogTheme = R.style.SetupWizardTheme_Transparent;
         }
+        return wifiDialogTheme;
     }
 
     public static void copySetupExtras(Intent fromIntent, Intent toIntent) {
diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java
index 156631c..50b9ecc 100644
--- a/src/com/android/settings/accounts/ManagedProfileSettings.java
+++ b/src/com/android/settings/accounts/ManagedProfileSettings.java
@@ -128,11 +128,8 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (preference == mWorkModePreference) {
-            if ((boolean) newValue) {
-                mUserManager.trySetQuietModeDisabled(mManagedUser.getIdentifier(), null);
-            } else {
-                mUserManager.setQuietModeEnabled(mManagedUser.getIdentifier(), true);
-            }
+            boolean quietModeEnabled = !(boolean) newValue;
+            mUserManager.trySetQuietModeEnabled(quietModeEnabled, mManagedUser);
             return true;
         }
         if (preference == mContactPrefrence) {
diff --git a/src/com/android/settings/dashboard/conditional/WorkModeCondition.java b/src/com/android/settings/dashboard/conditional/WorkModeCondition.java
index beed7b4..297e35a 100644
--- a/src/com/android/settings/dashboard/conditional/WorkModeCondition.java
+++ b/src/com/android/settings/dashboard/conditional/WorkModeCondition.java
@@ -91,7 +91,7 @@
     public void onActionClick(int index) {
         if (index == 0) {
             if (mUserHandle != null) {
-                mUm.trySetQuietModeDisabled(mUserHandle.getIdentifier(), null);
+                mUm.trySetQuietModeEnabled(false, mUserHandle);
             }
             setActive(false);
         } else {
diff --git a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java
index 614eb80..227f4a5 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java
@@ -16,15 +16,8 @@
 package com.android.settings.fuelgauge;
 
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.BatteryManager;
-import android.os.BatteryStats;
-import android.os.SystemClock;
+
 import com.android.internal.os.BatteryStatsHelper;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.utils.AsyncLoader;
 
 /**
@@ -49,40 +42,7 @@
 
     @Override
     public BatteryInfo loadInBackground() {
-        final long startTime = System.currentTimeMillis();
-        Context context = getContext();
-        PowerUsageFeatureProvider powerUsageFeatureProvider =
-                FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context);
-
-        // Stuff we always need to get BatteryInfo
-        Intent batteryBroadcast = context.registerReceiver(null,
-                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-        final long elapsedRealtimeUs = BatteryUtils.convertMsToUs(SystemClock.elapsedRealtime());
-        BatteryInfo batteryInfo;
-
-        // 0 means we are discharging, anything else means charging
-        boolean discharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
-        // Get enhanced prediction if available and discharging, otherwise use the old code
-        Cursor cursor = null;
-        if (discharging && powerUsageFeatureProvider != null &&
-                powerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context)) {
-            final Uri queryUri = powerUsageFeatureProvider.getEnhancedBatteryPredictionUri();
-            cursor = context.getContentResolver().query(queryUri, null, null, null, null);
-        }
-        BatteryStats stats = mStatsHelper.getStats();
-        BatteryUtils.logRuntime(LOG_TAG, "BatteryInfoLoader post query", startTime);
-        if (cursor != null && cursor.moveToFirst()) {
-            long enhancedEstimate = powerUsageFeatureProvider.getTimeRemainingEstimate(cursor);
-            batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
-                    elapsedRealtimeUs, false /* shortString */,
-                    BatteryUtils.convertMsToUs(enhancedEstimate), true /* basedOnUsage */);
-        } else {
-            batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
-                    elapsedRealtimeUs, false /* shortString */,
-                    discharging ? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0,
-                    false /* basedOnUsage */);
-        }
-        BatteryUtils.logRuntime(LOG_TAG, "BatteryInfoLoader.loadInBackground", startTime);
-        return batteryInfo;
+        final BatteryUtils batteryUtils = BatteryUtils.getInstance(getContext());
+        return batteryUtils.getBatteryInfo(mStatsHelper, LOG_TAG);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 3c83a9b..c623396 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -17,8 +17,13 @@
 
 import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.Build;
@@ -28,6 +33,7 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.annotation.VisibleForTesting;
+import android.support.annotation.WorkerThread;
 import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.SparseLongArray;
@@ -73,6 +79,7 @@
 
     private PackageManager mPackageManager;
     private AppOpsManager mAppOpsManager;
+    private Context mContext;
     @VisibleForTesting
     PowerUsageFeatureProvider mPowerUsageFeatureProvider;
 
@@ -85,6 +92,7 @@
 
     @VisibleForTesting
     BatteryUtils(Context context) {
+        mContext = context.getApplicationContext();
         mPackageManager = context.getPackageManager();
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         mPowerUsageFeatureProvider = FeatureFactory.getFactory(
@@ -388,6 +396,44 @@
         statsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, userManager.getUserProfiles());
     }
 
+    @WorkerThread
+    public BatteryInfo getBatteryInfo(final BatteryStatsHelper statsHelper, final String tag) {
+        final long startTime = System.currentTimeMillis();
+
+        // Stuff we always need to get BatteryInfo
+        final Intent batteryBroadcast = mContext.registerReceiver(null,
+                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        final long elapsedRealtimeUs = BatteryUtils.convertMsToUs(SystemClock.elapsedRealtime());
+        BatteryInfo batteryInfo;
+
+        // 0 means we are discharging, anything else means charging
+        final boolean discharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
+                == 0;
+        // Get enhanced prediction if available and discharging, otherwise use the old code
+        Cursor cursor = null;
+        if (discharging && mPowerUsageFeatureProvider != null &&
+                mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) {
+            final Uri queryUri = mPowerUsageFeatureProvider.getEnhancedBatteryPredictionUri();
+            cursor = mContext.getContentResolver().query(queryUri, null, null, null, null);
+        }
+        final BatteryStats stats = statsHelper.getStats();
+        BatteryUtils.logRuntime(tag, "BatteryInfoLoader post query", startTime);
+        if (cursor != null && cursor.moveToFirst()) {
+            long enhancedEstimate = mPowerUsageFeatureProvider.getTimeRemainingEstimate(cursor);
+            batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast, stats,
+                    elapsedRealtimeUs, false /* shortString */,
+                    BatteryUtils.convertMsToUs(enhancedEstimate), true /* basedOnUsage */);
+        } else {
+            batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast, stats,
+                    elapsedRealtimeUs, false /* shortString */,
+                    discharging ? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0,
+                    false /* basedOnUsage */);
+        }
+        BatteryUtils.logRuntime(tag, "BatteryInfoLoader.loadInBackground", startTime);
+
+        return batteryInfo;
+    }
+
     private boolean isDataCorrupted() {
         return mPackageManager == null || mAppOpsManager == null;
     }
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 2b5afe1..cbd9c3f 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -361,4 +361,14 @@
     public long[] getScreenOffCpuFreqTimes(int which) {
         return null;
     }
+
+    @Override
+    public long[] getCpuFreqTimes(int procState, int which) {
+        return null;
+    }
+
+    @Override
+    public long[] getScreenOffCpuFreqTimes(int procState, int which) {
+        return null;
+    }
 }
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 3330421..1279d67 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -73,6 +73,16 @@
     private LocationSwitchBarController mSwitchBarController;
 
     @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        final RecentLocationApps recentLocationApps = new RecentLocationApps(getActivity());
+        int locationRequestsApps = recentLocationApps.getAppList().size();
+        int locationRequestsPrefs = locationRequestsApps == 0 ? 1 : locationRequestsApps;
+        getPreferenceScreen().setInitialExpandedChildrenCount(locationRequestsPrefs + 2);
+    }
+
+
+    @Override
     public int getMetricsCategory() {
         return MetricsEvent.LOCATION;
     }
diff --git a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
index 461f6e3..8cbe95c 100644
--- a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
@@ -32,6 +32,7 @@
 import com.android.settingslib.location.RecentLocationApps;
 
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 
 public class RecentLocationRequestPreferenceController extends LocationBasePreferenceController {
@@ -107,15 +108,17 @@
 
         final Context prefContext = preference.getContext();
         final List<RecentLocationApps.Request> recentLocationRequests =
-                mRecentLocationApps.getAppList();
+                mRecentLocationApps.getAppListSorted();
 
         final List<Preference> recentLocationPrefs = new ArrayList<>(recentLocationRequests.size());
         for (final RecentLocationApps.Request request : recentLocationRequests) {
             recentLocationPrefs.add(createAppPreference(prefContext, request));
         }
         if (recentLocationRequests.size() > 0) {
-            LocationSettings.addPreferencesSorted(
-                    recentLocationPrefs, mCategoryRecentLocationRequests);
+            // Add preferences to container in original order (already sorted by recency).
+            for (Preference entry : recentLocationPrefs) {
+                mCategoryRecentLocationRequests.addPreference(entry);
+            }
         } else {
             // If there's no item to display, add a "No recent apps" item.
             final Preference banner = createAppPreference(prefContext);
diff --git a/src/com/android/settings/network/WifiCallingPreferenceController.java b/src/com/android/settings/network/WifiCallingPreferenceController.java
deleted file mode 100644
index 5d6e5cb..0000000
--- a/src/com/android/settings/network/WifiCallingPreferenceController.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 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.support.v7.preference.Preference;
-import android.telephony.TelephonyManager;
-
-import com.android.ims.ImsManager;
-import com.android.settings.WifiCallingSettings;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-
-public class WifiCallingPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin {
-
-    private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
-    private TelephonyManager mTm;
-
-    public WifiCallingPreferenceController(Context context) {
-        super(context);
-        mTm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        preference.setSummary(WifiCallingSettings.getWfcModeSummary(
-                mContext, ImsManager.getWfcMode(mContext, mTm.isNetworkRoaming())));
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return ImsManager.isWfcEnabledByPlatform(mContext)
-                && ImsManager.isWfcProvisionedOnDevice(mContext);
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_WFC_SETTINGS;
-    }
-}
diff --git a/src/com/android/settings/search/SearchFragment.java b/src/com/android/settings/search/SearchFragment.java
index e6316a8..ed7a2ee 100644
--- a/src/com/android/settings/search/SearchFragment.java
+++ b/src/com/android/settings/search/SearchFragment.java
@@ -28,6 +28,7 @@
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
 import android.util.TypedValue;
@@ -43,6 +44,7 @@
 import android.widget.Toolbar;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.EventLogTags;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
@@ -338,6 +340,8 @@
             mNoResultsView.setVisibility(View.VISIBLE);
             mMetricsFeatureProvider.visible(getContext(), getMetricsCategory(),
                     MetricsEvent.SETTINGS_SEARCH_NO_RESULT);
+            // Log settings_latency for search end-to-end.
+            EventLog.writeEvent(EventLogTags.SETTINGS_LATENCY, 1, 10);
         } else {
             mNoResultsView.setVisibility(View.GONE);
             mResultsRecyclerView.scrollToPosition(0);
diff --git a/src/com/android/settings/search/indexing/PreIndexDataCollector.java b/src/com/android/settings/search/indexing/PreIndexDataCollector.java
index a4e1131..63000b4 100644
--- a/src/com/android/settings/search/indexing/PreIndexDataCollector.java
+++ b/src/com/android/settings/search/indexing/PreIndexDataCollector.java
@@ -287,8 +287,14 @@
             String[] projection) {
 
         final ContentResolver resolver = packageContext.getContentResolver();
-        final Cursor cursor = resolver.query(uri, projection, null, null, null);
         final List<String> result = new ArrayList<>();
+        Cursor cursor;
+        try {
+            cursor = resolver.query(uri, projection, null, null, null);
+        } catch (NullPointerException e) {
+            Log.e(TAG, "Exception querying the keys!", e);
+            return result;
+        }
 
         if (cursor == null) {
             Log.w(TAG, "Cannot add index data for Uri: " + uri.toString());
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 22035d2..08ea7c6 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -88,7 +88,7 @@
         boolean finalWifiEnabled = wifiEnabled;
         return new ListBuilder(sliceUri)
                 .setColor(R.color.material_blue_500)
-                .add(b -> b
+                .addRow(b -> b
                         .setTitle(getContext().getString(R.string.wifi_settings))
                         .setTitleItem(Icon.createWithResource(getContext(), R.drawable.wifi_signal))
                         .setSubtitle(state)
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 13ec152..4cb87e5 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -30,7 +30,6 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.network.NetworkScorerPickerPreferenceController;
-import com.android.settings.network.WifiCallingPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.wifi.p2p.WifiP2pPreferenceController;
@@ -96,7 +95,6 @@
         controllers.add(new WifiInfoPreferenceController(context, getLifecycle(), wifiManager));
         controllers.add(new CellularFallbackPreferenceController(context));
         controllers.add(new WifiP2pPreferenceController(context, getLifecycle(), wifiManager));
-        controllers.add(new WifiCallingPreferenceController(context));
         controllers.add(new WpsPreferenceController(
                 context, getLifecycle(), wifiManager, getFragmentManager()));
         return controllers;
diff --git a/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java
new file mode 100644
index 0000000..5fa4e25
--- /dev/null
+++ b/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java
@@ -0,0 +1,53 @@
+/*
+ * 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.wifi.tether;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class WifiTetherAutoOffPreferenceController extends BasePreferenceController implements
+        Preference.OnPreferenceChangeListener {
+
+    public WifiTetherAutoOffPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final boolean settingsOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 0) != 0;
+
+        ((SwitchPreference) preference).setChecked(settingsOn);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean settingsOn = (Boolean) newValue;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SOFT_AP_TIMEOUT_ENABLED, settingsOn ? 1 : 0);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index d06ad4a..e9533b1 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -48,6 +48,7 @@
 
     private static final String TAG = "WifiTetherSettings";
     private static final IntentFilter TETHER_STATE_CHANGE_FILTER;
+    private static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off";
 
     private WifiTetherSwitchBarController mSwitchBarController;
     private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
@@ -133,6 +134,8 @@
         controllers.add(mSSIDPreferenceController);
         controllers.add(mPasswordPreferenceController);
         controllers.add(mApBandPreferenceController);
+        controllers.add(
+                new WifiTetherAutoOffPreferenceController(context, KEY_WIFI_TETHER_AUTO_OFF));
         return controllers;
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 5dfeec3..af3a3a5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -198,7 +198,7 @@
         doReturn(mPackageManager).when(mTestActivity).getPackageManager();
         doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE);
 
-        mBatteryUtils = spy(BatteryUtils.getInstance(mTestActivity));
+        mBatteryUtils = spy(new BatteryUtils(mContext));
         doReturn(FOREGROUND_SERVICE_TIME_US).when(mBatteryUtils).getForegroundServiceTotalTimeUs(
                 any(BatteryStats.Uid.class), anyLong());
 
diff --git a/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
index a1268d0..a9794c2 100644
--- a/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/RecentLocationRequestPreferenceControllerTest.java
@@ -15,8 +15,6 @@
  */
 package com.android.settings.location;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.argThat;
@@ -24,7 +22,6 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -36,7 +33,6 @@
 import android.support.v7.preference.PreferenceScreen;
 import android.text.TextUtils;
 import android.util.FeatureFlagUtils;
-
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.TestConfig;
@@ -48,19 +44,19 @@
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.location.RecentLocationApps;
 import com.android.settingslib.location.RecentLocationApps.Request;
-
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentMatcher;
+import org.mockito.InOrder;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.ArrayList;
-import java.util.List;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class RecentLocationRequestPreferenceControllerTest {
@@ -111,7 +107,7 @@
 
     @Test
     public void updateState_noRecentRequest_shouldRemoveAllAndAddBanner() {
-        doReturn(new ArrayList<>()).when(mRecentLocationApps).getAppList();
+        doReturn(new ArrayList<>()).when(mRecentLocationApps).getAppListSorted();
         mController.displayPreference(mScreen);
 
         mController.updateState(mCategory);
@@ -128,18 +124,25 @@
         final Request req2 = mock(Request.class);
         requests.add(req1);
         requests.add(req2);
-        doReturn(requests).when(mRecentLocationApps).getAppList();
-        final String title = "testTitle";
-        final AppPreference preference = mock(AppPreference.class);
-        when(preference.getTitle()).thenReturn(title);
-        doReturn(preference).when(mController)
-                .createAppPreference(any(Context.class), any(Request.class));
+        doReturn(requests).when(mRecentLocationApps).getAppListSorted();
+        final String title1 = "testTitle1";
+        final String title2 = "testTitle2";
+        final AppPreference preference1 = mock(AppPreference.class);
+        final AppPreference preference2 = mock(AppPreference.class);
+        when(preference1.getTitle()).thenReturn(title1);
+        when(preference2.getTitle()).thenReturn(title2);
+        doReturn(preference1).when(mController)
+                .createAppPreference(any(Context.class), eq(req1));
+        doReturn(preference2).when(mController)
+                .createAppPreference(any(Context.class), eq(req2));
         mController.displayPreference(mScreen);
-
         mController.updateState(mCategory);
 
         verify(mCategory).removeAll();
-        verify(mCategory, times(2)).addPreference(argThat(titleMatches(title)));
+        // Verifies two preferences are added in original order
+        InOrder inOrder = Mockito.inOrder(mCategory);
+        inOrder.verify(mCategory).addPreference(argThat(titleMatches(title1)));
+        inOrder.verify(mCategory).addPreference(argThat(titleMatches(title2)));
     }
 
     @Test
@@ -162,7 +165,7 @@
         final List<RecentLocationApps.Request> requests = new ArrayList<>();
         final Request request = mock(Request.class);
         requests.add(request);
-        doReturn(requests).when(mRecentLocationApps).getAppList();
+        doReturn(requests).when(mRecentLocationApps).getAppListSorted();
         final AppPreference preference = new AppPreference(mContext);
         doReturn(preference).when(mController).createAppPreference(any(Context.class));
         mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/network/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/WifiCallingPreferenceControllerTest.java
deleted file mode 100644
index 4c2c03c..0000000
--- a/tests/robotests/src/com/android/settings/network/WifiCallingPreferenceControllerTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.support.v7.preference.Preference;
-
-import com.android.ims.ImsManager;
-import com.android.settings.TestConfig;
-import com.android.settings.network.WifiCallingPreferenceControllerTest.ShadowImsManager;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.After;
-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 org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH,
-        sdk = TestConfig.SDK_VERSION,
-        shadows = {ShadowImsManager.class})
-public class WifiCallingPreferenceControllerTest {
-
-    @Mock
-    private Preference mPreference;
-
-    private Context mContext;
-    private WifiCallingPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        MockitoAnnotations.initMocks(this);
-
-        mController = new WifiCallingPreferenceController(mContext);
-    }
-
-    @After
-    public void teardown() {
-        ShadowImsManager.reset();
-    }
-
-    @Test
-    public void isAvailable_platformEnabledAndProvisioned_shouldReturnTrue() {
-        ShadowImsManager.wfcProvisioned = true;
-        ShadowImsManager.wfcEnabledByPlatform = true;
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void updateState_shouldUpdatePreferenceSummary() {
-        mController.updateState(mPreference);
-
-        verify(mPreference).setSummary(anyInt());
-    }
-
-    @Implements(ImsManager.class)
-    public static class ShadowImsManager {
-
-        public static boolean wfcEnabledByPlatform;
-        public static boolean wfcProvisioned;
-
-        public static void reset() {
-            wfcEnabledByPlatform = false;
-            wfcProvisioned = false;
-        }
-
-        @Implementation
-        public static boolean isWfcEnabledByPlatform(Context context) {
-            return wfcEnabledByPlatform;
-        }
-
-        @Implementation
-        public static boolean isWfcProvisionedOnDevice(Context context) {
-            return wfcProvisioned;
-        }
-    }
-
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java
new file mode 100644
index 0000000..3f820c3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.wifi.tether;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class WifiTetherAutoOffPreferenceControllerTest {
+    private static final String KEY_PREF = "wifi_tether_auto_off";
+    private static final int ON = 1;
+    private static final int OFF = 0;
+    private Context mContext;
+    private WifiTetherAutoOffPreferenceController mController;
+    private SwitchPreference mSwitchPreference;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mController = new WifiTetherAutoOffPreferenceController(mContext, KEY_PREF);
+        mSwitchPreference = new SwitchPreference(mContext);
+    }
+
+    @Test
+    public void testOnPreferenceChange_toggleOn_settingsOn() {
+        mController.onPreferenceChange(null, true);
+
+        assertThat(getAutoOffSetting()).isEqualTo(ON);
+    }
+
+    @Test
+    public void testOnPreferenceChange_toggleOff_settingsOff() {
+        mController.onPreferenceChange(null, false);
+
+        assertThat(getAutoOffSetting()).isEqualTo(OFF);
+    }
+
+    @Test
+    public void testUpdateState_settingsOn_toggleOn() {
+        setAutoOffSetting(ON);
+
+        mController.updateState(mSwitchPreference);
+
+        assertThat(mSwitchPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_settingsOff_toggleOff() {
+        setAutoOffSetting(OFF);
+
+        mController.updateState(mSwitchPreference);
+
+        assertThat(mSwitchPreference.isChecked()).isFalse();
+    }
+
+    private int getAutoOffSetting() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SOFT_AP_TIMEOUT_ENABLED, OFF);
+    }
+
+    private void setAutoOffSetting(int config) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SOFT_AP_TIMEOUT_ENABLED, config);
+    }
+}