Merge "[LE unicast] Disable the "phone calls" when LE is enabled"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 019ac70..e7f9990 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -608,8 +608,10 @@
     <string name="zone_info_exemplar_location_and_offset"><xliff:g id="exemplar_location" example="Los Angeles">%1$s</xliff:g> (<xliff:g id="offset" example="GMT-08:00">%2$s</xliff:g>)</string>
     <!-- Label describing a time zone offset and name[CHAR LIMIT=NONE] -->
     <string name="zone_info_offset_and_name"><xliff:g id="time_type" example="Pacific Time">%2$s</xliff:g> (<xliff:g id="offset" example="GMT-08:00">%1$s</xliff:g>)</string>
-    <!-- Label describing a time zone and changes to DST or standard time [CHAR LIMIT=NONE] -->
-    <string name="zone_info_footer">Uses <xliff:g id="offset_and_name" example="Pacific Time (GMT-08:00)">%1$s</xliff:g>. <xliff:g id="dst_time_type" example="Pacific Daylight Time">%2$s</xliff:g> starts on <xliff:g id="transition_date" example="Mar 11 2018">%3$s</xliff:g>.</string>
+    <!-- Label describing a time zone and a follow-up sentence [CHAR LIMIT=NONE] -->
+    <string name="zone_info_footer_first_sentence">Uses <xliff:g id="offset_and_name" example="Pacific Time (GMT-08:00)">%1$s</xliff:g>. <xliff:g id="second_sentence" example="Pacific Daylight Time starts on Mar 11 2018.">%2$s</xliff:g></string>
+    <!-- Label describing the upcoming daylight savings time change [CHAR LIMIT=NONE] -->
+    <string name="zone_info_footer_second_sentence"><xliff:g id="dst_time_type" example="Pacific Daylight Time">%1$s</xliff:g> starts on <xliff:g id="transition_date" example="Mar 11 2018">%2$s</xliff:g>.</string>
     <!-- Label describing a time zone without DST [CHAR LIMIT=NONE] -->
     <string name="zone_info_footer_no_dst">Uses <xliff:g id="offset_and_name" example="GMT-08:00 Pacific Time">%1$s</xliff:g>. No daylight savings time.</string>
     <!-- Describes the time type "daylight savings time" (used in zone_change_to_from_dst, when no zone specific name is available) -->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 0d03149..d009222 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -292,7 +292,7 @@
             android:title="@string/tethering_hardware_offload"
             android:summary="@string/tethering_hardware_offload_summary" />
 
-        <com.android.settingslib.RestrictedSwitchPreference
+        <com.android.settingslib.RestrictedPreference
             android:key="default_usb_configuration"
             android:fragment="com.android.settings.connecteddevice.usb.UsbDefaultFragment"
             android:title="@string/usb_default_label"/>
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
index 9e36247..650267a 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
@@ -55,6 +55,7 @@
     private BluetoothPairingController mPairingController;
     private BluetoothPairingDialog mPairingDialogActivity;
     private EditText mPairingView;
+    private boolean mPositiveClicked = false;
     /**
      * The interface we expect a listener to implement. Typically this should be done by
      * the controller.
@@ -83,6 +84,14 @@
     }
 
     @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (!mPositiveClicked) {
+            mPairingController.onCancel();
+        }
+    }
+
+    @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
     }
 
@@ -104,6 +113,7 @@
     @Override
     public void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_POSITIVE) {
+            mPositiveClicked = true;
             mPairingController.onDialogPositiveClick(this);
         } else if (which == DialogInterface.BUTTON_NEGATIVE) {
             mPairingController.onDialogNegativeClick(this);
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 6beb3d8..4ee6530 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -37,7 +37,6 @@
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.View;
@@ -49,6 +48,7 @@
 import android.widget.Spinner;
 
 import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
 import androidx.loader.app.LoaderManager.LoaderCallbacks;
 import androidx.loader.content.Loader;
 import androidx.preference.Preference;
@@ -501,6 +501,17 @@
                         + cycle.end + "]");
             }
 
+            // Avoid from updating UI after #onStop.
+            if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
+                return;
+            }
+
+            // Avoid from updating UI when async query still on-going.
+            // This could happen when a request from #onMobileDataEnabledChange.
+            if (mCycleData == null) {
+                return;
+            }
+
             // update chart to show selected cycle, and update detail data
             // to match updated sweep bounds.
             mChart.setNetworkCycleData(mCycleData.get(position));
diff --git a/src/com/android/settings/datetime/timezone/RegionPreferenceController.java b/src/com/android/settings/datetime/timezone/RegionPreferenceController.java
index 53959a6..c4b47b9 100644
--- a/src/com/android/settings/datetime/timezone/RegionPreferenceController.java
+++ b/src/com/android/settings/datetime/timezone/RegionPreferenceController.java
@@ -15,6 +15,8 @@
  */
 package com.android.settings.datetime.timezone;
 
+import static com.android.settingslib.datetime.ZoneGetter.capitalizeForStandaloneDisplay;
+
 import android.content.Context;
 import android.icu.text.LocaleDisplayNames;
 
@@ -23,19 +25,21 @@
 public class RegionPreferenceController extends BaseTimeZonePreferenceController {
     private static final String PREFERENCE_KEY = "region";
 
+    private final Locale mLocale;
     private final LocaleDisplayNames mLocaleDisplayNames;
     private String mRegionId = "";
 
     public RegionPreferenceController(Context context) {
         super(context, PREFERENCE_KEY);
         Locale locale = context.getResources().getConfiguration().getLocales().get(0);
+        mLocale = locale;
         mLocaleDisplayNames = LocaleDisplayNames.getInstance(locale);
-
     }
 
     @Override
     public CharSequence getSummary() {
-        return mLocaleDisplayNames.regionDisplayName(mRegionId);
+        return capitalizeForStandaloneDisplay(mLocale,
+                mLocaleDisplayNames.regionDisplayName(mRegionId));
     }
 
     public void setRegionId(String regionId) {
diff --git a/src/com/android/settings/datetime/timezone/RegionSearchPicker.java b/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
index 85d5d70..3977aa9 100644
--- a/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
+++ b/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.datetime.timezone;
 
+import static com.android.settingslib.datetime.ZoneGetter.capitalizeForStandaloneDisplay;
+
 import android.app.Activity;
 import android.app.settings.SettingsEnums;
 import android.content.Intent;
@@ -116,7 +118,8 @@
         final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
         long i = 0;
         for (String regionId : regionIds) {
-            String name = localeDisplayNames.regionDisplayName(regionId);
+            String name = capitalizeForStandaloneDisplay(
+                    mLocale, localeDisplayNames.regionDisplayName(regionId));
             items.add(new RegionItem(i++, regionId, name));
         }
         return new ArrayList<>(items);
diff --git a/src/com/android/settings/datetime/timezone/RegionZonePicker.java b/src/com/android/settings/datetime/timezone/RegionZonePicker.java
index 7f988cd..1bc68a1 100644
--- a/src/com/android/settings/datetime/timezone/RegionZonePicker.java
+++ b/src/com/android/settings/datetime/timezone/RegionZonePicker.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.datetime.timezone;
 
+import static com.android.settingslib.datetime.ZoneGetter.capitalizeForStandaloneDisplay;
+
 import android.app.settings.SettingsEnums;
 import android.content.Intent;
 import android.icu.text.Collator;
@@ -65,7 +67,8 @@
         final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
         final String regionId =
                 getArguments() == null ? null : getArguments().getString(EXTRA_REGION_ID);
-        mRegionName = regionId == null ? null : localeDisplayNames.regionDisplayName(regionId);
+        mRegionName = regionId == null ? null : capitalizeForStandaloneDisplay(
+                mLocale, localeDisplayNames.regionDisplayName(regionId));
     }
 
     @Override
diff --git a/src/com/android/settings/datetime/timezone/SpannableUtil.java b/src/com/android/settings/datetime/timezone/SpannableUtil.java
index 49c3e7d..ed28f64 100644
--- a/src/com/android/settings/datetime/timezone/SpannableUtil.java
+++ b/src/com/android/settings/datetime/timezone/SpannableUtil.java
@@ -18,14 +18,72 @@
 
 import android.annotation.StringRes;
 import android.content.res.Resources;
+import android.icu.text.CaseMap;
+import android.icu.text.Edits;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
+import android.util.Log;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formattable;
+import java.util.FormattableFlags;
 import java.util.Formatter;
+import java.util.List;
 import java.util.Locale;
 
 
 public class SpannableUtil {
+    private static final String TAG = "SpannableUtil";
+
+    private static class SpannableFormattable implements Formattable {
+
+        private final Spannable mSpannable;
+
+        private SpannableFormattable(Spannable spannable) {
+            this.mSpannable = spannable;
+        }
+
+        @Override
+        public void formatTo(Formatter formatter, int flags, int width, int precision) {
+            CharSequence s = handlePrecision(mSpannable, precision);
+            s = handleWidth(s, width, (flags & FormattableFlags.LEFT_JUSTIFY) != 0);
+            try {
+                formatter.out().append(s);
+            } catch (IOException e) {
+                // The error should never occur because formatter.out() returns
+                // SpannableStringBuilder which doesn't throw IOException.
+                Log.e(TAG, "error in SpannableFormattable", e);
+            }
+        }
+
+        private static CharSequence handlePrecision(CharSequence s, int precision) {
+            if (precision != -1 && precision < s.length()) {
+                return s.subSequence(0, precision);
+            }
+            return s;
+        }
+
+        private static CharSequence handleWidth(CharSequence s, int width, boolean isLeftJustify) {
+            if (width == -1) {
+                return s;
+            }
+            int diff = width - s.length();
+            if (diff <= 0) {
+                return s;
+            }
+            SpannableStringBuilder sb = new SpannableStringBuilder();
+            if (!isLeftJustify) {
+                sb.append(" ".repeat(diff));
+            }
+            sb.append(s);
+            if (isLeftJustify) {
+                sb.append(" ".repeat(diff));
+            }
+            return sb;
+        }
+    }
 
     /**
      * {@class Resources} has no method to format string resource with {@class Spannable} a
@@ -35,7 +93,56 @@
             Object... args) {
         final Locale locale = res.getConfiguration().getLocales().get(0);
         final SpannableStringBuilder builder = new SpannableStringBuilder();
+        // Formatter converts CharSequence to String by calling toString() if an arg isn't
+        // Formattable. Wrap Spannable by SpannableFormattable to preserve Spannable objects.
+        for (int i = 0; i < args.length; i++) {
+            if (args[i] instanceof Spannable) {
+                args[i] = new SpannableFormattable((Spannable) args[i]);
+            }
+        }
         new Formatter(builder, locale).format(res.getString(resId), args);
         return builder;
     }
+
+    private static final CaseMap.Title TITLE_CASE_MAP =
+            CaseMap.toTitle().sentences().noLowercase();
+
+    /**
+     * Titlecasing {@link CharSequence} and {@link Spannable} by using {@link CaseMap.Title}.
+     */
+    public static CharSequence titleCaseSentences(Locale locale, CharSequence src) {
+        if (src instanceof Spannable) {
+            return applyCaseMapToSpannable(locale, TITLE_CASE_MAP, (Spannable) src);
+        } else {
+            return TITLE_CASE_MAP.apply(locale, null, src);
+        }
+    }
+
+    private static Spannable applyCaseMapToSpannable(Locale locale, CaseMap.Title caseMap,
+            Spannable src) {
+        Edits edits = new Edits();
+        SpannableStringBuilder dest = new SpannableStringBuilder();
+        caseMap.apply(locale, null, src, dest, edits);
+        if (!edits.hasChanges()) {
+            return src;
+        }
+        Edits.Iterator iterator = edits.getCoarseChangesIterator();
+        List<int[]> changes = new ArrayList<>();
+        while (iterator.next()) {
+            int[] change = new int[] {
+                iterator.sourceIndex(),       // 0
+                iterator.oldLength(),         // 1
+                iterator.destinationIndex(),  // 2
+                iterator.newLength(),         // 3
+            };
+            changes.add(change);
+        }
+        // Replacement starts from the end to avoid shifting the source index during replacement
+        Collections.reverse(changes);
+        SpannableStringBuilder result = new SpannableStringBuilder(src);
+        for (int[] c : changes) {
+            result.replace(c[0], c[0] + c[1], dest, c[2], c[2] + c[3]);
+        }
+        return result;
+    }
 }
diff --git a/src/com/android/settings/datetime/timezone/TimeZoneInfo.java b/src/com/android/settings/datetime/timezone/TimeZoneInfo.java
index f9e819c..5076f72 100644
--- a/src/com/android/settings/datetime/timezone/TimeZoneInfo.java
+++ b/src/com/android/settings/datetime/timezone/TimeZoneInfo.java
@@ -15,6 +15,8 @@
  */
 package com.android.settings.datetime.timezone;
 
+import static com.android.settingslib.datetime.ZoneGetter.capitalizeForStandaloneDisplay;
+
 import android.icu.text.TimeZoneFormat;
 import android.icu.text.TimeZoneNames;
 import android.icu.util.TimeZone;
@@ -152,19 +154,29 @@
             String canonicalZoneId = getCanonicalZoneId(timeZone);
             final TimeZoneNames timeZoneNames = mTimeZoneFormat.getTimeZoneNames();
             final java.util.TimeZone javaTimeZone = toJavaTimeZone(canonicalZoneId);
-            final CharSequence gmtOffset = ZoneGetter.getGmtOffsetText(mTimeZoneFormat, mLocale,
-                javaTimeZone, mNow);
+            final CharSequence gmtOffset =
+                    ZoneGetter.getGmtOffsetText(mTimeZoneFormat, mLocale, javaTimeZone, mNow);
             return new TimeZoneInfo.Builder(timeZone)
-                    .setGenericName(timeZoneNames.getDisplayName(canonicalZoneId,
-                            TimeZoneNames.NameType.LONG_GENERIC, mNow.getTime()))
-                    .setStandardName(timeZoneNames.getDisplayName(canonicalZoneId,
-                            TimeZoneNames.NameType.LONG_STANDARD, mNow.getTime()))
-                    .setDaylightName(timeZoneNames.getDisplayName(canonicalZoneId,
-                            TimeZoneNames.NameType.LONG_DAYLIGHT, mNow.getTime()))
-                    .setExemplarLocation(timeZoneNames.getExemplarLocationName(canonicalZoneId))
+                    .setGenericName(getTzNameForListDisplay(mLocale, timeZoneNames,
+                            canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_GENERIC))
+                    .setStandardName(getTzNameForListDisplay(mLocale, timeZoneNames,
+                            canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_STANDARD))
+                    .setDaylightName(getTzNameForListDisplay(mLocale, timeZoneNames,
+                            canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_DAYLIGHT))
+                    .setExemplarLocation(capitalizeForStandaloneDisplay(mLocale,
+                            timeZoneNames.getExemplarLocationName(canonicalZoneId)))
                     .setGmtOffset(gmtOffset)
                     .build();
         }
+
+        private static String getTzNameForListDisplay(
+                Locale locale, TimeZoneNames timeZoneNames, String canonicalZoneId, Date now,
+                TimeZoneNames.NameType nameType) {
+            long nowEpochMillis = now.getTime();
+            String displayName = timeZoneNames.getDisplayName(
+                    canonicalZoneId, nameType, nowEpochMillis);
+            return capitalizeForStandaloneDisplay(locale, displayName);
+        }
     }
 
     /* package-private */ java.util.TimeZone getJavaTimeZone() {
diff --git a/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java b/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java
index c6ac328..fb2392b 100644
--- a/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java
+++ b/src/com/android/settings/datetime/timezone/TimeZoneInfoPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.datetime.timezone;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
 import android.icu.text.SimpleDateFormat;
@@ -32,6 +33,7 @@
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
 import java.util.Date;
+import java.util.Locale;
 
 public class TimeZoneInfoPreferenceController extends BasePreferenceController {
 
@@ -82,14 +84,15 @@
     private CharSequence formatInfo(TimeZoneInfo item) {
         final CharSequence offsetAndName = formatOffsetAndName(item);
         final TimeZone timeZone = item.getTimeZone();
-        if (!timeZone.observesDaylightTime()) {
-            return mContext.getString(R.string.zone_info_footer_no_dst, offsetAndName);
+        ZoneOffsetTransition nextDstTransition = null;
+        if (timeZone.observesDaylightTime()) {
+            nextDstTransition = findNextDstTransition(item);
+        }
+        if (nextDstTransition == null || !timeZone.observesDaylightTime()) {
+            return SpannableUtil.getResourcesText(mContext.getResources(),
+                R.string.zone_info_footer_no_dst, offsetAndName);
         }
 
-        final ZoneOffsetTransition nextDstTransition = findNextDstTransition(item);
-        if (nextDstTransition == null) { // No future transition
-            return mContext.getString(R.string.zone_info_footer_no_dst, offsetAndName);
-        }
         final boolean toDst = getDSTSavings(timeZone, nextDstTransition.getInstant()) != 0;
         String timeType = toDst ? item.getDaylightName() : item.getStandardName();
         if (timeType == null) {
@@ -103,8 +106,24 @@
         final Calendar transitionTime = Calendar.getInstance(timeZone);
         transitionTime.setTimeInMillis(nextDstTransition.getInstant().toEpochMilli());
         final String date = mDateFormat.format(transitionTime);
-        return SpannableUtil.getResourcesText(mContext.getResources(),
-                R.string.zone_info_footer, offsetAndName, timeType, date);
+        return createFooterString(offsetAndName, timeType, date);
+    }
+
+    /**
+     * @param offsetAndName {@Spannable} styled text information should be preserved. See
+     * {@link #formatInfo} and {@link com.android.settingslib.datetime.ZoneGetter#getGmtOffsetText}.
+     *
+     */
+    private CharSequence createFooterString(CharSequence offsetAndName, String timeType,
+            String date) {
+        Resources res = mContext.getResources();
+        Locale locale = res.getConfiguration().getLocales().get(0);
+        CharSequence secondSentence = SpannableUtil.titleCaseSentences(locale,
+                SpannableUtil.getResourcesText(res, R.string.zone_info_footer_second_sentence,
+                timeType, date));
+
+        return SpannableUtil.titleCaseSentences(locale, SpannableUtil.getResourcesText(res,
+            R.string.zone_info_footer_first_sentence, offsetAndName, secondSentence));
     }
 
     private ZoneOffsetTransition findNextDstTransition(TimeZoneInfo timeZoneInfo) {
diff --git a/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java b/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
index be7704f..7c3d3b1 100644
--- a/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
+++ b/src/com/android/settings/development/DefaultUsbConfigurationPreferenceController.java
@@ -24,7 +24,7 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
 
 public class DefaultUsbConfigurationPreferenceController extends
@@ -32,7 +32,7 @@
 
     private static final String PREFERENCE_KEY = "default_usb_configuration";
 
-    private RestrictedSwitchPreference mPreference;
+    private RestrictedPreference mPreference;
 
     public DefaultUsbConfigurationPreferenceController(Context context) {
         super(context);
diff --git a/src/com/android/settings/enterprise/OWNERS b/src/com/android/settings/enterprise/OWNERS
index 5811673..c675d26 100644
--- a/src/com/android/settings/enterprise/OWNERS
+++ b/src/com/android/settings/enterprise/OWNERS
@@ -1,7 +1,4 @@
 # Default reviewers for this and subdirectories.
-sandness@google.com
-tonymak@google.com
-yuemingw@google.com
-arangelov@google.com
+file:platform/frameworks/base:/core/java/android/app/admin/WorkDeviceExperience_OWNERS
 
-# Emergency approvers in case the above are not available
\ No newline at end of file
+# Emergency approvers in case the above are not available
diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java
index 07d5714..ed6f9ed 100644
--- a/src/com/android/settings/network/PrivateDnsPreferenceController.java
+++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java
@@ -85,9 +85,12 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)
-                ? AVAILABLE
-                : UNSUPPORTED_ON_DEVICE;
+        if (!mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+        final UserManager userManager = mContext.getSystemService(UserManager.class);
+        if (userManager.isGuestUser()) return DISABLED_FOR_USER;
+        return AVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/security/SimLockPreferenceController.java b/src/com/android/settings/security/SimLockPreferenceController.java
index 3b85888..e570e5d 100644
--- a/src/com/android/settings/security/SimLockPreferenceController.java
+++ b/src/com/android/settings/security/SimLockPreferenceController.java
@@ -95,7 +95,8 @@
         for (SubscriptionInfo subInfo : subInfoList) {
             final int simState = mTelephonyManager.getSimState(subInfo.getSimSlotIndex());
             if ((simState != TelephonyManager.SIM_STATE_ABSENT)
-                    && (simState != TelephonyManager.SIM_STATE_UNKNOWN)) {
+                    && (simState != TelephonyManager.SIM_STATE_UNKNOWN)
+                    && (simState != TelephonyManager.SIM_STATE_PERM_DISABLED)) {
                 return true;
             }
         }
diff --git a/src/com/android/settings/wfd/WifiDisplayPreferenceController.java b/src/com/android/settings/wfd/WifiDisplayPreferenceController.java
index a83a56b..b15396b 100644
--- a/src/com/android/settings/wfd/WifiDisplayPreferenceController.java
+++ b/src/com/android/settings/wfd/WifiDisplayPreferenceController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteInfo;
+import android.text.TextUtils;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
@@ -87,7 +88,12 @@
             final MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
             if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)
                     && route.isSelected() && !route.isConnecting()) {
-                summary = mContext.getString(R.string.wifi_display_status_connected);
+                CharSequence status = route.getStatus();
+                if (!TextUtils.isEmpty(status)) {
+                    summary = status;
+                } else {
+                    summary = mContext.getString(R.string.wifi_display_status_connected);
+                }
                 break;
             }
         }
diff --git a/src/com/android/settings/wfd/WifiDisplaySettings.java b/src/com/android/settings/wfd/WifiDisplaySettings.java
index 19b6c54..8562e5f 100755
--- a/src/com/android/settings/wfd/WifiDisplaySettings.java
+++ b/src/com/android/settings/wfd/WifiDisplaySettings.java
@@ -38,6 +38,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.TypedValue;
 import android.view.Menu;
@@ -678,7 +679,12 @@
                 if (route.isConnecting()) {
                     setSummary(R.string.wifi_display_status_connecting);
                 } else {
-                    setSummary(R.string.wifi_display_status_connected);
+                    CharSequence status = route.getStatus();
+                    if (!TextUtils.isEmpty(status)) {
+                        setSummary(status);
+                    } else {
+                        setSummary(R.string.wifi_display_status_connected);
+                    }
                 }
             } else {
                 if (isEnabled()) {
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java
index b9a3056..04528d0 100644
--- a/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/SpannableUtilTest.java
@@ -18,23 +18,91 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.icu.text.TimeZoneFormat;
 import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 
 import com.android.settings.R;
+import com.android.settingslib.datetime.ZoneGetter;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
 @RunWith(RobolectricTestRunner.class)
 public class SpannableUtilTest {
 
     @Test
-    public void testFormat() {
+    public void testGetResourceText() {
+        CharSequence gmtString = getGmtString("GMT+00:00");
+
         Spannable spannable = SpannableUtil.getResourcesText(
                 RuntimeEnvironment.application.getResources(), R.string.zone_info_offset_and_name,
-                "GMT+00:00", "UTC");
+                gmtString, "UTC");
         assertThat(spannable.toString()).isEqualTo("UTC (GMT+00:00)");
+
+        // Verify that the spans are kept.
+        Object[] spans = ((Spannable) gmtString).getSpans(0, gmtString.length(), Object.class);
+        Object[] newSpans = spannable.getSpans(0, spannable.length(), Object.class);
+        assertThat(newSpans.length).isEqualTo(spans.length);
+        assertThat(newSpans).isEqualTo(spans);
+    }
+
+    private static CharSequence getGmtString(String tzId) {
+        Locale locale = Locale.US;
+        TimeZoneFormat timeZoneFormat = TimeZoneFormat.getInstance(locale);
+        TimeZone gmtZone = TimeZone.getTimeZone(tzId);
+        Date date = new Date(0);
+        return ZoneGetter.getGmtOffsetText(timeZoneFormat, locale, gmtZone, date);
+    }
+    /**
+     * Verify the assumption on the GMT string used in {@link #testGetResourceText()}
+     */
+    @Test
+    public void testGetGmtString() {
+        // Create a GMT string and verify the assumptions
+        CharSequence gmtString = getGmtString("GMT+00:00");
+        assertThat(gmtString.toString()).isEqualTo("GMT+00:00");
+        assertThat(gmtString).isInstanceOf(Spannable.class);
+        Object[] spans = ((Spannable) gmtString).getSpans(0, gmtString.length(), Object.class);
+        assertThat(spans).isNotEmpty();
+
+        assertThat(getGmtString("GMT-08:00").toString()).isEqualTo("GMT-08:00");
+    }
+
+    @Test
+    public void testTitleCaseSentences_enUS() {
+        Locale locale = Locale.US;
+        CharSequence titleCasedFirstSentence = SpannableUtil.titleCaseSentences(locale,
+                "pacific Daylight Time starts on Mar 11 2018.");
+        assertThat(titleCasedFirstSentence.toString())
+            .isEqualTo("Pacific Daylight Time starts on Mar 11 2018.");
+
+        SpannableStringBuilder sb = new SpannableStringBuilder()
+                .append("uses ")
+                .append("Pacific Time (")
+                .append(getGmtString("GMT-08:00"))
+                .append("). ")
+                .append(titleCasedFirstSentence);
+
+        assertThat(sb.toString()).isEqualTo(
+                "uses Pacific Time (GMT-08:00). Pacific Daylight Time starts on Mar 11 2018.");
+
+        Object[] spans = sb.getSpans(0, sb.length(), Object.class);
+        assertThat(spans).isNotEmpty();
+
+        CharSequence titledOutput = SpannableUtil.titleCaseSentences(Locale.US, sb);
+        assertThat(titledOutput.toString()).isEqualTo(
+                "Uses Pacific Time (GMT-08:00). Pacific Daylight Time starts on Mar 11 2018.");
+        assertThat(titledOutput).isInstanceOf(Spannable.class);
+        Object[] newSpans = ((Spannable) titledOutput).getSpans(0, titledOutput.length(),
+                Object.class);
+        assertThat(newSpans.length).isEqualTo(spans.length);
+        assertThat(newSpans).isEqualTo(spans);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
index c9b13e27..a386473 100644
--- a/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/DefaultUsbConfigurationPreferenceControllerTest.java
@@ -32,7 +32,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.RestrictedPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +48,7 @@
     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("test", "test");
 
     @Mock
-    private RestrictedSwitchPreference mPreference;
+    private RestrictedPreference mPreference;
     @Mock
     private PreferenceScreen mPreferenceScreen;
     @Mock
diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
index e31d959..057b6cb 100644
--- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
@@ -26,6 +26,7 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -35,6 +36,7 @@
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
@@ -109,6 +111,8 @@
     private Network mNetwork;
     @Mock
     private Preference mPreference;
+    @Mock
+    private UserManager mUserManager;
     @Captor
     private ArgumentCaptor<NetworkCallback> mCallbackCaptor;
     private PrivateDnsPreferenceController mController;
@@ -127,6 +131,7 @@
         mShadowContentResolver = Shadow.extract(mContentResolver);
         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(mConnectivityManager);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
         doNothing().when(mConnectivityManager).registerDefaultNetworkCallback(
                 mCallbackCaptor.capture(), nullable(Handler.class));
 
@@ -174,6 +179,12 @@
     }
 
     @Test
+    public void getAvailabilityStatus_disabledForGuestUser() {
+        doReturn(true).when(mUserManager).isGuestUser();
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
+    }
+
+    @Test
     public void goThroughLifecycle_shouldRegisterUnregisterSettingsObserver() {
         mLifecycle.handleLifecycleEvent(ON_START);
         verify(mContext, atLeastOnce()).getContentResolver();