Merge "Update tests due to new platform API intruducing ambibuity"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index a88d6f6..b2d5468 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -72,6 +72,8 @@
<attr name="platform_slice" format="boolean" />
<!-- Whether or not dynamic summary text from PreferenceController is allowed when creating slice object, by default it's false. -->
<attr name="allowDynamicSummaryInSlice" format="boolean" />
+ <!-- customized subtitle if it's an unavailable slice -->
+ <attr name="unavailableSliceSubtitle" format="string" />
</declare-styleable>
<declare-styleable name="PreferenceScreen">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d1c5dfb..9f5b562 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -927,10 +927,12 @@
<string name="security_settings_face_settings_require_attention">Eyes open to unlock</string>
<!-- Text shown on the details of a toggle which disables/enables face authentication, depending if the user's eyes are open. [CHAR LIMIT=70] -->
<string name="security_settings_face_settings_require_attention_details">When using face authentication, your eyes must be open</string>
+ <!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=50] -->
+ <string name="security_settings_face_settings_require_confirmation">Always require confirmation</string>
+ <!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=70] -->
+ <string name="security_settings_face_settings_require_confirmation_details">When authenticating in apps, always require confirmation</string>
<!-- Button text in face settings which removes the user's faces from the device [CHAR LIMIT=20] -->
<string name="security_settings_face_settings_remove_face_data">Remove face data</string>
- <!-- Text shown in face settings allowing the user to update/improve the enrolled face. This brings the user back to the enrollment flow. [CHAR LIMIT=30] -->
- <string name="security_settings_face_settings_improve_face">Improve your face data</string>
<!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_footer">Your face can be used to unlock your device and access apps.
<annotation id="url">Learn more</annotation></string>
@@ -4689,7 +4691,9 @@
<!-- Title for accessibility preference screen for configuring vibrations. -->
<string name="accessibility_vibration_settings_title">Vibration</string>
<!-- Title for accessibility preference for configuring notification vibrations. -->
- <string name="accessibility_notification_vibration_title">Ring & notification vibration</string>
+ <string name="accessibility_notification_vibration_title">Notification vibration</string>
+ <!-- Title for accessibility preference for configuring ring vibrations. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_ring_vibration_title">Ring vibration</string>
<!-- Title for accessibility preference for configuring touch feedback vibrations. -->
<string name="accessibility_touch_vibration_title">Touch vibration</string>
<!-- Used in the acessibilty service settings to control turning on/off the service entirely -->
@@ -4759,8 +4763,8 @@
<item quantity="other">Very long delay (<xliff:g id="click_delay_label" example="200">%1$d</xliff:g> ms)</item>
</plurals>
- <!-- Summary for vibration settings preference when notification vibration and haptic feedback intensity are set. [CHAR LIMIT=32] -->
- <string name="accessibility_vibration_summary">Ring <xliff:g id="summary_ring" example="Medium">%1$s</xliff:g>, touch <xliff:g id="summary_touch" example="High">%2$s</xliff:g></string>
+ <!-- Summary for vibration settings preference when notification vibration and haptic feedback intensity are set. [CHAR LIMIT=50] -->
+ <string name="accessibility_vibration_summary">Ring <xliff:g id="summary_ring" example="Medium">%1$s</xliff:g>, notification <xliff:g id="summary_notification" example="Low">%2$s</xliff:g>, touch <xliff:g id="summary_touch" example="High">%3$s</xliff:g></string>
<!-- Summary for vibration settings preference when ring & notification are set to off-->
<string name="accessibility_vibration_summary_off">Ring & notification set to off</string>
@@ -7054,8 +7058,10 @@
<!-- List of synonyms for touch vibration setting (where you get a haptic response for touching things on the screen), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_touch_vibration">haptics, vibrate, screen, sensitivity</string>
- <!-- List of synonyms for ring and notification vibration setting (changes whether your phone vibrates when it rings), used to match in settings search [CHAR LIMIT=NONE] -->
- <string name="keywords_ring_vibration">haptics, vibrate, phone, call, sensitivity</string>
+ <!-- List of synonyms for ring vibration setting (changes whether your phone vibrates when it rings), used to match in settings search [CHAR LIMIT=NONE] -->
+ <string name="keywords_ring_vibration">haptics, vibrate, phone, call, sensitivity, ring</string>
+ <!-- List of synonyms for notification vibration setting (changes whether your phone vibrates when it shows a notification), used to match in settings search [CHAR LIMIT=NONE] -->
+ <string name="keywords_notification_vibration">haptics, vibrate, sensitivity</string>
<!-- NFC Wi-Fi pairing/setup strings-->
@@ -10063,23 +10069,23 @@
<!-- UI debug setting: ANGLE enabled app has been set [CHAR LIMIT=NONE] -->
<string name="angle_enabled_app_set">ANGLE enabled application: <xliff:g id="app_name" example="com.company.app">%1$s</xliff:g></string>
- <!-- Title for Game Update Packages dashboard where developers can configure apps to use GUP or not [CHAR LIMIT=50] -->
- <string name="gup_dashboard_title">Game Update Packages Preferences</string>
- <!-- Summary for Game Update Packages dashboard [CHAR LIMIT=50] -->
- <string name="gup_dashboard_summary">Modify Game Update Packages settings</string>
- <!-- Title for Game Update Packages preference [CHAR LIMIT=50] -->
+ <!-- Title for Game Update Package dashboard where developers can configure apps to use GUP or not [CHAR LIMIT=50] -->
+ <string name="gup_dashboard_title">Game Update Package Preferences</string>
+ <!-- Summary for Game Update Package dashboard [CHAR LIMIT=50] -->
+ <string name="gup_dashboard_summary">Modify Game Update Package settings</string>
+ <!-- Title for Game Update Package preference [CHAR LIMIT=50] -->
<string name="gup_app_preference_title">Select Graphics Driver</string>
- <!-- The default value for Game Update Packages preference [CHAR LIMIT=50] -->
+ <!-- The default value for Game Update Package preference [CHAR LIMIT=50] -->
<string name="gup_app_preference_default">Default</string>
- <!-- The gup value for Game Update Packages preference [CHAR LIMIT=50] -->
- <string name="gup_app_preference_gup">Game Update Packages</string>
- <!-- The native value for Game Update Packages preference [CHAR LIMIT=50] -->
- <string name="gup_app_preference_native">Native Graphics Driver</string>
- <!-- All the values for Game Update Packages preference [CHAR LIMIT=50] -->
+ <!-- The gup value for Game Update Package preference [CHAR LIMIT=50] -->
+ <string name="gup_app_preference_gup">Game Update Package</string>
+ <!-- The system value for Game Update Package preference [CHAR LIMIT=50] -->
+ <string name="gup_app_preference_system">System Graphics Driver</string>
+ <!-- All the values for Game Update Package preference [CHAR LIMIT=50] -->
<string-array name="gup_app_preference_values">
<item>@string/gup_app_preference_default</item>
<item>@string/gup_app_preference_gup</item>
- <item>@string/gup_app_preference_native</item>
+ <item>@string/gup_app_preference_system</item>
</string-array>
<!-- Slices Strings -->
@@ -10198,12 +10204,6 @@
<!-- Homepage bottom menu. Title for display personalized Settings [CHAR LIMIT=30] -->
<string name="homepage_personal_settings">Suggestions</string>
- <!-- Setting Checkbox title whether to enable CBRS data. [CHAR LIMIT=40] -->
- <string name="cbrs_data_switch">CBRS Data</string>
-
- <!-- Title of implications of enabling CBRS Data -->
- <string name="cbrs_data_switch_summary">CBRS Data</string>
-
<!-- Available networks screen, name of button when user wants to select network manually [CHAR LIMIT=60] -->
<string name="choose_network_title">Choose network</string>
<!-- Available networks screen, text when no networks connected [CHAR LIMIT=60] -->
diff --git a/res/xml/accessibility_ring_vibration_settings.xml b/res/xml/accessibility_ring_vibration_settings.xml
new file mode 100644
index 0000000..078f76c
--- /dev/null
+++ b/res/xml/accessibility_ring_vibration_settings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/accessibility_ring_vibration_title" />
diff --git a/res/xml/accessibility_vibration_settings.xml b/res/xml/accessibility_vibration_settings.xml
index b2b3596..dc2b16a 100644
--- a/res/xml/accessibility_vibration_settings.xml
+++ b/res/xml/accessibility_vibration_settings.xml
@@ -22,10 +22,17 @@
android:title="@string/accessibility_vibration_settings_title">
<Preference
+ android:fragment="com.android.settings.accessibility.RingVibrationPreferenceFragment"
+ android:key="ring_vibration_preference_screen"
+ android:title="@string/accessibility_ring_vibration_title"
+ settings:keywords="@string/keywords_ring_vibration"
+ app:controller="com.android.settings.accessibility.RingVibrationIntensityPreferenceController" />
+
+ <Preference
android:fragment="com.android.settings.accessibility.NotificationVibrationPreferenceFragment"
android:key="notification_vibration_preference_screen"
android:title="@string/accessibility_notification_vibration_title"
- settings:keywords="@string/keywords_ring_vibration"
+ settings:keywords="@string/keywords_notification_vibration"
app:controller="com.android.settings.accessibility.NotificationVibrationIntensityPreferenceController" />
<Preference
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 90895f2..cf9fbf9 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -31,7 +31,7 @@
<com.android.settings.slices.SlicePreference
android:key="bt_device_slice"
- settings:controller="com.android.settings.slices.SlicePreferenceController"
+ settings:controller="com.android.settings.slices.BlockingSlicePrefController"
settings:allowDividerBelow="true"
settings:allowDividerAbove="true"/>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index a5e26f6..4cdab33 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -241,11 +241,6 @@
android:title="@string/usb_default_label"/>
<SwitchPreference
- android:key="cbrs_data_switch"
- android:title="@string/cbrs_data_switch"
- android:summary="@string/cbrs_data_switch" />
-
- <SwitchPreference
android:key="bluetooth_show_devices_without_names"
android:title="@string/bluetooth_show_devices_without_names"
android:summary="@string/bluetooth_show_devices_without_names_summary" />
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index c202a6c..f5dde8b 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -47,13 +47,16 @@
<SwitchPreference
android:key="security_settings_face_require_attention"
android:title="@string/security_settings_face_settings_require_attention"
+ android:summary="@string/security_settings_face_settings_require_attention_details"
app:keywords="@string/keywords_face_unlock"
app:controller="com.android.settings.biometrics.face.FaceSettingsAttentionPreferenceController"/>
- <Preference
- android:key="security_settings_face_improve"
- android:title="@string/security_settings_face_settings_improve_face">
- </Preference>
+ <SwitchPreference
+ android:key="security_settings_face_require_confirmation"
+ android:title="@string/security_settings_face_settings_require_confirmation"
+ android:summary="@string/security_settings_face_settings_require_confirmation_details"
+ app:keywords="@string/keywords_face_unlock"
+ app:controller="com.android.settings.biometrics.face.FaceSettingsConfirmPreferenceController"/>
<com.android.settingslib.widget.LayoutPreference
android:key="security_settings_face_delete_faces_container"
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 76be66d..402fa61 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -810,15 +810,30 @@
final Context context = getContext();
final Vibrator vibrator = context.getSystemService(Vibrator.class);
- final int ringIntensity = Settings.System.getInt(context.getContentResolver(),
- Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- vibrator.getDefaultNotificationVibrationIntensity());
+ int ringIntensity = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.RING_VIBRATION_INTENSITY,
+ vibrator.getDefaultRingVibrationIntensity());
+ if (Settings.System.getInt(context.getContentResolver(),
+ Settings.System.VIBRATE_WHEN_RINGING, 0) == 0) {
+ ringIntensity = Vibrator.VIBRATION_INTENSITY_OFF;
+ }
CharSequence ringIntensityString =
VibrationIntensityPreferenceController.getIntensityString(context, ringIntensity);
- final int touchIntensity = Settings.System.getInt(context.getContentResolver(),
+ int notificationIntensity = Settings.System.getInt(context.getContentResolver(),
+ Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
+ vibrator.getDefaultNotificationVibrationIntensity());
+ CharSequence notificationIntensityString =
+ VibrationIntensityPreferenceController.getIntensityString(context,
+ notificationIntensity);
+
+ int touchIntensity = Settings.System.getInt(context.getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_INTENSITY,
vibrator.getDefaultHapticFeedbackIntensity());
+ if (Settings.System.getInt(context.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) {
+ touchIntensity = Vibrator.VIBRATION_INTENSITY_OFF;
+ }
CharSequence touchIntensityString =
VibrationIntensityPreferenceController.getIntensityString(context, touchIntensity);
@@ -826,12 +841,14 @@
mVibrationPreferenceScreen = findPreference(VIBRATION_PREFERENCE_SCREEN);
}
- if (ringIntensity == touchIntensity) {
+ if (ringIntensity == touchIntensity && ringIntensity == notificationIntensity) {
mVibrationPreferenceScreen.setSummary(ringIntensityString);
} else {
mVibrationPreferenceScreen.setSummary(
getString(R.string.accessibility_vibration_summary,
- ringIntensityString, touchIntensityString));
+ ringIntensityString,
+ notificationIntensityString,
+ touchIntensityString));
}
}
diff --git a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java
index 343ebb1..a2142a2 100644
--- a/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/HapticFeedbackIntensityPreferenceController.java
@@ -28,7 +28,8 @@
static final String PREF_KEY = "touch_vibration_preference_screen";
public HapticFeedbackIntensityPreferenceController(Context context) {
- super(context, PREF_KEY, Settings.System.HAPTIC_FEEDBACK_INTENSITY);
+ super(context, PREF_KEY, Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+ Settings.System.HAPTIC_FEEDBACK_ENABLED);
}
@Override
diff --git a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java
index 4aff513..4ace4c6 100644
--- a/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceController.java
@@ -28,7 +28,7 @@
static final String PREF_KEY = "notification_vibration_preference_screen";
public NotificationVibrationIntensityPreferenceController(Context context) {
- super(context, PREF_KEY, Settings.System.NOTIFICATION_VIBRATION_INTENSITY);
+ super(context, PREF_KEY, Settings.System.NOTIFICATION_VIBRATION_INTENSITY, "");
}
@Override
diff --git a/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java
index 6804abc..ba7d51d 100644
--- a/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java
@@ -45,6 +45,11 @@
}
@Override
+ protected String getVibrationEnabledSetting() {
+ return "";
+ }
+
+ @Override
protected int getPreviewVibrationAudioAttributesUsage() {
return AudioAttributes.USAGE_NOTIFICATION;
}
diff --git a/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java
new file mode 100644
index 0000000..818c414
--- /dev/null
+++ b/src/com/android/settings/accessibility/RingVibrationIntensityPreferenceController.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.accessibility;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.annotation.VisibleForTesting;
+
+public class RingVibrationIntensityPreferenceController
+ extends VibrationIntensityPreferenceController {
+
+ @VisibleForTesting
+ static final String PREF_KEY = "ring_vibration_preference_screen";
+
+ public RingVibrationIntensityPreferenceController(Context context) {
+ super(context, PREF_KEY, Settings.System.RING_VIBRATION_INTENSITY,
+ Settings.System.VIBRATE_WHEN_RINGING);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ protected int getDefaultIntensity() {
+ return mVibrator.getDefaultRingVibrationIntensity();
+ }
+}
diff --git a/src/com/android/settings/accessibility/RingVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/RingVibrationPreferenceFragment.java
new file mode 100644
index 0000000..df05231
--- /dev/null
+++ b/src/com/android/settings/accessibility/RingVibrationPreferenceFragment.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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.accessibility;
+
+import android.media.AudioAttributes;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+
+/**
+ * Fragment for picking accessibility shortcut service
+ */
+public class RingVibrationPreferenceFragment extends VibrationPreferenceFragment {
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ACCESSIBILITY_VIBRATION_RING;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.accessibility_ring_vibration_settings;
+ }
+
+ /**
+ * Get the setting string of the vibration intensity setting this preference is dealing with.
+ */
+ @Override
+ protected String getVibrationIntensitySetting() {
+ return Settings.System.RING_VIBRATION_INTENSITY;
+ }
+
+ @Override
+ protected String getVibrationEnabledSetting() {
+ return Settings.System.VIBRATE_WHEN_RINGING;
+ }
+
+ @Override
+ protected int getPreviewVibrationAudioAttributesUsage() {
+ return AudioAttributes.USAGE_NOTIFICATION;
+ }
+
+ @Override
+ protected int getDefaultVibrationIntensity() {
+ Vibrator vibrator = getContext().getSystemService(Vibrator.class);
+ return vibrator.getDefaultRingVibrationIntensity();
+ }
+}
diff --git a/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java
index ba08a43..52fd069 100644
--- a/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java
@@ -45,6 +45,11 @@
}
@Override
+ protected String getVibrationEnabledSetting() {
+ return Settings.System.HAPTIC_FEEDBACK_ENABLED;
+ }
+
+ @Override
protected int getDefaultVibrationIntensity() {
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
return vibrator.getDefaultHapticFeedbackIntensity();
@@ -54,13 +59,4 @@
protected int getPreviewVibrationAudioAttributesUsage() {
return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION;
}
-
- @Override
- public void onVibrationIntensitySelected(int intensity) {
- // We want to keep HAPTIC_FEEDBACK_ENABLED consistent with this setting since some
- // applications check it directly before triggering their own haptic feedback.
- final boolean hapticFeedbackEnabled = !(intensity == Vibrator.VIBRATION_INTENSITY_OFF);
- Settings.System.putInt(getContext().getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_ENABLED, hapticFeedbackEnabled ? 1 : 0);
- }
}
diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
index d9b1d79..e52f92d 100644
--- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
@@ -39,14 +39,16 @@
protected final Vibrator mVibrator;
private final SettingObserver mSettingsContentObserver;
private final String mSettingKey;
+ private final String mEnabledKey;
private Preference mPreference;
public VibrationIntensityPreferenceController(Context context, String prefkey,
- String settingKey) {
+ String settingKey, String enabledKey) {
super(context, prefkey);
mVibrator = mContext.getSystemService(Vibrator.class);
mSettingKey = settingKey;
+ mEnabledKey = enabledKey;
mSettingsContentObserver = new SettingObserver(settingKey) {
@Override
public void onChange(boolean selfChange, Uri uri) {
@@ -78,7 +80,9 @@
public CharSequence getSummary() {
final int intensity = Settings.System.getInt(mContext.getContentResolver(),
mSettingKey, getDefaultIntensity());
- return getIntensityString(mContext, intensity);
+ final boolean enabled = Settings.System.getInt(mContext.getContentResolver(),
+ mEnabledKey, 1) == 1;
+ return getIntensityString(mContext, enabled ? intensity : Vibrator.VIBRATION_INTENSITY_OFF);
}
public static CharSequence getIntensityString(Context context, int intensity) {
diff --git a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java
index 1101611..648acad 100644
--- a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java
@@ -26,6 +26,7 @@
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -117,6 +118,11 @@
protected abstract String getVibrationIntensitySetting();
/**
+ * Get the setting string of the vibration enabledness setting this preference is dealing with.
+ */
+ protected abstract String getVibrationEnabledSetting();
+
+ /**
* Get the default intensity for the desired setting.
*/
protected abstract int getDefaultVibrationIntensity();
@@ -154,8 +160,13 @@
@Override
protected String getDefaultKey() {
- final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(),
+ int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(),
getVibrationIntensitySetting(), getDefaultVibrationIntensity());
+ final boolean vibrationEnabled = Settings.System.getInt(getContext().getContentResolver(),
+ getVibrationEnabledSetting(), 1) == 1;
+ if (!vibrationEnabled) {
+ vibrationIntensity = Vibrator.VIBRATION_INTENSITY_OFF;
+ }
for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) {
final boolean matchesIntensity = candidate.getIntensity() == vibrationIntensity;
final boolean matchesOn = candidate.getKey().equals(KEY_INTENSITY_ON)
@@ -174,8 +185,11 @@
Log.e(TAG, "Tried to set unknown intensity (key=" + key + ")!");
return false;
}
- Settings.System.putInt(getContext().getContentResolver(),
- getVibrationIntensitySetting(), candidate.getIntensity());
+ if (candidate.getIntensity() != Vibrator.VIBRATION_INTENSITY_OFF ||
+ TextUtils.isEmpty(getVibrationEnabledSetting())) {
+ Settings.System.putInt(getContext().getContentResolver(),
+ getVibrationIntensitySetting(), candidate.getIntensity());
+ }
onVibrationIntensitySelected(candidate.getIntensity());
return true;
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index eb5e02b..84745d2 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -179,6 +179,7 @@
controllers.add(new FaceSettingsAttentionPreferenceController(context));
controllers.add(new FaceSettingsRemoveButtonPreferenceController(context));
controllers.add(new FaceSettingsFooterPreferenceController(context));
+ controllers.add(new FaceSettingsConfirmPreferenceController(context));
return controllers;
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
new file mode 100644
index 0000000..08740cf
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 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.biometrics.face;
+
+import static android.provider.Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * Preference controller giving the user an option to always require confirmation.
+ */
+public class FaceSettingsConfirmPreferenceController extends TogglePreferenceController {
+
+ private static final String KEY = "security_settings_face_require_confirmation";
+
+ private static final int ON = 1;
+ private static final int OFF = 0;
+ private static final int DEFAULT = OFF;
+
+ public FaceSettingsConfirmPreferenceController(Context context) {
+ this(context, KEY);
+ }
+
+ public FaceSettingsConfirmPreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, DEFAULT) == ON;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Secure.putInt(mContext.getContentResolver(),
+ FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, isChecked ? ON : OFF);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 6ec419b..43de5a4 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -30,7 +30,7 @@
import com.android.settings.core.FeatureFlags;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.slices.SlicePreferenceController;
+import com.android.settings.slices.BlockingSlicePrefController;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -106,7 +106,7 @@
if (FeatureFlagUtils.isEnabled(context, FeatureFlags.SLICE_INJECTION)) {
final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(context)
.getBluetoothFeatureProvider(context);
- use(SlicePreferenceController.class).setSliceUri(
+ use(BlockingSlicePrefController.class).setSliceUri(
featureProvider.getBluetoothDeviceSettingsUri(mDeviceAddress));
}
}
diff --git a/src/com/android/settings/core/BasePreferenceController.java b/src/com/android/settings/core/BasePreferenceController.java
index facec4a..1c85009 100644
--- a/src/com/android/settings/core/BasePreferenceController.java
+++ b/src/com/android/settings/core/BasePreferenceController.java
@@ -106,6 +106,7 @@
protected final String mPreferenceKey;
+ protected UiBlockListener mUiBlockListener;
/**
* Instantiate a controller as specified controller type and user-defined key.
@@ -289,4 +290,36 @@
*/
public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
}
+
+ /**
+ * Set {@link UiBlockListener}
+ * @param uiBlockListener listener to set
+ */
+ public void setUiBlockListener(UiBlockListener uiBlockListener) {
+ mUiBlockListener = uiBlockListener;
+ }
+
+ /**
+ * Listener to invoke when background job is finished
+ */
+ public interface UiBlockListener {
+ /**
+ * To notify client that UI related background work is finished.
+ * (i.e. Slice is fully loaded.)
+ * @param controller Controller that contains background work
+ */
+ void onBlockerWorkFinished(BasePreferenceController controller);
+ }
+
+ /**
+ * Used for {@link BasePreferenceController} to decide whether it is ui blocker.
+ * If it is, entire UI will be invisible for a certain period until controller
+ * invokes {@link UiBlockListener}
+ *
+ * This won't block UI thread however has similar side effect. Please use it if you
+ * want to avoid janky animation(i.e. new preference is added in the middle of page).
+ *
+ * This music be used in {@link BasePreferenceController}
+ */
+ public interface UiBlocker {}
}
\ No newline at end of file
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index ce5c505..db6cd41 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -72,9 +72,11 @@
MetadataFlag.FLAG_NEED_PREF_SUMMARY,
MetadataFlag.FLAG_NEED_PREF_ICON,
MetadataFlag.FLAG_NEED_SEARCHABLE,
- MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE})
+ MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
+ MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE})
@Retention(RetentionPolicy.SOURCE)
public @interface MetadataFlag {
+
int FLAG_INCLUDE_PREF_SCREEN = 1;
int FLAG_NEED_KEY = 1 << 1;
int FLAG_NEED_PREF_TYPE = 1 << 2;
@@ -87,6 +89,7 @@
int FLAG_NEED_SEARCHABLE = 1 << 9;
int FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE = 1 << 10;
int FLAG_NEED_PREF_APPEND = 1 << 11;
+ int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 12;
}
public static final String METADATA_PREF_TYPE = "type";
@@ -101,6 +104,8 @@
public static final String METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE =
"allow_dynamic_summary_in_slice";
public static final String METADATA_APPEND = "staticPreferenceLocation";
+ public static final String METADATA_UNAVAILABLE_SLICE_SUBTITLE =
+ "unavailable_slice_subtitle";
private static final String ENTRIES_SEPARATOR = "|";
@@ -249,6 +254,10 @@
preferenceMetadata.putBoolean(METADATA_APPEND,
isAppended(preferenceScreenAttributes));
}
+ if (hasFlag(flags, MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE)) {
+ preferenceMetadata.putString(METADATA_UNAVAILABLE_SLICE_SUBTITLE,
+ getUnavailableSliceSubtitle(preferenceAttributes));
+ }
metadata.add(preferenceMetadata);
preferenceAttributes.recycle();
@@ -344,6 +353,11 @@
private static boolean isAppended(TypedArray styledAttributes) {
return styledAttributes.getInt(R.styleable.PreferenceScreen_staticPreferenceLocation,
- PREPEND_VALUE) == APPEND_VALUE;
+ PREPEND_VALUE) == APPEND_VALUE;
}
-}
+
+ private static String getUnavailableSliceSubtitle(TypedArray styledAttributes) {
+ return styledAttributes.getString(
+ R.styleable.Preference_unavailableSliceSubtitle);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 1916110..11858a7 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -56,7 +56,8 @@
*/
public abstract class DashboardFragment extends SettingsPreferenceFragment
implements SettingsBaseActivity.CategoryListener, Indexable,
- SummaryLoader.SummaryConsumer, PreferenceGroup.OnExpandButtonClickListener {
+ SummaryLoader.SummaryConsumer, PreferenceGroup.OnExpandButtonClickListener,
+ BasePreferenceController.UiBlockListener {
private static final String TAG = "DashboardFragment";
private final Map<Class, List<AbstractPreferenceController>> mPreferenceControllers =
@@ -67,6 +68,7 @@
private DashboardTilePlaceholderPreferenceController mPlaceholderPreferenceController;
private boolean mListeningToCategoryChange;
private SummaryLoader mSummaryLoader;
+ private UiBlockerController mBlockerController;
@Override
public void onAttach(Context context) {
@@ -105,6 +107,22 @@
for (AbstractPreferenceController controller : controllers) {
addPreferenceController(controller);
}
+
+ checkUiBlocker(controllers);
+ }
+
+ private void checkUiBlocker(List<AbstractPreferenceController> controllers) {
+ final List<String> keys = new ArrayList<>();
+ controllers
+ .stream()
+ .filter(controller -> controller instanceof BasePreferenceController.UiBlocker)
+ .forEach(controller -> {
+ ((BasePreferenceController) controller).setUiBlockListener(this);
+ keys.add(controller.getPreferenceKey());
+ });
+
+ mBlockerController = new UiBlockerController(keys);
+ mBlockerController.start(()->updatePreferenceVisibility());
}
@Override
@@ -319,10 +337,11 @@
* DashboardCategory.
*/
private void refreshAllPreferences(final String TAG) {
+ final PreferenceScreen screen = getPreferenceScreen();
// First remove old preferences.
- if (getPreferenceScreen() != null) {
+ if (screen != null) {
// Intentionally do not cache PreferenceScreen because it will be recreated later.
- getPreferenceScreen().removeAll();
+ screen.removeAll();
}
// Add resource based tiles.
@@ -335,6 +354,27 @@
Log.d(TAG, "All preferences added, reporting fully drawn");
activity.reportFullyDrawn();
}
+
+ updatePreferenceVisibility();
+ }
+
+ private void updatePreferenceVisibility() {
+ final PreferenceScreen screen = getPreferenceScreen();
+ if (screen == null) {
+ return;
+ }
+
+ final boolean visible = mBlockerController.isBlockerFinished();
+ for (List<AbstractPreferenceController> controllerList :
+ mPreferenceControllers.values()) {
+ for (AbstractPreferenceController controller : controllerList) {
+ final String key = controller.getPreferenceKey();
+ final Preference preference = screen.findPreference(key);
+ if (preference != null) {
+ preference.setVisible(visible && controller.isAvailable());
+ }
+ }
+ }
}
/**
@@ -413,4 +453,9 @@
}
mSummaryLoader.setListening(true);
}
+
+ @Override
+ public void onBlockerWorkFinished(BasePreferenceController controller) {
+ mBlockerController.countDown(controller.getPreferenceKey());
+ }
}
diff --git a/src/com/android/settings/dashboard/UiBlockerController.java b/src/com/android/settings/dashboard/UiBlockerController.java
new file mode 100644
index 0000000..eeb56e6
--- /dev/null
+++ b/src/com/android/settings/dashboard/UiBlockerController.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 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.dashboard;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Control ui blocker data and check whether it is finished
+ *
+ * @see BasePreferenceController.UiBlocker
+ * @see BasePreferenceController.OnUiBlockListener
+ */
+public class UiBlockerController {
+ private static final String TAG = "UiBlockerController";
+ private static final int TIMEOUT_MILLIS = 500;
+
+ private CountDownLatch mCountDownLatch;
+ private boolean mBlockerFinished;
+ private Set<String> mKeys;
+ private long mTimeoutMillis;
+
+ public UiBlockerController(@NonNull List<String> keys) {
+ this(keys, TIMEOUT_MILLIS);
+ }
+
+ public UiBlockerController(@NonNull List<String> keys, long timeout) {
+ mCountDownLatch = new CountDownLatch(keys.size());
+ mBlockerFinished = keys.isEmpty();
+ mKeys = new HashSet<>(keys);
+ mTimeoutMillis = timeout;
+ }
+
+ /**
+ * Start background thread, it will invoke {@code finishRunnable} if any condition is met
+ *
+ * 1. Waiting time exceeds {@link #mTimeoutMillis}
+ * 2. All background work that associated with {@link #mCountDownLatch} is finished
+ */
+ public boolean start(Runnable finishRunnable) {
+ if (mKeys.isEmpty()) {
+ // Don't need to run finishRunnable because it doesn't start
+ return false;
+ }
+ ThreadUtils.postOnBackgroundThread(() -> {
+ try {
+ mCountDownLatch.await(mTimeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Log.w(TAG, "interrupted");
+ }
+ mBlockerFinished = true;
+ ThreadUtils.postOnMainThread(finishRunnable);
+ });
+
+ return true;
+ }
+
+ /**
+ * Return {@code true} if all work finished
+ */
+ public boolean isBlockerFinished() {
+ return mBlockerFinished;
+ }
+
+ /**
+ * Count down latch by {@code key}. It only count down 1 time if same key count down multiple
+ * times.
+ */
+ public boolean countDown(String key) {
+ if (mKeys.remove(key)) {
+ mCountDownLatch.countDown();
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/src/com/android/settings/development/CbrsDataSwitchPreferenceController.java b/src/com/android/settings/development/CbrsDataSwitchPreferenceController.java
deleted file mode 100644
index d5c78e8..0000000
--- a/src/com/android/settings/development/CbrsDataSwitchPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2018 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.development;
-
-import android.content.Context;
-import android.util.Log;
-import android.telephony.TelephonyManager;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.SwitchPreference;
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-public class CbrsDataSwitchPreferenceController extends DeveloperOptionsPreferenceController
- implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
- private static final String CBRS_DATA_SWITCH_KEY = "cbrs_data_switch";
- private static final String TAG = "CbrsDataSwitchPreferenceController";
- private Context mContext;
-
- private TelephonyManager mTelephonyManager;
-
- public CbrsDataSwitchPreferenceController(Context context) {
- super(context);
- mContext = context;
- mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
- }
-
- @Override
- public String getPreferenceKey() {
- return CBRS_DATA_SWITCH_KEY;
- }
-
- @Override
- public boolean isAvailable() {
- return mTelephonyManager != null;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- boolean state = (Boolean)newValue;
- return mTelephonyManager.setAlternativeNetworkState(state);
- }
-
- @Override
- public void updateState(Preference preference) {
- boolean state = mTelephonyManager.isAlternativeNetworkEnabled();
- ((SwitchPreference) mPreference).setChecked(state);
- }
-
-}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 725a195..2a9919a 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -481,7 +481,6 @@
controllers.add(new SmsAccessRestrictionPreferenceController(context));
controllers.add(new ShortcutManagerThrottlingPreferenceController(context));
controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context));
- controllers.add(new CbrsDataSwitchPreferenceController(context));
controllers.add(new DefaultLaunchPreferenceController(context, "running_apps"));
controllers.add(new DefaultLaunchPreferenceController(context, "demo_mode"));
controllers.add(new DefaultLaunchPreferenceController(context, "quick_settings_tiles"));
diff --git a/src/com/android/settings/development/gup/GupPreferenceController.java b/src/com/android/settings/development/gup/GupPreferenceController.java
index 7623144..d4cd2f1 100644
--- a/src/com/android/settings/development/gup/GupPreferenceController.java
+++ b/src/com/android/settings/development/gup/GupPreferenceController.java
@@ -48,7 +48,7 @@
private final String mPreferenceTitle;
private final String mPreferenceDefault;
private final String mPreferenceGup;
- private final String mPreferenceNative;
+ private final String mPreferenceSystem;
private final List<AppInfo> mAppInfos;
private final Set<String> mDevOptInApps;
@@ -62,7 +62,7 @@
mPreferenceTitle = resources.getString(R.string.gup_app_preference_title);
mPreferenceDefault = resources.getString(R.string.gup_app_preference_default);
mPreferenceGup = resources.getString(R.string.gup_app_preference_gup);
- mPreferenceNative = resources.getString(R.string.gup_app_preference_native);
+ mPreferenceSystem = resources.getString(R.string.gup_app_preference_system);
// TODO: Move this task to background if there's potential ANR/Jank.
// Update the UI when all the app infos are ready.
@@ -105,19 +105,18 @@
// When user choose a new preference, update both Sets for
// opt-in and opt-out apps. Then set the new summary text.
- if (value.equals(mPreferenceNative)) {
+ if (value.equals(mPreferenceSystem)) {
mDevOptInApps.remove(packageName);
mDevOptOutApps.add(packageName);
- listPref.setSummary(mPreferenceNative);
} else if (value.equals(mPreferenceGup)) {
mDevOptInApps.add(packageName);
mDevOptOutApps.remove(packageName);
- listPref.setSummary(mPreferenceGup);
} else {
mDevOptInApps.remove(packageName);
mDevOptOutApps.remove(packageName);
- listPref.setSummary(mPreferenceDefault);
}
+ listPref.setValue(value);
+ listPref.setSummary(value);
// Push the updated Sets for opt-in and opt-out apps to
// corresponding Settings.Global.GUP_DEV_OPT_(IN|OUT)_APPS
@@ -189,8 +188,8 @@
// Initialize preference default and summary with the opt in/out choices
// from Settings.Global.GUP_DEV_OPT_(IN|OUT)_APPS
if (mDevOptOutApps.contains(packageName)) {
- listPreference.setValue(mPreferenceNative);
- listPreference.setSummary(mPreferenceNative);
+ listPreference.setValue(mPreferenceSystem);
+ listPreference.setSummary(mPreferenceSystem);
} else if (mDevOptInApps.contains(packageName)) {
listPreference.setValue(mPreferenceGup);
listPreference.setSummary(mPreferenceGup);
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
index 215f400..6c11576 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
@@ -54,9 +54,11 @@
mContext = context;
mSeekBarPreference = new SeekBarPreference(context);
mSeekBarPreference.setOnPreferenceChangeListener(this);
- mSeekBarPreference.setMax(BatterySaverScheduleSeekBarController.MAX_SEEKBAR_VALUE);
- mSeekBarPreference.setMin(BatterySaverScheduleSeekBarController.MIN_SEEKBAR_VALUE);
+ mSeekBarPreference.setContinuousUpdates(true);
+ mSeekBarPreference.setMax(MAX_SEEKBAR_VALUE);
+ mSeekBarPreference.setMin(MIN_SEEKBAR_VALUE);
mSeekBarPreference.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
+ updateSeekBar();
}
@Override
@@ -83,11 +85,12 @@
if (threshold <= 0) {
mSeekBarPreference.setVisible(false);
} else {
+ final int currentSeekbarValue = Math.max(threshold / 5, MIN_SEEKBAR_VALUE);
mSeekBarPreference.setVisible(true);
- mSeekBarPreference.setProgress(MIN_SEEKBAR_VALUE);
+ mSeekBarPreference.setProgress(currentSeekbarValue);
mSeekBarPreference.setTitle(mContext.getString(
R.string.battery_saver_seekbar_title,
- Utils.formatPercentage(MIN_SEEKBAR_VALUE * 5)));
+ Utils.formatPercentage(currentSeekbarValue * 5)));
}
} else {
mSeekBarPreference.setVisible(false);
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
index 6e9c711..bfd36f3 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
@@ -17,10 +17,14 @@
package com.android.settings.fuelgauge.batterysaver;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.PreferenceScreen;
import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settings.R;
@@ -59,6 +63,13 @@
}
@Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ setDivider(new ColorDrawable(Color.TRANSPARENT));
+ setDividerHeight(0);
+ }
+
+ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
diff --git a/src/com/android/settings/slices/BlockingSlicePrefController.java b/src/com/android/settings/slices/BlockingSlicePrefController.java
new file mode 100644
index 0000000..94810c5
--- /dev/null
+++ b/src/com/android/settings/slices/BlockingSlicePrefController.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 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.slices;
+
+import android.content.Context;
+
+import androidx.slice.Slice;
+
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * The blocking slice preference controller. It will make whole page invisible for a certain time
+ * until {@link Slice} is fully loaded.
+ */
+public class BlockingSlicePrefController extends SlicePreferenceController implements
+ BasePreferenceController.UiBlocker {
+
+ public BlockingSlicePrefController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public void onChanged(Slice slice) {
+ super.onChanged(slice);
+ if (mUiBlockListener != null) {
+ mUiBlockListener.onBlockerWorkFinished(this);
+ }
+ }
+}
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index b2b8310..925306e 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -425,7 +425,10 @@
final String title = data.getTitle();
final Set<String> keywords = buildSliceKeywords(data);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
- final CharSequence summary = context.getText(R.string.disabled_dependent_setting_summary);
+
+ final String customSubtitle = data.getUnavailableSliceSubtitle();
+ final CharSequence subtitle = !TextUtils.isEmpty(customSubtitle) ? customSubtitle
+ : context.getText(R.string.disabled_dependent_setting_summary);
final IconCompat icon = getSafeIcon(context, data);
final SliceAction primaryAction = SliceAction.createDeeplink(
getContentPendingIntent(context, data),
@@ -436,7 +439,7 @@
.addRow(new RowBuilder()
.setTitle(title)
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
- .setSubtitle(summary)
+ .setSubtitle(subtitle)
.setPrimaryAction(primaryAction))
.setKeywords(keywords)
.build();
diff --git a/src/com/android/settings/slices/SliceData.java b/src/com/android/settings/slices/SliceData.java
index 8705884..9d52d56 100644
--- a/src/com/android/settings/slices/SliceData.java
+++ b/src/com/android/settings/slices/SliceData.java
@@ -28,7 +28,6 @@
* Note that {@link #mKey} is treated as a primary key for this class and determines equality.
*/
public class SliceData {
-
/**
* Flags indicating the UI type of the Slice.
*/
@@ -76,6 +75,8 @@
private final boolean mIsDynamicSummaryAllowed;
+ private final String mUnavailableSliceSubtitle;
+
public String getKey() {
return mKey;
}
@@ -124,6 +125,10 @@
return mIsDynamicSummaryAllowed;
}
+ public String getUnavailableSliceSubtitle() {
+ return mUnavailableSliceSubtitle;
+ }
+
private SliceData(Builder builder) {
mKey = builder.mKey;
mTitle = builder.mTitle;
@@ -137,6 +142,7 @@
mSliceType = builder.mSliceType;
mIsPlatformDefined = builder.mIsPlatformDefined;
mIsDynamicSummaryAllowed = builder.mIsDynamicSummaryAllowed;
+ mUnavailableSliceSubtitle = builder.mUnavailableSliceSubtitle;
}
@Override
@@ -178,6 +184,8 @@
private boolean mIsDynamicSummaryAllowed;
+ private String mUnavailableSliceSubtitle;
+
public Builder setKey(String key) {
mKey = key;
return this;
@@ -238,6 +246,12 @@
return this;
}
+ public Builder setUnavailableSliceSubtitle(
+ String unavailableSliceSubtitle) {
+ mUnavailableSliceSubtitle = unavailableSliceSubtitle;
+ return this;
+ }
+
public SliceData build() {
if (TextUtils.isEmpty(mKey)) {
throw new InvalidSliceDataException("Key cannot be empty");
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index cb2980d..dcc8089 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -16,12 +16,12 @@
package com.android.settings.slices;
-import static com.android.settings.core.PreferenceXmlParserUtils
- .METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_PLATFORM_SLICE_FLAG;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_UNAVAILABLE_SLICE_SUBTITLE;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
@@ -189,7 +189,8 @@
| MetadataFlag.FLAG_NEED_PREF_ICON
| MetadataFlag.FLAG_NEED_PREF_SUMMARY
| MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG
- | MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE);
+ | MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE
+ | MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE);
for (Bundle bundle : metadata) {
// TODO (b/67996923) Non-controller Slices should become intent-only slices.
@@ -208,6 +209,8 @@
final boolean isPlatformSlice = bundle.getBoolean(METADATA_PLATFORM_SLICE_FLAG);
final boolean isDynamicSummaryAllowed = bundle.getBoolean(
METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE);
+ final String unavailableSliceSubtitle = bundle.getString(
+ METADATA_UNAVAILABLE_SLICE_SUBTITLE);
final SliceData xmlSlice = new SliceData.Builder()
.setKey(key)
@@ -220,6 +223,7 @@
.setSliceType(sliceType)
.setPlatformDefined(isPlatformSlice)
.setDynamicSummaryAllowed(isDynamicSummaryAllowed)
+ .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
.build();
final BasePreferenceController controller =
diff --git a/src/com/android/settings/slices/SlicePreferenceController.java b/src/com/android/settings/slices/SlicePreferenceController.java
index 8c751c8..93ba652 100644
--- a/src/com/android/settings/slices/SlicePreferenceController.java
+++ b/src/com/android/settings/slices/SlicePreferenceController.java
@@ -51,8 +51,7 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mSlicePreference = (SlicePreference) screen.findPreference(
- getPreferenceKey());
+ mSlicePreference = screen.findPreference(getPreferenceKey());
}
@Override
diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
index c75f3ef..ae77dd2 100644
--- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java
+++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
@@ -50,6 +50,7 @@
IndexColumns.PLATFORM_SLICE,
IndexColumns.SLICE_TYPE,
IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
+ IndexColumns.UNAVAILABLE_SLICE_SUBTITLE,
};
// Cursor value for boolean true
@@ -167,6 +168,8 @@
cursor.getColumnIndex(IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE)) == TRUE;
int sliceType = cursor.getInt(
cursor.getColumnIndex(IndexColumns.SLICE_TYPE));
+ final String unavailableSliceSubtitle = cursor.getString(
+ cursor.getColumnIndex(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE));
if (isIntentOnly) {
sliceType = SliceData.SliceType.INTENT;
@@ -185,6 +188,7 @@
.setPlatformDefined(isPlatformDefined)
.setSliceType(sliceType)
.setDynamicSummaryAllowed(isDynamicSummaryAllowed)
+ .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
.build();
}
diff --git a/src/com/android/settings/slices/SlicesDatabaseHelper.java b/src/com/android/settings/slices/SlicesDatabaseHelper.java
index e463099..8dc86fb 100644
--- a/src/com/android/settings/slices/SlicesDatabaseHelper.java
+++ b/src/com/android/settings/slices/SlicesDatabaseHelper.java
@@ -36,7 +36,7 @@
private static final String DATABASE_NAME = "slices_index.db";
private static final String SHARED_PREFS_TAG = "slices_shared_prefs";
- private static final int DATABASE_VERSION = 3;
+ private static final int DATABASE_VERSION = 4;
public interface Tables {
String TABLE_SLICES_INDEX = "slices_index";
@@ -99,6 +99,11 @@
* preference controller.
*/
String ALLOW_DYNAMIC_SUMMARY_IN_SLICE = "allow_dynamic_summary_in_slice";
+
+ /**
+ * Customized subtitle if it's a unavailable slice
+ */
+ String UNAVAILABLE_SLICE_SUBTITLE = "unavailable_slice_subtitle";
}
private static final String CREATE_SLICES_TABLE =
@@ -125,6 +130,8 @@
IndexColumns.SLICE_TYPE +
", " +
IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE +
+ ", " +
+ IndexColumns.UNAVAILABLE_SLICE_SUBTITLE +
");";
private final Context mContext;
@@ -151,7 +158,7 @@
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < DATABASE_VERSION) {
- Log.d(TAG, "Reconstructing DB from " + oldVersion + "to " + newVersion);
+ Log.d(TAG, "Reconstructing DB from " + oldVersion + " to " + newVersion);
reconstruct(db);
}
}
diff --git a/src/com/android/settings/slices/SlicesIndexer.java b/src/com/android/settings/slices/SlicesIndexer.java
index 0c39429..ec2be29 100644
--- a/src/com/android/settings/slices/SlicesIndexer.java
+++ b/src/com/android/settings/slices/SlicesIndexer.java
@@ -113,6 +113,8 @@
values.put(IndexColumns.SLICE_TYPE, dataRow.getSliceType());
values.put(IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
dataRow.isDynamicSummaryAllowed());
+ values.put(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE,
+ dataRow.getUnavailableSliceSubtitle());
database.replaceOrThrow(Tables.TABLE_SLICES_INDEX, null /* nullColumnHack */,
values);
diff --git a/tests/robotests/res/xml-mcc999/location_settings.xml b/tests/robotests/res/xml-mcc999/location_settings.xml
index 91e4c41..a25f36d 100644
--- a/tests/robotests/res/xml-mcc999/location_settings.xml
+++ b/tests/robotests/res/xml-mcc999/location_settings.xml
@@ -27,6 +27,7 @@
settings:controller="com.android.settings.slices.FakePreferenceController"
settings:keywords="a, b, c"
settings:platform_slice="true"
- settings:allowDynamicSummaryInSlice="true"/>
+ settings:allowDynamicSummaryInSlice="true"
+ settings:unavailableSliceSubtitle="subtitleOfUnavailableSlice"/>
</PreferenceScreen>
\ No newline at end of file
diff --git a/tests/robotests/res/xml-mcc999/night_display_settings.xml b/tests/robotests/res/xml-mcc999/night_display_settings.xml
new file mode 100644
index 0000000..c23a2cf
--- /dev/null
+++ b/tests/robotests/res/xml-mcc999/night_display_settings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:key="fake_title_key"
+ android:title="screen_title">
+
+ <Preference
+ android:key="key1"
+ android:title="title"
+ android:icon="@drawable/ic_android"
+ android:summary="summary"
+ settings:controller="com.android.settings.slices.FakePreferenceController"
+ settings:keywords="keyword"
+ settings:platform_slice="true"/>
+
+ <Preference
+ android:key="key2"
+ android:title="title"
+ android:icon="@drawable/ic_android"
+ android:summary="summary"
+ settings:controller="com.android.settings.slices.FakePreferenceController"
+ settings:keywords="keyword"
+ settings:platform_slice="true"
+ settings:unavailableSliceSubtitle="subtitleOfUnavailable"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java
index 68d5e36..9f83f72 100644
--- a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java
@@ -161,6 +161,11 @@
}
@Override
+ protected String getVibrationEnabledSetting() {
+ return "";
+ }
+
+ @Override
protected int getDefaultVibrationIntensity() {
return Vibrator.VIBRATION_INTENSITY_MEDIUM;
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
index 21d62bc..be77283 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
@@ -26,6 +26,8 @@
import android.content.Context;
import android.os.Bundle;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -49,9 +51,10 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private CachedBluetoothDevice mCachedDevice;
-
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private LocalBluetoothManager mLocalManager;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
@@ -62,6 +65,7 @@
mFragment = spy(BluetoothDeviceDetailsFragment.newInstance(TEST_ADDRESS));
doReturn(mLocalManager).when(mFragment).getLocalBluetoothManager(any());
doReturn(mCachedDevice).when(mFragment).getCachedDevice(any());
+ doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
Bundle args = new Bundle();
diff --git a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
index 9627a48..b8051a1 100644
--- a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
@@ -16,12 +16,12 @@
package com.android.settings.core;
-import static com.android.settings.core.PreferenceXmlParserUtils
- .METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_APPEND;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEYWORDS;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SEARCHABLE;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_UNAVAILABLE_SLICE_SUBTITLE;
import static com.google.common.truth.Truth.assertThat;
@@ -35,7 +35,6 @@
import com.android.settings.R;
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
-import java.util.Objects;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,6 +46,7 @@
import java.io.IOException;
import java.util.List;
+import java.util.Objects;
/**
* These tests use a series of preferences that have specific attributes which are sometimes
@@ -320,7 +320,7 @@
@Test
@Config(qualifiers = "mcc999")
public void extractMetadata_requestAppendProperty_shouldDefaultToFalse()
- throws Exception {
+ throws Exception {
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
R.xml.display_settings,
MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
@@ -333,7 +333,7 @@
@Test
@Config(qualifiers = "mcc999")
public void extractMetadata_requestAppendProperty_shouldReturnCorrectValue()
- throws Exception {
+ throws Exception {
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
R.xml.battery_saver_schedule_settings,
MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
@@ -343,6 +343,46 @@
}
}
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void extractMetadata_requestUnavailableSliceSubtitle_shouldDefaultNull()
+ throws Exception {
+ final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
+ R.xml.night_display_settings,
+ MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE);
+
+ boolean bundleWithKey1Found = false;
+ for (Bundle bundle : metadata) {
+ if (bundle.getString(METADATA_KEY).equals("key1")) {
+ assertThat(bundle.getString(METADATA_UNAVAILABLE_SLICE_SUBTITLE)).isNull();
+ bundleWithKey1Found = true;
+ break;
+ }
+ }
+ assertThat(bundleWithKey1Found).isTrue();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void extractMetadata_requestUnavailableSliceSubtitle_shouldReturnAttributeValue()
+ throws Exception {
+ final String expectedSubtitle = "subtitleOfUnavailable";
+ final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
+ R.xml.night_display_settings,
+ MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE);
+
+ boolean bundleWithKey2Found = false;
+ for (Bundle bundle : metadata) {
+ if (bundle.getString(METADATA_KEY).equals("key2")) {
+ assertThat(bundle.getString(METADATA_UNAVAILABLE_SLICE_SUBTITLE)).isEqualTo(
+ expectedSubtitle);
+ bundleWithKey2Found = true;
+ break;
+ }
+ }
+ assertThat(bundleWithKey2Found).isTrue();
+ }
+
/**
* @param resId the ID for the XML preference
* @return an XML resource parser that points to the start tag
diff --git a/tests/robotests/src/com/android/settings/development/CbrsDataSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/CbrsDataSwitchPreferenceControllerTest.java
deleted file mode 100644
index d955a6e..0000000
--- a/tests/robotests/src/com/android/settings/development/CbrsDataSwitchPreferenceControllerTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2018 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.development;
-
-import static org.mockito.Mockito.when;
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.telephony.TelephonyManager;
-
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public final class CbrsDataSwitchPreferenceControllerTest {
-
- @Mock
- private PreferenceScreen mPreferenceScreen;
- private Context mContext;
- private TelephonyManager mTelephonyManager;
- private SwitchPreference mPreference;
- private CbrsDataSwitchPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mController = new CbrsDataSwitchPreferenceController(mContext);
- mPreference = new SwitchPreference(mContext);
- when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn(mPreference);
- mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
- mController.displayPreference(mPreferenceScreen);
- }
-
- @Test
- public void onPreferenceChanged_settingEnabled_shouldEnableANAS() {
- mController.onPreferenceChange(mPreference, true);
-
- assertThat(mTelephonyManager.isAlternativeNetworkEnabled()).isTrue();
- }
-
- @Test
- public void onPreferenceChanged_settingDisabled_shouldDisableANAS() {
- mController.onPreferenceChange(mPreference, false);
-
- assertThat(mTelephonyManager.isAlternativeNetworkEnabled()).isFalse();
- }
-
- @Test
- public void updateState_settingEnabled_shouldEnablePreference() {
- mTelephonyManager.setAlternativeNetworkState(true);
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void updateState_settingDisabled_shouldDisablePreference() {
- mTelephonyManager.setAlternativeNetworkState(false);
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java
index 62e3475..d5e7a85 100644
--- a/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java
@@ -52,7 +52,7 @@
public class GupPreferenceControllerTest {
private static final int DEFAULT = 0;
private static final int GUP = 1;
- private static final int NATIVE = 2;
+ private static final int SYSTEM = 2;
private static final String TEST_APP_NAME = "testApp";
private static final String TEST_PKG_NAME = "testPkg";
@@ -143,7 +143,7 @@
}
@Test
- public void createPreference_configNative_shouldSetNativeAttributes() {
+ public void createPreference_configSystem_shouldSetSystemAttributes() {
loadConfig("", TEST_PKG_NAME);
final ListPreference preference =
mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
@@ -153,9 +153,9 @@
assertThat(preference.getDialogTitle()).isEqualTo(mDialogTitle);
assertThat(preference.getEntries()).isEqualTo(mValueList);
assertThat(preference.getEntryValues()).isEqualTo(mValueList);
- assertThat(preference.getEntry()).isEqualTo(mValueList[NATIVE]);
- assertThat(preference.getValue()).isEqualTo(mValueList[NATIVE]);
- assertThat(preference.getSummary()).isEqualTo(mValueList[NATIVE]);
+ assertThat(preference.getEntry()).isEqualTo(mValueList[SYSTEM]);
+ assertThat(preference.getValue()).isEqualTo(mValueList[SYSTEM]);
+ assertThat(preference.getSummary()).isEqualTo(mValueList[SYSTEM]);
}
@Test
@@ -165,6 +165,8 @@
mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
mController.onPreferenceChange(preference, mValueList[DEFAULT]);
+ assertThat(preference.getEntry()).isEqualTo(mValueList[DEFAULT]);
+ assertThat(preference.getValue()).isEqualTo(mValueList[DEFAULT]);
assertThat(preference.getSummary()).isEqualTo(mValueList[DEFAULT]);
assertThat(Settings.Global.getString(mResolver, Settings.Global.GUP_DEV_OPT_IN_APPS))
.isEqualTo("");
@@ -179,6 +181,8 @@
mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
mController.onPreferenceChange(preference, mValueList[GUP]);
+ assertThat(preference.getEntry()).isEqualTo(mValueList[GUP]);
+ assertThat(preference.getValue()).isEqualTo(mValueList[GUP]);
assertThat(preference.getSummary()).isEqualTo(mValueList[GUP]);
assertThat(Settings.Global.getString(mResolver, Settings.Global.GUP_DEV_OPT_IN_APPS))
.isEqualTo(TEST_PKG_NAME);
@@ -187,13 +191,15 @@
}
@Test
- public void onPreferenceChange_selectNative_shouldUpdateAttributesAndSettingsGlobal() {
+ public void onPreferenceChange_selectSystem_shouldUpdateAttributesAndSettingsGlobal() {
loadDefaultConfig();
final ListPreference preference =
mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
- mController.onPreferenceChange(preference, mValueList[NATIVE]);
+ mController.onPreferenceChange(preference, mValueList[SYSTEM]);
- assertThat(preference.getSummary()).isEqualTo(mValueList[NATIVE]);
+ assertThat(preference.getEntry()).isEqualTo(mValueList[SYSTEM]);
+ assertThat(preference.getValue()).isEqualTo(mValueList[SYSTEM]);
+ assertThat(preference.getSummary()).isEqualTo(mValueList[SYSTEM]);
assertThat(Settings.Global.getString(mResolver, Settings.Global.GUP_DEV_OPT_IN_APPS))
.isEqualTo("");
assertThat(Settings.Global.getString(mResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS))
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 2d893a6..c2d1e93 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -449,7 +449,7 @@
R.drawable.ic_settings).toIcon().getResId();
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, 0 /* icon */,
- IS_DYNAMIC_SUMMARY_ALLOWED);
+ IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */);
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
@@ -518,33 +518,65 @@
assertThat(actualIconResource).isEqualTo(settingsIcon);
}
+ @Test
+ public void buildUnavailableSlice_customizeSubtitle_returnsSliceWithCustomizedSubtitle() {
+ final String subtitleOfUnavailableSlice = "subtitleOfUnavailableSlice";
+ final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
+ SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, 0 /* icon */,
+ IS_DYNAMIC_SUMMARY_ALLOWED, subtitleOfUnavailableSlice);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ FakeUnavailablePreferenceController.AVAILABILITY_KEY,
+ BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+
+ final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
+
+ final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+ assertThat(metadata.getSubtitle()).isEqualTo(subtitleOfUnavailableSlice);
+ }
+
+ @Test
+ public void buildUnavailableSlice_notCustomizeSubtitle_returnsSliceWithDefaultSubtitle() {
+ final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
+ SliceData.SliceType.SWITCH);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ FakeUnavailablePreferenceController.AVAILABILITY_KEY,
+ BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+
+ final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
+
+ final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+ assertThat(metadata.getSubtitle()).isEqualTo(
+ mContext.getString(R.string.disabled_dependent_setting_summary));
+ }
+
private SliceData getDummyData() {
return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE,
- ICON, IS_DYNAMIC_SUMMARY_ALLOWED);
+ ICON, IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */);
}
private SliceData getDummyData(boolean isDynamicSummaryAllowed) {
return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE,
- ICON, isDynamicSummaryAllowed);
+ ICON, isDynamicSummaryAllowed, null /* unavailableSliceSubtitle */);
}
private SliceData getDummyData(Class prefController, int sliceType, int icon) {
- return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE,
- icon, IS_DYNAMIC_SUMMARY_ALLOWED);
+ return getDummyData(prefController, SUMMARY, sliceType, SCREEN_TITLE,
+ icon, IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */);
}
private SliceData getDummyData(String summary, String screenTitle) {
return getDummyData(TOGGLE_CONTROLLER, summary, SliceData.SliceType.SWITCH, screenTitle,
- ICON, IS_DYNAMIC_SUMMARY_ALLOWED);
+ ICON, IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */);
}
private SliceData getDummyData(Class prefController, int sliceType) {
return getDummyData(prefController, SUMMARY, sliceType, SCREEN_TITLE, ICON,
- IS_DYNAMIC_SUMMARY_ALLOWED);
+ IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */);
}
private SliceData getDummyData(Class prefController, String summary, int sliceType,
- String screenTitle, int icon, boolean isDynamicSummaryAllowed) {
+ String screenTitle, int icon, boolean isDynamicSummaryAllowed,
+ String unavailableSliceSubtitle) {
return new SliceData.Builder()
.setKey(KEY)
.setTitle(TITLE)
@@ -557,6 +589,7 @@
.setPreferenceControllerClassName(prefController.getName())
.setSliceType(sliceType)
.setDynamicSummaryAllowed(isDynamicSummaryAllowed)
+ .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
.build();
}
}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index b935e76..7c1319c 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -125,6 +125,8 @@
assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER);
assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML
assertThat(fakeSlice.isDynamicSummaryAllowed()).isTrue(); // from XML
+ assertThat(fakeSlice.getUnavailableSliceSubtitle()).isEqualTo(
+ "subtitleOfUnavailableSlice"); // from XML
}
private void assertFakeA11ySlice(SliceData fakeSlice) {
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
index 579af1f..b6c7af5 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
@@ -39,6 +39,7 @@
private final int SLICE_TYPE = SliceData.SliceType.SWITCH;
private final boolean IS_PLATFORM_DEFINED = true;
private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = true;
+ private final String UNAVAILABLE_SLICE_SUBTITLE = "subtitleOfUnavailableSlice";
@Test
public void testBuilder_buildsMatchingObject() {
@@ -54,7 +55,8 @@
.setPreferenceControllerClassName(PREF_CONTROLLER)
.setSliceType(SLICE_TYPE)
.setPlatformDefined(IS_PLATFORM_DEFINED)
- .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED);
+ .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED)
+ .setUnavailableSliceSubtitle(UNAVAILABLE_SLICE_SUBTITLE);
SliceData data = builder.build();
@@ -70,6 +72,7 @@
assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE);
assertThat(data.isPlatformDefined()).isEqualTo(IS_PLATFORM_DEFINED);
assertThat(data.isDynamicSummaryAllowed()).isEqualTo(IS_DYNAMIC_SUMMARY_ALLOWED);
+ assertThat(data.getUnavailableSliceSubtitle()).isEqualTo(UNAVAILABLE_SLICE_SUBTITLE);
}
@Test(expected = SliceData.InvalidSliceDataException.class)
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
index f4b68a5..a657ede 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
@@ -109,12 +109,14 @@
assertThat(data.getUri()).isNull();
assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME);
assertThat(data.isDynamicSummaryAllowed()).isFalse(); /* default value */
+ assertThat(data.getUnavailableSliceSubtitle()).isNull();
}
@Test
public void testGetSliceDataFromKey_allowDynamicSummary_validSliceReturned() {
String key = "key";
- insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */);
+ insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */,
+ null /* customizedUnavailableSliceSubtitle */);
SliceData data = mAccessor.getSliceDataFromKey(key);
@@ -133,7 +135,8 @@
@Test
public void testGetSliceDataFromKey_doNotAllowDynamicSummary_validSliceReturned() {
String key = "key";
- insertSpecialCase(key, true /* isPlatformSlice */, false /* isDynamicSummaryAllowed */);
+ insertSpecialCase(key, true /* isPlatformSlice */, false /* isDynamicSummaryAllowed */,
+ null /* customizedUnavailableSliceSubtitle */);
SliceData data = mAccessor.getSliceDataFromKey(key);
@@ -243,16 +246,58 @@
assertThat(keys).isNotEmpty();
}
+ @Test
+ public void testGetSliceDataFromKey_defaultUnavailableSlice_validSliceReturned() {
+ String key = "key";
+ insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */,
+ null /* customizedUnavailableSliceSubtitle */);
+
+ SliceData data = mAccessor.getSliceDataFromKey(key);
+
+ assertThat(data.getKey()).isEqualTo(key);
+ assertThat(data.getTitle()).isEqualTo(FAKE_TITLE);
+ assertThat(data.getSummary()).isEqualTo(FAKE_SUMMARY);
+ assertThat(data.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE);
+ assertThat(data.getKeywords()).isEqualTo(FAKE_KEYWORDS);
+ assertThat(data.getIconResource()).isEqualTo(FAKE_ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME);
+ assertThat(data.getUri()).isNull();
+ assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME);
+ assertThat(data.getUnavailableSliceSubtitle()).isNull();
+ }
+
+ @Test
+ public void testGetSliceDataFromKey_customizeSubtitleOfUnavailableSlice_validSliceReturned() {
+ String key = "key";
+ String subtitle = "subtitle";
+ insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */,
+ subtitle);
+
+ SliceData data = mAccessor.getSliceDataFromKey(key);
+
+ assertThat(data.getKey()).isEqualTo(key);
+ assertThat(data.getTitle()).isEqualTo(FAKE_TITLE);
+ assertThat(data.getSummary()).isEqualTo(FAKE_SUMMARY);
+ assertThat(data.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE);
+ assertThat(data.getKeywords()).isEqualTo(FAKE_KEYWORDS);
+ assertThat(data.getIconResource()).isEqualTo(FAKE_ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME);
+ assertThat(data.getUri()).isNull();
+ assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME);
+ assertThat(data.getUnavailableSliceSubtitle()).isEqualTo(subtitle);
+ }
+
private void insertSpecialCase(String key) {
insertSpecialCase(key, true);
}
private void insertSpecialCase(String key, boolean isPlatformSlice) {
- insertSpecialCase(key, isPlatformSlice, false /* isDynamicSummaryAllowed */);
+ insertSpecialCase(key, isPlatformSlice, false /* isDynamicSummaryAllowed */,
+ null /*customizedUnavailableSliceSubtitle*/);
}
private void insertSpecialCase(String key, boolean isPlatformSlice,
- boolean isDynamicSummaryAllowed) {
+ boolean isDynamicSummaryAllowed, String customizedUnavailableSliceSubtitle) {
ContentValues values = new ContentValues();
values.put(SlicesDatabaseHelper.IndexColumns.KEY, key);
values.put(SlicesDatabaseHelper.IndexColumns.TITLE, FAKE_TITLE);
@@ -266,6 +311,8 @@
values.put(SlicesDatabaseHelper.IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
isDynamicSummaryAllowed);
values.put(SlicesDatabaseHelper.IndexColumns.SLICE_TYPE, SliceData.SliceType.INTENT);
+ values.put(SlicesDatabaseHelper.IndexColumns.UNAVAILABLE_SLICE_SUBTITLE,
+ customizedUnavailableSliceSubtitle);
mDb.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, values);
}
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java
index 2bc3443..0e92c05 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java
@@ -74,6 +74,7 @@
IndexColumns.PLATFORM_SLICE,
IndexColumns.SLICE_TYPE,
IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
+ IndexColumns.UNAVAILABLE_SLICE_SUBTITLE,
};
assertThat(columnNames).isEqualTo(expectedNames);
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java b/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java
index 827c3f6..b63dfd9 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java
@@ -55,6 +55,7 @@
private final boolean PLATFORM_DEFINED = true;
private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = true;
private final int SLICE_TYPE = SliceData.SliceType.SLIDER;
+ private final String UNAVAILABLE_SLICE_SUBTITLE = "subtitleOfUnavailableSlice";
private Context mContext;
@@ -145,6 +146,9 @@
cursor.getColumnIndex(
IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE)))
.isEqualTo(1 /* true */);
+ assertThat(cursor.getString(
+ cursor.getColumnIndex(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE)))
+ .isEqualTo(UNAVAILABLE_SLICE_SUBTITLE);
cursor.moveToNext();
}
} finally {
@@ -179,7 +183,8 @@
.setPreferenceControllerClassName(PREF_CONTROLLER)
.setPlatformDefined(PLATFORM_DEFINED)
.setSliceType(SLICE_TYPE)
- .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED);
+ .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED)
+ .setUnavailableSliceSubtitle(UNAVAILABLE_SLICE_SUBTITLE);
for (int i = 0; i < KEYS.length; i++) {
builder.setKey(KEYS[i]).setTitle(TITLES[i]);
diff --git a/tests/unit/src/com/android/settings/dashboard/UiBlockerControllerTest.java b/tests/unit/src/com/android/settings/dashboard/UiBlockerControllerTest.java
new file mode 100644
index 0000000..c3a7a4e
--- /dev/null
+++ b/tests/unit/src/com/android/settings/dashboard/UiBlockerControllerTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.dashboard;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class UiBlockerControllerTest {
+ private static final long TIMEOUT = 600;
+ private static final String KEY_1 = "key1";
+ private static final String KEY_2 = "key2";
+
+ private Instrumentation mInstrumentation;
+ private UiBlockerController mSyncableController;
+
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
+ mSyncableController = new UiBlockerController(Arrays.asList(KEY_1, KEY_2));
+ }
+
+ @Test
+ public void start_isSyncedReturnFalseUntilAllWorkDone() throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mSyncableController.start(() -> latch.countDown());
+
+ // Return false at first
+ assertThat(mSyncableController.isBlockerFinished()).isFalse();
+
+ // Return false if only one job is done
+ mSyncableController.countDown(KEY_1);
+ assertThat(mSyncableController.isBlockerFinished()).isFalse();
+
+ // Return true if all jobs done
+ mSyncableController.countDown(KEY_2);
+ assertThat(latch.await(TIMEOUT, TimeUnit.MILLISECONDS)).isTrue();
+ assertThat(mSyncableController.isBlockerFinished()).isTrue();
+ }
+}