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();