diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 41cb12d03b5..3cb964fefd8 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -3037,4 +3037,36 @@
column="5"/>
+
+
+
+
+
+
+
+
diff --git a/res/drawable-nodpi/color_mode_preview.jpg b/res/drawable-nodpi/color_mode_preview.jpg
index 51dedbf48ad..804bcf1961a 100644
Binary files a/res/drawable-nodpi/color_mode_preview.jpg and b/res/drawable-nodpi/color_mode_preview.jpg differ
diff --git a/res/drawable/face_enroll_introduction.xml b/res/drawable/face_enroll_introduction.xml
index 6065f237237..217b13c2ff2 100644
--- a/res/drawable/face_enroll_introduction.xml
+++ b/res/drawable/face_enroll_introduction.xml
@@ -16,13 +16,13 @@
-->
diff --git a/res/drawable/ic_content_copy_grey600_24dp.xml b/res/drawable/ic_content_copy_grey600_24dp.xml
index 827c66ebab0..ba17ab658e3 100644
--- a/res/drawable/ic_content_copy_grey600_24dp.xml
+++ b/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -1,9 +1,10 @@
+ android:fillColor="@android:color/white"/>
diff --git a/res/drawable/ic_devices_other_opaque_black.xml b/res/drawable/ic_devices_other_opaque_black.xml
index 1b5af2d97dc..40cf527ae69 100644
--- a/res/drawable/ic_devices_other_opaque_black.xml
+++ b/res/drawable/ic_devices_other_opaque_black.xml
@@ -16,9 +16,10 @@
diff --git a/res/drawable/ic_face_24dp.xml b/res/drawable/ic_face_24dp.xml
new file mode 100644
index 00000000000..7920c12570e
--- /dev/null
+++ b/res/drawable/ic_face_24dp.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_friction_lock_closed.xml b/res/drawable/ic_friction_lock_closed.xml
index 2f035e77baa..2c34060ccd6 100644
--- a/res/drawable/ic_friction_lock_closed.xml
+++ b/res/drawable/ic_friction_lock_closed.xml
@@ -17,9 +17,10 @@
diff --git a/res/drawable/ic_settings_adaptive_sleep.xml b/res/drawable/ic_settings_adaptive_sleep.xml
new file mode 100644
index 00000000000..ac103dd4431
--- /dev/null
+++ b/res/drawable/ic_settings_adaptive_sleep.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_settings_disable.xml b/res/drawable/ic_settings_disable.xml
index d0edf4a4bd3..e7a8f4116cb 100644
--- a/res/drawable/ic_settings_disable.xml
+++ b/res/drawable/ic_settings_disable.xml
@@ -18,8 +18,9 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24">
-
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+
diff --git a/res/drawable/ic_settings_enable.xml b/res/drawable/ic_settings_enable.xml
index 560daef774a..673471d874e 100644
--- a/res/drawable/ic_settings_enable.xml
+++ b/res/drawable/ic_settings_enable.xml
@@ -18,8 +18,9 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
diff --git a/res/drawable/ic_settings_gestures.xml b/res/drawable/ic_settings_gestures.xml
index c75e7c3b2e1..f1c1625022a 100644
--- a/res/drawable/ic_settings_gestures.xml
+++ b/res/drawable/ic_settings_gestures.xml
@@ -16,10 +16,13 @@
+ android:pathData="M17,18L7,18L7,6L17,6L17,7L19,7L19,3C19,1.895 18.105,1 17,1L7,1C5.895,1 5,1.895 5,3L5,21C5,22.105 5.895,23 7,23L17,23C18.105,23 19,22.105 19,21L19,17L17,17L17,18ZM7,3L17,3L17,4L7,4L7,3ZM17,21L7,21L7,20L17,20L17,21ZM17.94,12.06L20,13L17.94,13.94L17,16L16.06,13.94L14,13L16.06,12.06L17,10L17.94,12.06ZM20.63,8.38L22,9L20.63,9.63L20,11L19.38,9.63L18,9L19.38,8.38L20,7L20.63,8.38Z"
+ android:strokeColor="#00000000"
+ android:fillType="nonZero"
+ android:fillColor="#000000"
+ android:strokeWidth="1"/>
\ No newline at end of file
diff --git a/res/drawable/ic_sync_problem_24dp.xml b/res/drawable/ic_sync_problem_24dp.xml
index 2139e98ec90..200a1b0ebbf 100644
--- a/res/drawable/ic_sync_problem_24dp.xml
+++ b/res/drawable/ic_sync_problem_24dp.xml
@@ -21,6 +21,6 @@
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
+ android:fillColor="@android:color/white"
+ android:pathData="M11 4.07v2.02C8.17 6.57 6 9.03 6 12c0 2.22 1.21 4.15 3 5.19V14h2v6H5v-2h1.74C5.07 16.54 4 14.4 4 12c0-4.08 3.05-7.44 7-7.93zm8.51 10.67c0.3 0.52 0.49 1.11 0.49 1.76 0 1.93-1.57 3.5-3.5 3.5-0.65 0-1.25-0.19-1.77-0.49-0.65-0.38-1.17-0.96-1.46-1.67-0.17-0.41-0.27-0.87-0.27-1.34 0-1.93 1.57-3.5 3.5-3.5 0.48 0 0.93 0.1 1.35 0.27 0.09-0.41 0.15 -0.83 0.15 -1.27 0-2.22-1.21-4.15-3-5.19V10h-2V4h6v2h-1.74C18.93 7.46 20 9.6 20 12c0 0.96-0.18 1.89-0.49 2.74zM17 18h-1v1h1v-1zm0-4h-1v3h1v-3z" />
diff --git a/res/layout/contextual_slice_deferred_setup.xml b/res/layout/contextual_slice_deferred_setup.xml
index e695d1ddb12..7d5b688c1e8 100644
--- a/res/layout/contextual_slice_deferred_setup.xml
+++ b/res/layout/contextual_slice_deferred_setup.xml
@@ -25,7 +25,7 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="left"
+ android:gravity="start"
android:orientation="vertical"
android:paddingEnd="@dimen/contextual_card_padding_end"
android:paddingTop="@dimen/contextual_deferred_setup_card_padding_top"
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 00ab4433c8b..f551e3637a6 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -56,7 +56,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/SudContentIllustration"
- app:sudVideo="@raw/face_enroll_introduction_animation"/>
+ app:sudVideo="@raw/face_settings"/>
@@ -65,13 +65,35 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:layout_gravity="center_horizontal|bottom">
+ android:layout_gravity="center_horizontal|bottom"
+ android:paddingTop="12dp">
+
+
+
+
+
+
+
+
+
@*android:color/material_grey_800
#AECBFA
#5F6368
+ ?android:attr/colorAccent
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 4a4c896a770..7114bb15152 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -147,4 +147,5 @@
@*android:color/background_device_default_light
+ #ffdadce0
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 856bd210864..9e01877debd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -790,13 +790,13 @@
- Automatically lock
+ Lock after screen timeout
- %1$s after sleep
+ %1$s after timeout
- Immediately after sleep, except when kept unlocked by %1$s
+ Immediately after timeout, except when kept unlocked by %1$s
- %1$s after sleep, except when kept unlocked by %2$s
+ %1$s after timeout, except when kept unlocked by %2$s
Show owner info on lock screen
@@ -808,7 +808,7 @@
Show lockdown option
- Display power button option that turns off Smart Lock, fingerprint unlocking, and notifications on the lock screen
+ Display power button option that turns off Smart Lock, biometric unlocking, and notifications on the lock screen
Trust agents only extend unlock
@@ -882,17 +882,19 @@
Screen lock
-
+
Face added
-
- Tap to set up face authentication
+
+ Set up face unlock
- Face authentication
+ Face unlock
+
+ Face unlock for work
- How to set up Face unlock
+ How to set up face unlock
- Set up Face unlock
-
+ Set up face unlock
+
Use your face to authenticate
@@ -910,7 +912,7 @@
Cancel
Unlock with your face
-
+
Use your face to authenticate
Use your face to unlock your phone, authorize purchases, or sign in to apps.
@@ -919,6 +921,8 @@
Use your face to unlock your phone, authorize purchases, or sign in to apps
+
+
@@ -950,29 +954,30 @@
Use face unlock for
Unlocking your phone
-
+
App sign-in \u0026 payments
- Require for face unlock
-
- Open eyes looking at screen
-
- To unlock the phone, always require looking at the screen with your eyes open
+ Requirements for face unlock
+
+ Require eyes to be open
+
+ To unlock the phone, your eyes must be open
- Confirm button
+ Always require confirmation
- When authenticating for apps, always require confirmation
+ When using face unlock in apps, always require confirmation step
Delete face data
- Set up new face unlock
+ Set up face unlock
- Use Face unlock to unlock your device, sign in to apps, and confirm payments.\n\nKeep in mind:\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face while your eyes are open.\n\nYour phone can be unlocked by someone who looks a lot like you, say, your child or an identical sibling.
+ Use face unlock to unlock your device, sign in to apps, and confirm payments.\n\nKeep in mind:\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face, even if your eyes are closed.\n\nYour phone can be unlocked by someone who looks a lot like you, say, an identical sibling.
Delete face data?
- Data recorded by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.
-
+ The images and biometric data used by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.
+
+ Use face unlock to unlock your phone
@@ -1072,12 +1077,12 @@
Protect your device with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN, pattern, or password.
Protect your phone with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up fingerprint. Tap Cancel, then set a PIN, pattern, or password.
-
- Protect your tablet with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN, pattern, or password.
-
- Protect your device with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN, pattern, or password.
-
- Protect your phone with a screen lock option so no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face authentication. Tap Cancel, then set a PIN, pattern, or password.
+
+ By protecting your tablet with a screen lock option, no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face unlock. To go back, tap Cancel.
+
+ By protecting your device with a screen lock option, no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face unlock. To go back, tap Cancel.
+
+ By protecting your phone with a screen lock option, no one will be able to use it if it is lost or stolen. You also need a screen lock option to set up face unlock. To go back, tap Cancel.
Skip PIN setup?
@@ -1321,7 +1326,7 @@
Choose your backup screen lock method
-
+
Choose your backup screen lock method
@@ -1399,19 +1404,19 @@
You can unlock your phone using your fingerprint. For security, this option requires a backup screen lock.
-
- Face authentication + Pattern
+
+ Face unlock + Pattern
-
- Face authentication + PIN
+
+ Face unlock + PIN
-
- Face authentication + Password
+
+ Face unlock + Password
-
- Continue without face authentication
+
+ Continue without face unlock
-
+
You can unlock your phone using your face. For security, this option requires a backup screen lock.
@@ -2826,17 +2831,24 @@
Display white balance
+
+
Screen attention
- On / Screen won’t turn off if you’re looking at it
+ On / Screen won\u2019t turn off if you\u2019re looking at it
Off
+
+ Camera access needed
+
+ Tap to manage permissions for Device Personalization Services
- Prevents your screen from turning off if you’re looking at it.
+ Prevents your screen from turning off if you\u2019re looking at it
Screen attention uses the front camera to see if someone is looking at the screen. It works on device, and images are never stored or sent to Google.
-
+
+ Keep screen on when viewing it
Night Light
@@ -2912,7 +2924,7 @@
Customize your Pixel
- Try different styles, wallpapers, clocks, and more
+ Try different styles, wallpapers, and more
Screen saver
@@ -4052,12 +4064,12 @@
PIN has been set
Pattern has been set
-
- To use face authentication, set password
-
- To use face authentication, set pattern
-
- To use face authentication, set PIN
+
+ To use face unlock, set password
+
+ To use face unlock, set pattern
+
+ To use face unlock, set PIN
@@ -4873,6 +4885,8 @@
Got it
The Accessibility button is set to %1$s. To use magnification, touch & hold the Accessibility button, then select magnification.
+
+ The accessibility gesture is set to the %1$s. To use magnification, swipe up with two fingers from the bottom of the screen and hold. Then select magnification.
Volume key shortcut
@@ -4949,6 +4963,8 @@
Use color correction
Use captions
+
+ Not all apps support this setting.
Continue
@@ -7993,6 +8009,15 @@
Lock screen
+
+ Skip lock screen
+
+
+ After face unlock, go directly to last used screen
+
+
+ Lock screen, Lockscreen, Skip, Bypass
+
When work profile is locked
@@ -10000,12 +10025,6 @@
Theming
-
- Accent color
-
- Headline / Body font
-
- Icon shape
Device default
diff --git a/res/xml/adaptive_sleep_detail.xml b/res/xml/adaptive_sleep_detail.xml
index 606bb55d465..568e6944581 100644
--- a/res/xml/adaptive_sleep_detail.xml
+++ b/res/xml/adaptive_sleep_detail.xml
@@ -28,6 +28,14 @@
settings:preview="@drawable/adaptive_sleep"
settings:controller="com.android.settings.widget.VideoPreferenceController"/>
+
+
-
+
+
+
+
+
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index 63f67510490..89464fbc5db 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -72,6 +72,13 @@
android:summary="@string/lock_screen_notifs_redact_work_summary"
settings:controller="com.android.settings.notification.RedactNotificationPreferenceController" />
+
+
+ android:order="1100">
-
-
-
-
-
-
-
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index ad06e959aed..c45e6a2ae10 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -93,6 +93,7 @@
-
+ settings:controller="com.android.settings.security.screenlock.LockScreenPreferenceController" />
-
@@ -30,6 +32,6 @@
-
+
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index 611d33fee57..8cd4d76fbe0 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -30,6 +30,13 @@
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_lock_screen_notif"/>
+
+
-
+ settings:controller="com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController"
+ settings:userRestriction="no_ambient_display" />
@@ -39,18 +40,17 @@
android:title="@string/security_settings_face_settings_use_face_for_apps"
app:keywords="@string/keywords_face_unlock"
app:controller="com.android.settings.biometrics.face.FaceSettingsAppPreferenceController"/>
+
-
-
mPreferenceList = new ArrayList<>();
+
@Override
public int getMetricsCategory() {
return SettingsEnums.ACCESSIBILITY_CAPTION_PROPERTIES;
@@ -110,31 +111,18 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
updateAllPreferences();
refreshShowingCustom();
installUpdateListeners();
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- final boolean enabled = mCaptioningManager.isEnabled();
- SettingsActivity activity = (SettingsActivity) getActivity();
- mSwitchBar = activity.getSwitchBar();
- mSwitchBar.setSwitchBarText(R.string.accessibility_caption_master_switch_title,
- R.string.accessibility_caption_master_switch_title);
- mSwitchBar.setCheckedInternal(enabled);
- mToggleSwitch = mSwitchBar.getSwitch();
-
- getPreferenceScreen().setEnabled(enabled);
-
refreshPreviewText();
-
- installSwitchBarToggleSwitch();
}
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- removeSwitchBarToggleSwitch();
+ private void setPreferenceViewEnabled(boolean enabled) {
+ for (Preference preference : mPreferenceList) {
+ preference.setEnabled(enabled);
+ }
+ }
+
+ private void refreshPreferenceViewEnabled(boolean enabled) {
+ setPreferenceViewEnabled(enabled);
+ mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
}
private void refreshPreviewText() {
@@ -196,38 +184,10 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
}
}
- protected void onInstallSwitchBarToggleSwitch() {
- mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
- @Override
- public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
- mSwitchBar.setCheckedInternal(checked);
- Settings.Secure.putInt(getActivity().getContentResolver(),
- Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, checked ? 1 : 0);
- getPreferenceScreen().setEnabled(checked);
- if (mPreviewText != null) {
- mPreviewText.setVisibility(checked ? View.VISIBLE : View.INVISIBLE);
- }
- return false;
- }
- });
- }
-
- private void installSwitchBarToggleSwitch() {
- onInstallSwitchBarToggleSwitch();
- mSwitchBar.show();
- }
-
- private void removeSwitchBarToggleSwitch() {
- mSwitchBar.hide();
- mToggleSwitch.setOnBeforeCheckedChangeListener(null);
- }
-
private void initializeAllPreferences() {
final LayoutPreference captionPreview = findPreference(PREF_CAPTION_PREVIEW);
- final boolean enabled = mCaptioningManager.isEnabled();
mPreviewText = captionPreview.findViewById(R.id.preview_text);
- mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
mPreviewWindow = captionPreview.findViewById(R.id.preview_window);
@@ -236,9 +196,6 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
-> refreshPreviewText());
- mLocale = (LocalePreference) findPreference(PREF_LOCALE);
- mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
-
final Resources res = getResources();
final int[] presetValues = res.getIntArray(R.array.captioning_preset_selector_values);
final String[] presetTitles = res.getStringArray(R.array.captioning_preset_selector_titles);
@@ -246,6 +203,17 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
mPreset.setValues(presetValues);
mPreset.setTitles(presetTitles);
+ mSwitch = (SwitchPreference) findPreference(PREF_SWITCH);
+ mLocale = (LocalePreference) findPreference(PREF_LOCALE);
+ mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
+
+ // Initialize the preference list
+ mPreferenceList.add(mLocale);
+ mPreferenceList.add(mFontSize);
+ mPreferenceList.add(mPreset);
+
+ refreshPreferenceViewEnabled(mCaptioningManager.isEnabled());
+
mCustom = (PreferenceCategory) findPreference(PREF_CUSTOM);
mShowingCustom = true;
@@ -304,6 +272,7 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
mWindowOpacity.setOnValueChangedListener(this);
mEdgeType.setOnValueChangedListener(this);
+ mSwitch.setOnPreferenceChangeListener(this);
mTypeface.setOnPreferenceChangeListener(this);
mFontSize.setOnPreferenceChangeListener(this);
mLocale.setOnPreferenceChangeListener(this);
@@ -338,6 +307,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
final String rawLocale = mCaptioningManager.getRawLocale();
mLocale.setValue(rawLocale == null ? "" : rawLocale);
+
+ mSwitch.setChecked(mCaptioningManager.isEnabled());
}
/**
@@ -431,16 +402,22 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
if (mTypeface == preference) {
Settings.Secure.putString(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE, (String) value);
+ refreshPreviewText();
} else if (mFontSize == preference) {
Settings.Secure.putFloat(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
Float.parseFloat((String) value));
+ refreshPreviewText();
} else if (mLocale == preference) {
Settings.Secure.putString(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE, (String) value);
+ refreshPreviewText();
+ } else if (mSwitch == preference) {
+ Settings.Secure.putInt(
+ cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, (boolean) value ? 1 : 0);
+ refreshPreferenceViewEnabled((boolean) value);
}
- refreshPreviewText();
return true;
}
}
diff --git a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
index c3cb34fbcbc..b96d2b76725 100644
--- a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
@@ -132,9 +134,10 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
if (info.getComponentName().equals(assignedComponentName)) {
final CharSequence assignedServiceName = info.getResolveInfo().loadLabel(
context.getPackageManager());
- return context.getString(
- R.string.accessibility_screen_magnification_navbar_configuration_warning,
- assignedServiceName);
+ final int messageId = isGestureNavigateEnabled(context)
+ ? R.string.accessibility_screen_magnification_gesture_navigation_warning
+ : R.string.accessibility_screen_magnification_navbar_configuration_warning;
+ return context.getString(messageId, assignedServiceName);
}
}
}
@@ -158,6 +161,12 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
}
+ private static boolean isGestureNavigateEnabled(Context context) {
+ return context.getResources().getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode)
+ == NAV_BAR_MODE_GESTURAL;
+ }
+
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
@@ -173,4 +182,4 @@ public final class MagnificationPreferenceFragment extends DashboardFragment {
return isApplicable(context.getResources());
}
};
-}
+}
\ No newline at end of file
diff --git a/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java b/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java
index d887634a540..b0d49390cd0 100644
--- a/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppStoragePreferenceController.java
@@ -31,6 +31,7 @@ import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppStorageSettings;
import com.android.settings.applications.FetchPackageStorageAsyncLoader;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
@@ -48,9 +49,12 @@ public class AppStoragePreferenceController extends AppInfoPreferenceControllerB
@Override
public void updateState(Preference preference) {
- final boolean isExternal =
- (mParent.getAppEntry().info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
- preference.setSummary(getStorageSummary(mLastResult, isExternal));
+ final ApplicationsState.AppEntry entry = mParent.getAppEntry();
+ if (entry != null && entry.info != null) {
+ final boolean isExternal =
+ (entry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
+ preference.setSummary(getStorageSummary(mLastResult, isExternal));
+ }
}
@Override
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index c3f794f6905..c23aee659cc 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -172,11 +172,11 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
if (mUserId == UserHandle.USER_NULL) {
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(titleResId),
- null, null, challenge);
+ null, null, challenge, true /* foregroundOnly */);
} else {
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(titleResId),
- null, null, challenge, mUserId);
+ null, null, challenge, mUserId, true /* foregroundOnly */);
}
if (!launchedConfirmationActivity) {
// This shouldn't happen, as we should only end up at this step if a lock thingy is
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index d5414c9664d..d94686e3f27 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -47,6 +47,8 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
private boolean mHasPassword;
private boolean mBiometricUnlockDisabledByAdmin;
private TextView mErrorText;
+ protected boolean mConfirmingCredentials;
+ protected boolean mNextClicked;
/**
* @return true if the biometric is disabled by a device administrator
@@ -149,10 +151,12 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
if (!mHasPassword) {
// No password registered, launch into enrollment wizard.
+ mConfirmingCredentials = true;
launchChooseLock();
} else if (mToken == null) {
// It's possible to have a token but mLaunchedConfirmLock == false, since
// ChooseLockGeneric can pass us a token.
+ mConfirmingCredentials = true;
launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
}
}
@@ -182,6 +186,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
@Override
protected void onNextButtonClick(View view) {
+ mNextClicked = true;
if (checkMaxEnrolled() == 0) {
// Lock thingy is already set up, launch directly to the next page
launchNextEnrollingActivity(mToken);
@@ -249,12 +254,14 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
+ mConfirmingCredentials = false;
return;
} else {
setResult(resultCode, data);
finish();
}
} else if (requestCode == CONFIRM_REQUEST) {
+ mConfirmingCredentials = false;
if (resultCode == RESULT_OK && data != null) {
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
index dffc67de169..f6ba0f989e5 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
@@ -60,6 +60,8 @@ public class FaceEnrollAccessibilityToggle extends LinearLayout {
}
mSwitch = findViewById(R.id.toggle);
mSwitch.setChecked(false);
+ mSwitch.setClickable(false);
+ mSwitch.setFocusable(false);
}
public boolean isChecked() {
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
index 956ba49d6be..e1253c14796 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -16,7 +16,6 @@
package com.android.settings.biometrics.face;
-import static android.provider.Settings.Secure.FACE_UNLOCK_EDUCATION_INFO_DISPLAYED;
import static android.security.KeyStore.getApplicationContext;
import android.app.settings.SettingsEnums;
@@ -50,8 +49,6 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
private static final String TAG = "FaceEducation";
private static final int ON = 1;
private static final int OFF = 0;
- // 8 seconds.
- private static final long FACE_ENROLL_EDUCATION_DELAY = 8000;
private FaceManager mFaceManager;
private FaceEnrollAccessibilityToggle mSwitchDiversity;
@@ -61,6 +58,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
private Handler mHandler;
private Intent mResultIntent;
private TextView mDescriptionText;
+ private boolean mNextClicked;
private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
new CompoundButton.OnCheckedChangeListener() {
@@ -101,14 +99,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
mDescriptionText = findViewById(R.id.sud_layout_description);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_enrolling_skip)
- .setListener(this::onSkipButtonClick)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build()
- );
+
+ if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.skip_label)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+ } else {
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_introduction_cancel)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.CANCEL)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+ }
final FooterButton footerButton = new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_education_start)
@@ -121,24 +131,15 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
final AccessibilityManager accessibilityManager = getApplicationContext().getSystemService(
AccessibilityManager.class);
if (accessibilityManager != null) {
- accessibilityEnabled = accessibilityManager.isEnabled();
+ // Add additional check for touch exploration. This prevents other accessibility
+ // features such as Live Transcribe from defaulting to the accessibility setup.
+ accessibilityEnabled = accessibilityManager.isEnabled()
+ && accessibilityManager.isTouchExplorationEnabled();
}
mFooterBarMixin.setPrimaryButton(footerButton);
- final Context context = getApplicationContext();
- final boolean didDisplayEdu = Settings.Secure.getIntForUser(context.getContentResolver(),
- FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, OFF, mUserId) == ON;
- if (!didDisplayEdu && !accessibilityEnabled) {
- Settings.Secure.putIntForUser(context.getContentResolver(),
- FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, ON, mUserId);
- footerButton.setEnabled(false);
- mHandler.postDelayed(() -> {
- footerButton.setEnabled(true);
- }, FACE_ENROLL_EDUCATION_DELAY);
- }
final Button accessibilityButton = findViewById(R.id.accessibility_button);
accessibilityButton.setOnClickListener(view -> {
- footerButton.setEnabled(true);
mSwitchDiversity.setChecked(true);
accessibilityButton.setVisibility(View.GONE);
mSwitchDiversity.setVisibility(View.VISIBLE);
@@ -146,6 +147,9 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mSwitchDiversity.setListener(mSwitchDiversityListener);
+ mSwitchDiversity.setOnClickListener(v -> {
+ mSwitchDiversity.getSwitch().toggle();
+ });
if (accessibilityEnabled) {
accessibilityButton.callOnClick();
@@ -157,6 +161,26 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
super.onResume();
mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
mSwitchDiversity.isChecked());
+
+ // If the user goes back after enrollment, we should send them back to the intro page
+ // if they've met the max limit.
+ final int max = getResources().getInteger(
+ com.android.internal.R.integer.config_faceMaxTemplatesPerUser);
+ final int numEnrolledFaces = mFaceManager.getEnrolledFaces(mUserId).size();
+ if (numEnrolledFaces >= max) {
+ finish();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ if (!isChangingConfigurations() && !WizardManagerHelper.isAnySetupWizard(getIntent())
+ && !mNextClicked) {
+ setResult(RESULT_SKIP);
+ finish();
+ }
}
@Override
@@ -168,6 +192,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
+ intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
final String flattenedString = getString(R.string.config_face_enroll);
if (!TextUtils.isEmpty(flattenedString)) {
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
@@ -175,11 +200,12 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
} else {
intent.setClass(this, FaceEnrollEnrolling.class);
}
- intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
if (mResultIntent != null) {
intent.putExtras(mResultIntent);
}
- WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ mNextClicked = true;
+ intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
index ea2fa5c438b..bf4a1d46187 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
@@ -32,6 +32,7 @@ import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.biometrics.BiometricErrorDialog;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
+import com.android.settings.slices.CustomSliceRegistry;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
@@ -184,6 +185,10 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
// TODO: Have this match any animations that UX comes up with
if (remaining == 0) {
+ // Force the reload of the FaceEnroll slice in case a user has enrolled,
+ // this will cause the slice to no longer appear.
+ getApplicationContext().getContentResolver().notifyChange(
+ CustomSliceRegistry.FACE_ENROLL_SLICE_URI, null);
launchFinish(mToken);
}
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 525c1a3ee42..6686c96f928 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -77,6 +77,16 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
);
}
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ if (!isChangingConfigurations() && !mConfirmingCredentials && !mNextClicked
+ && !WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ finish();
+ }
+ }
+
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
index c75f300aa8e..512d8fe4de6 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
@@ -52,7 +52,7 @@ public class FaceEnrollSidecar extends BiometricEnrollSidecar {
mFaceManager.setActiveUser(mUserId);
}
- mFaceManager.enroll(mToken, mEnrollmentCancel,
+ mFaceManager.enroll(mUserId, mToken, mEnrollmentCancel,
mEnrollmentCallback, mDisabledFeatures);
}
diff --git a/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java
index 196992dbd9d..56b325bdf89 100644
--- a/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java
@@ -19,14 +19,30 @@ package com.android.settings.biometrics.face;
import android.content.Context;
import android.os.UserHandle;
+import com.android.settings.R;
+
+import androidx.preference.Preference;
+
public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceController {
- public static final String KEY_FACE_SETTINGS = "face_settings_profile";
+ private static final String KEY_FACE_SETTINGS = "face_settings_profile";
public FaceProfileStatusPreferenceController(Context context) {
super(context, KEY_FACE_SETTINGS);
}
+ @Override
+ public int getAvailabilityStatus() {
+ // Check if Face for Profile is available.
+ final int isAvailable = super.getAvailabilityStatus();
+ if (isAvailable != AVAILABLE) {
+ return isAvailable;
+ }
+ // Make the profile unsearchable so the user preference controller gets highlighted
+ // when searched for.
+ return AVAILABLE_UNSEARCHABLE;
+ }
+
@Override
protected boolean isUserSupported() {
return mProfileChallengeUserId != UserHandle.USER_NULL
@@ -37,4 +53,11 @@ public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceC
protected int getUserId() {
return mProfileChallengeUserId;
}
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ preference.setTitle(mContext.getResources().getString(
+ R.string.security_settings_face_profile_preference_title));
+ }
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index 48370d9fb78..b8bb030bc43 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -60,7 +60,6 @@ public class FaceSettings extends DashboardFragment {
private FaceManager mFaceManager;
private int mUserId;
private byte[] mToken;
- private FaceSettingsAttentionPreferenceController mAttentionController;
private FaceSettingsRemoveButtonPreferenceController mRemoveController;
private FaceSettingsEnrollButtonPreferenceController mEnrollController;
private List mControllers;
@@ -69,6 +68,8 @@ public class FaceSettings extends DashboardFragment {
private Preference mRemoveButton;
private Preference mEnrollButton;
+ private boolean mConfirmingPassword;
+
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
// Disable the toggles until the user re-enrolls
@@ -117,12 +118,18 @@ public class FaceSettings extends DashboardFragment {
mUserId = getActivity().getIntent().getIntExtra(
Intent.EXTRA_USER_ID, UserHandle.myUserId());
+ if (mUserManager.getUserInfo(mUserId).isManagedProfile()) {
+ getActivity().setTitle(getActivity().getResources().getString(
+ R.string.security_settings_face_profile_preference_title));
+ }
+
Preference keyguardPref = findPreference(FaceSettingsKeyguardPreferenceController.KEY);
Preference appPref = findPreference(FaceSettingsAppPreferenceController.KEY);
- Preference attentionPref = findPreference(FaceSettingsAttentionPreferenceController.KEY);
Preference confirmPref = findPreference(FaceSettingsConfirmPreferenceController.KEY);
+ Preference bypassPref =
+ findPreference(FaceSettingsLockscreenBypassPreferenceController.KEY);
mTogglePreferences = new ArrayList<>(
- Arrays.asList(keyguardPref, appPref, attentionPref, confirmPref));
+ Arrays.asList(keyguardPref, appPref, confirmPref, bypassPref));
mRemoveButton = findPreference(FaceSettingsRemoveButtonPreferenceController.KEY);
mEnrollButton = findPreference(FaceSettingsEnrollButtonPreferenceController.KEY);
@@ -145,24 +152,27 @@ public class FaceSettings extends DashboardFragment {
if (savedInstanceState != null) {
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
}
-
- if (mToken == null) {
- final long challenge = mFaceManager.generateChallenge();
- ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
- if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
- getString(R.string.security_settings_face_preference_title),
- null, null, challenge, mUserId)) {
- Log.e(TAG, "Password not set");
- finish();
- }
- }
}
@Override
public void onResume() {
super.onResume();
- if (mToken != null) {
- mAttentionController.setToken(mToken);
+
+ if (mToken == null && !mConfirmingPassword) {
+ // Generate challenge in onResume instead of onCreate, since FaceSettings can be
+ // created while Keyguard is showing, in which case the resetLockout revokeChallenge
+ // will invalidate the too-early created challenge here.
+ final long challenge = mFaceManager.generateChallenge();
+ ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
+
+ mConfirmingPassword = true;
+ if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
+ getString(R.string.security_settings_face_preference_title),
+ null, null, challenge, mUserId, true /* foregroundOnly */)) {
+ Log.e(TAG, "Password not set");
+ finish();
+ }
+ } else {
mEnrollController.setToken(mToken);
}
@@ -175,6 +185,7 @@ public class FaceSettings extends DashboardFragment {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CONFIRM_REQUEST) {
+ mConfirmingPassword = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
mFaceManager.setActiveUser(mUserId);
// The pin/pattern/password was set.
@@ -182,7 +193,6 @@ public class FaceSettings extends DashboardFragment {
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
if (mToken != null) {
- mAttentionController.setToken(mToken);
mEnrollController.setToken(mToken);
}
}
@@ -196,16 +206,28 @@ public class FaceSettings extends DashboardFragment {
}
@Override
- public void onDestroy() {
- super.onDestroy();
- if (getActivity().isFinishing()) {
- final int result = mFaceManager.revokeChallenge();
- if (result < 0) {
- Log.w(TAG, "revokeChallenge failed, result: " + result);
+ public void onStop() {
+ super.onStop();
+
+ if (!mEnrollController.isClicked() && !getActivity().isChangingConfigurations()
+ && !mConfirmingPassword) {
+ // Revoke challenge and finish
+ if (mToken != null) {
+ final int result = mFaceManager.revokeChallenge();
+ if (result < 0) {
+ Log.w(TAG, "revokeChallenge failed, result: " + result);
+ }
+ mToken = null;
}
+ getActivity().finish();
}
}
+ @Override
+ public int getHelpResource() {
+ return R.string.help_url_face;
+ }
+
@Override
protected List createPreferenceControllers(Context context) {
if (!isAvailable(context)) {
@@ -214,9 +236,7 @@ public class FaceSettings extends DashboardFragment {
mControllers = buildPreferenceControllers(context, getSettingsLifecycle());
// There's no great way of doing this right now :/
for (AbstractPreferenceController controller : mControllers) {
- if (controller instanceof FaceSettingsAttentionPreferenceController) {
- mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
- } else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
+ if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
mRemoveController = (FaceSettingsRemoveButtonPreferenceController) controller;
mRemoveController.setListener(mRemovalListener);
mRemoveController.setActivity((SettingsActivity) getActivity());
@@ -235,7 +255,6 @@ public class FaceSettings extends DashboardFragment {
controllers.add(new FaceSettingsVideoPreferenceController(context));
controllers.add(new FaceSettingsKeyguardPreferenceController(context));
controllers.add(new FaceSettingsAppPreferenceController(context));
- controllers.add(new FaceSettingsAttentionPreferenceController(context));
controllers.add(new FaceSettingsRemoveButtonPreferenceController(context));
controllers.add(new FaceSettingsFooterPreferenceController(context));
controllers.add(new FaceSettingsConfirmPreferenceController(context));
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
index 70c00e54d28..a54171e8c42 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
@@ -78,6 +78,19 @@ public class FaceSettingsAppPreferenceController extends FaceSettingsPreferenceC
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ if(mFaceManager == null){
+ return AVAILABLE_UNSEARCHABLE;
+ }
+
+ // By only allowing this preference controller to be searchable when the feature is turned
+ // off, it will give preference to the face setup controller.
+ final boolean hasEnrolledUser = mFaceManager.hasEnrolledTemplates(getUserId());
+ final boolean appUnlockEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED, OFF, getUserId()) == ON;
+ if (hasEnrolledUser && !appUnlockEnabled) {
+ return AVAILABLE;
+ } else {
+ return AVAILABLE_UNSEARCHABLE;
+ }
}
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index ef90b1eda34..9ae6a874b0a 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -99,7 +99,8 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
}
// Set to disabled until we know the true value.
mPreference.setEnabled(false);
- mFaceManager.getFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, mGetFeatureCallback);
+ mFaceManager.getFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION,
+ mGetFeatureCallback);
// Ideally returns a cached value.
return true;
@@ -111,8 +112,8 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
mPreference.setEnabled(false);
mPreference.setChecked(isChecked);
- mFaceManager.setFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked, mToken,
- mSetFeatureCallback);
+ mFaceManager.setFeature(getUserId(), FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked,
+ mToken, mSetFeatureCallback);
return true;
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java
index ec7b1948fea..a087ccc78e4 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java
@@ -42,6 +42,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
private byte[] mToken;
private SettingsActivity mActivity;
private Button mButton;
+ private boolean mIsClicked;
public FaceSettingsEnrollButtonPreferenceController(Context context) {
this(context, KEY);
@@ -63,6 +64,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
@Override
public void onClick(View v) {
+ mIsClicked = true;
final Intent intent = new Intent();
intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName());
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
@@ -83,6 +85,13 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference
mToken = token;
}
+ // Return the click state, then clear its state.
+ public boolean isClicked() {
+ final boolean wasClicked = mIsClicked;
+ mIsClicked = false;
+ return wasClicked;
+ }
+
public void setActivity(SettingsActivity activity) {
mActivity = activity;
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
index c64455af30b..9ec1ad1eb74 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
@@ -18,16 +18,13 @@ package com.android.settings.biometrics.face;
import static android.provider.Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED;
-import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.hardware.face.FaceManager;
-import android.os.UserHandle;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.Utils;
-import com.android.settings.core.TogglePreferenceController;
/**
* Preference controller for Face settings page controlling the ability to unlock the phone
@@ -87,13 +84,4 @@ public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
preference.setEnabled(true);
}
}
-
- private boolean adminDisabled() {
- DevicePolicyManager dpm =
- (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- return dpm != null &&
- (dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
- & DevicePolicyManager.KEYGUARD_DISABLE_FACE)
- != 0;
- }
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
new file mode 100644
index 00000000000..15fab260dc9
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
@@ -0,0 +1,89 @@
+/*
+ * 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 android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.face.FaceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+public class FaceSettingsLockscreenBypassPreferenceController
+ extends FaceSettingsPreferenceController {
+
+ static final String KEY = "security_lockscreen_bypass";
+
+ @VisibleForTesting
+ protected FaceManager mFaceManager;
+ private UserManager mUserManager;
+
+ public FaceSettingsLockscreenBypassPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ mFaceManager = context.getSystemService(FaceManager.class);
+ }
+
+ mUserManager = context.getSystemService(UserManager.class);
+ }
+
+ @Override
+ public boolean isChecked() {
+ boolean defaultValue = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_faceAuthDismissesKeyguard);
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, defaultValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, isChecked ? 1 : 0);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (!FaceSettings.isAvailable(mContext)) {
+ preference.setEnabled(false);
+ } else if (adminDisabled()) {
+ preference.setEnabled(false);
+ } else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
+ preference.setEnabled(false);
+ } else {
+ preference.setEnabled(true);
+ }
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mUserManager.isManagedProfile(UserHandle.myUserId())) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
+ if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
+ return mFaceManager.hasEnrolledTemplates() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ } else {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
index b8ac118551e..55e093ba79a 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
@@ -16,7 +16,9 @@
package com.android.settings.biometrics.face;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.os.UserHandle;
import com.android.settings.core.TogglePreferenceController;
@@ -38,4 +40,13 @@ public abstract class FaceSettingsPreferenceController extends TogglePreferenceC
protected int getUserId() {
return mUserId;
}
+
+ protected boolean adminDisabled() {
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ return dpm != null &&
+ (dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
+ & DevicePolicyManager.KEYGUARD_DISABLE_FACE)
+ != 0;
+ }
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index d532a7636f4..1c1b81df6c8 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -64,7 +64,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
builder.setTitle(R.string.security_settings_face_settings_remove_dialog_title)
.setMessage(R.string.security_settings_face_settings_remove_dialog_details)
- .setPositiveButton(R.string.okay, mOnClickListener)
+ .setPositiveButton(R.string.delete, mOnClickListener)
.setNegativeButton(R.string.cancel, mOnClickListener);
AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
diff --git a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
index 84505772092..cb82b5e8563 100644
--- a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java
@@ -26,7 +26,7 @@ import com.android.settings.biometrics.BiometricStatusPreferenceController;
public class FaceStatusPreferenceController extends BiometricStatusPreferenceController {
- private static final String KEY_FACE_SETTINGS = "face_settings";
+ public static final String KEY_FACE_SETTINGS = "face_settings";
protected final FaceManager mFaceManager;
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index ad0ae6fd968..3fbcfd4be96 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -617,7 +617,7 @@ public class FingerprintSettings extends SubSettings {
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
getString(R.string.security_settings_fingerprint_preference_title),
- null, null, challenge, mUserId)) {
+ null, null, challenge, mUserId, true /* foregroundOnly */)) {
intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName());
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index aba95c80cc7..f384d8570ce 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -494,12 +494,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle));
controllers.add(new AutofillResetOptionsPreferenceController(context));
- controllers.add(new OverlayCategoryPreferenceController(context,
- "android.theme.customization.accent_color"));
- controllers.add(new OverlayCategoryPreferenceController(context,
- "android.theme.customization.font"));
- controllers.add(new OverlayCategoryPreferenceController(context,
- "android.theme.customization.adaptive_icon_shape"));
controllers.add(new TrustAgentsExtendUnlockPreferenceController(context));
controllers.add(new TrustLostLocksScreenPreferenceController(context));
return controllers;
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
index ff9352a7d4b..fd54f19b819 100644
--- a/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
@@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;
+import android.text.format.DateFormat;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -28,9 +29,20 @@ import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.TimeZone;
+
public class MainlineModuleVersionPreferenceController extends BasePreferenceController {
private static final String TAG = "MainlineModuleControl";
+ private static final List VERSION_NAME_DATE_PATTERNS = Arrays.asList("yyyy-MM-dd",
+ "yyyy-MM");
@VisibleForTesting
static final Intent MODULE_UPDATE_INTENT =
@@ -81,6 +93,30 @@ public class MainlineModuleVersionPreferenceController extends BasePreferenceCon
@Override
public CharSequence getSummary() {
- return mModuleVersion;
+ if (TextUtils.isEmpty(mModuleVersion)) {
+ return mModuleVersion;
+ }
+
+ final Optional parsedDate = parseDateFromVersionName(mModuleVersion);
+ if (!parsedDate.isPresent()) {
+ Log.w("Could not parse mainline versionName (%s) as date.", mModuleVersion);
+ return mModuleVersion;
+ }
+
+ return DateFormat.getLongDateFormat(mContext).format(parsedDate.get());
+ }
+
+ private Optional parseDateFromVersionName(String text) {
+ for (String pattern : VERSION_NAME_DATE_PATTERNS) {
+ try {
+ final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern,
+ Locale.getDefault());
+ simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return Optional.of(simpleDateFormat.parse(text));
+ } catch (ParseException e) {
+ // ignore and try next pattern
+ }
+ }
+ return Optional.empty();
}
}
diff --git a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java
index 5ce7be5b43e..0e2358c806b 100644
--- a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java
@@ -21,6 +21,7 @@ import android.content.Context;
import androidx.preference.Preference;
public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPreferenceController {
+
public AdaptiveSleepDetailPreferenceController(Context context, String key) {
super(context, key);
}
@@ -42,6 +43,6 @@ public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPrefer
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- preference.setEnabled(super.hasSufficientPermissions);
+ preference.setEnabled(hasSufficientPermission(mContext.getPackageManager()));
}
-}
+}
\ No newline at end of file
diff --git a/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.java
new file mode 100644
index 00000000000..9e6bca453e4
--- /dev/null
+++ b/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.java
@@ -0,0 +1,63 @@
+/*
+ * 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.display;
+
+import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class AdaptiveSleepPermissionPreferenceController extends BasePreferenceController {
+ final static String PREF_NAME = "adaptive_sleep_permission";
+ private final Intent mIntent;
+
+ public AdaptiveSleepPermissionPreferenceController(Context context, String key) {
+ super(context, key);
+ final String packageName = context.getPackageManager().getAttentionServicePackageName();
+ mIntent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ mIntent.setData(Uri.parse("package:" + packageName));
+ }
+
+ @Override
+ @AvailabilityStatus
+ public int getAvailabilityStatus() {
+ return AVAILABLE_UNSEARCHABLE;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
+ mContext.startActivity(mIntent);
+ return true;
+ }
+ return super.handlePreferenceTreeClick(preference);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
+ preference.setVisible(!hasSufficientPermission(mContext.getPackageManager()));
+ }
+ }
+}
diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
index 6b91792800e..b736b79575f 100644
--- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
@@ -25,28 +25,20 @@ import com.android.settings.core.TogglePreferenceController;
public class AdaptiveSleepPreferenceController extends TogglePreferenceController {
-
- private final String SYSTEM_KEY = ADAPTIVE_SLEEP;
- private final int DEFAULT_VALUE = 0;
-
- final boolean hasSufficientPermissions;
+ public static final String PREF_NAME = "adaptive_sleep";
+ private static final String SYSTEM_KEY = ADAPTIVE_SLEEP;
+ private static final int DEFAULT_VALUE = 0;
public AdaptiveSleepPreferenceController(Context context, String key) {
super(context, key);
-
- final PackageManager packageManager = mContext.getPackageManager();
- final String attentionPackage = packageManager.getAttentionServicePackageName();
- hasSufficientPermissions = attentionPackage != null && packageManager.checkPermission(
- Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
}
@Override
public boolean isChecked() {
- return hasSufficientPermissions && Settings.System.getInt(mContext.getContentResolver(),
- SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
+ return hasSufficientPermission(mContext.getPackageManager()) && Settings.System.getInt(
+ mContext.getContentResolver(), SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
}
-
@Override
public boolean setChecked(boolean isChecked) {
Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY,
@@ -57,10 +49,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
- return mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_adaptive_sleep_available)
- ? AVAILABLE_UNSEARCHABLE
- : UNSUPPORTED_ON_DEVICE;
+ return isControllerAvailable(mContext);
}
@Override
@@ -69,4 +58,17 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
? R.string.adaptive_sleep_summary_on
: R.string.adaptive_sleep_summary_off);
}
+
+ public static int isControllerAvailable(Context context) {
+ return context.getResources().getBoolean(
+ com.android.internal.R.bool.config_adaptive_sleep_available)
+ ? AVAILABLE_UNSEARCHABLE
+ : UNSUPPORTED_ON_DEVICE;
+ }
+
+ static boolean hasSufficientPermission(PackageManager packageManager) {
+ final String attentionPackage = packageManager.getAttentionServicePackageName();
+ return attentionPackage != null && packageManager.checkPermission(
+ Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
+ }
}
diff --git a/src/com/android/settings/display/AdaptiveSleepSettings.java b/src/com/android/settings/display/AdaptiveSleepSettings.java
index 4c17a67b717..66e20b4b8fd 100644
--- a/src/com/android/settings/display/AdaptiveSleepSettings.java
+++ b/src/com/android/settings/display/AdaptiveSleepSettings.java
@@ -16,11 +16,16 @@
package com.android.settings.display;
+import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
+import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED;
+
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
+import androidx.preference.Preference;
+
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -34,14 +39,28 @@ import java.util.List;
public class AdaptiveSleepSettings extends DashboardFragment {
private static final String TAG = "AdaptiveSleepSettings";
+ private Context mContext;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final FooterPreference footerPreference =
mFooterPreferenceMixin.createFooterPreference();
+ mContext = getContext();
+
footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
footerPreference.setTitle(R.string.adaptive_sleep_privacy);
+
+ Preference permissionPreference = findPreference(
+ AdaptiveSleepPermissionPreferenceController.PREF_NAME);
+ if (permissionPreference != null) {
+ permissionPreference.setVisible(false);
+ }
+
+ mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
+ .edit()
+ .putBoolean(PREF_KEY_INTERACTED, true)
+ .apply();
}
@Override
diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java
index c28de731ffe..598d9c16bd0 100644
--- a/src/com/android/settings/display/ColorModePreferenceFragment.java
+++ b/src/com/android/settings/display/ColorModePreferenceFragment.java
@@ -213,5 +213,13 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
sir.xmlResId = R.xml.color_mode_settings;
return Arrays.asList(sir);
}
+
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ final int[] availableColorModes = context.getResources().getIntArray(
+ com.android.internal.R.array.config_availableColorModes);
+ return availableColorModes != null && availableColorModes.length > 0
+ && !ColorDisplayManager.areAccessibilityTransformsEnabled(context);
+ }
};
}
diff --git a/src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java b/src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java
deleted file mode 100644
index 6e8b4142d8b..00000000000
--- a/src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.gestures;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.os.Bundle;
-
-import com.android.settings.R;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-
-/**
- * Dialog to notify user that gesture navigation is not available because of unsupported launcher.
- */
-public class GestureNavigationNotAvailableDialog extends InstrumentedDialogFragment {
- private static final String TAG = "GestureNavigationNotAvailableDialog";
-
- public static void show(SystemNavigationGestureSettings parent) {
- if (!parent.isAdded()) {
- return;
- }
-
- final GestureNavigationNotAvailableDialog dialog =
- new GestureNavigationNotAvailableDialog();
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.SETTINGS_GESTURE_NAV_NOT_AVAILABLE_DLG;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
- final String defaultHomeAppName = SystemNavigationPreferenceController
- .getDefaultHomeAppName(context);
- final String message = getString(R.string.gesture_not_supported_dialog_message,
- defaultHomeAppName);
- return new AlertDialog.Builder(context)
- .setMessage(message)
- .setPositiveButton(R.string.okay, null)
- .create();
- }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index b3d090d75f2..3def7804bb5 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -22,7 +22,6 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVE
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE;
-import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO;
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_SETTING;
import android.accessibilityservice.AccessibilityServiceInfo;
@@ -160,17 +159,9 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
RadioButtonPreferenceWithExtraWidget p = (RadioButtonPreferenceWithExtraWidget) pref;
if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL) {
- if (SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(
- getContext())) {
- p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
- p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog
- .show(this, getBackSensitivity(getContext(), mOverlayManager)));
- } else {
- p.setEnabled(false);
- p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO);
- p.setExtraWidgetOnClickListener((v) ->
- GestureNavigationNotAvailableDialog.show(this));
- }
+ p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
+ p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog
+ .show(this, getBackSensitivity(getContext(), mOverlayManager)));
} else {
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE);
}
@@ -219,12 +210,6 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
@Override
protected boolean setDefaultKey(String key) {
final Context c = getContext();
- if (key == KEY_SYSTEM_NAV_GESTURAL &&
- !SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(c)) {
- // This should not happen since the preference is disabled. Return to be safe.
- return false;
- }
-
setCurrentSystemNavigationMode(c, mOverlayManager, key);
setIllustrationVideo(mVideoPreference, key);
if (TextUtils.equals(KEY_SYSTEM_NAV_GESTURAL, key) && (
diff --git a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
index a151dc1746c..d0d81552ff5 100644
--- a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
@@ -22,14 +22,11 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
-import java.util.ArrayList;
-
public class SystemNavigationPreferenceController extends BasePreferenceController {
static final String PREF_KEY_SYSTEM_NAVIGATION = "gesture_system_navigation";
@@ -101,31 +98,4 @@ public class SystemNavigationPreferenceController extends BasePreferenceControll
return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode);
}
-
- static boolean isGestureNavSupportedByDefaultLauncher(Context context) {
- final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
- if (cn == null) {
- // There is no default home app set for the current user, don't make any changes yet.
- return true;
- }
- ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
- com.android.internal.R.string.config_recentsComponentName));
- return recentsComponentName.getPackageName().equals(cn.getPackageName());
- }
-
- static String getDefaultHomeAppName(Context context) {
- final PackageManager pm = context.getPackageManager();
- final ComponentName cn = pm.getHomeActivities(new ArrayList<>());
- if (cn != null) {
- try {
- ApplicationInfo ai = pm.getApplicationInfo(cn.getPackageName(), 0);
- if (ai != null) {
- return pm.getApplicationLabel(ai).toString();
- }
- } catch (final PackageManager.NameNotFoundException e) {
- // Do nothing
- }
- }
- return "";
- }
}
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 86fee03e556..385f8cda010 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -64,12 +64,28 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
.setCardName(contextualNotificationChannelSliceUri)
.setCardCategory(ContextualCard.Category.POSSIBLE)
.build();
+ final String contextualAdaptiveSleepSliceUri =
+ CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI.toString();
+ final ContextualCard contextualAdaptiveSleepCard =
+ ContextualCard.newBuilder()
+ .setSliceUri(contextualAdaptiveSleepSliceUri)
+ .setCardName(contextualAdaptiveSleepSliceUri)
+ .setCardCategory(ContextualCard.Category.DEFAULT)
+ .build();
+ final ContextualCard contextualFaceSettingsCard =
+ ContextualCard.newBuilder()
+ .setSliceUri(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
+ .setCardCategory(ContextualCard.Category.DEFAULT)
+ .build();
final ContextualCardList cards = ContextualCardList.newBuilder()
.addCard(wifiCard)
.addCard(connectedDeviceCard)
.addCard(lowStorageCard)
.addCard(batteryFixCard)
.addCard(notificationChannelCard)
+ .addCard(contextualAdaptiveSleepCard)
+ .addCard(contextualFaceSettingsCard)
.build();
return cards;
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java
new file mode 100644
index 00000000000..3da57634e58
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java
@@ -0,0 +1,156 @@
+/*
+ * 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.homepage.contextualcards.slices;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
+import static com.android.settings.display.AdaptiveSleepPreferenceController.PREF_NAME;
+import static com.android.settings.display.AdaptiveSleepPreferenceController.isControllerAvailable;
+import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI;
+
+import android.app.PendingIntent;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.SubSettings;
+import com.android.settings.display.AdaptiveSleepSettings;
+import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBuilderUtils;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.concurrent.TimeUnit;
+
+public class ContextualAdaptiveSleepSlice implements CustomSliceable {
+ private static final String TAG = "ContextualAdaptiveSleepSlice";
+ private static final long DEFAULT_SETUP_TIME = 0;
+ private Context mContext;
+
+ @VisibleForTesting
+ static final long DEFERRED_TIME_DAYS = TimeUnit.DAYS.toMillis(14);
+ @VisibleForTesting
+ static final String PREF_KEY_SETUP_TIME = "adaptive_sleep_setup_time";
+
+ public static final String PREF_KEY_INTERACTED = "adaptive_sleep_interacted";
+ public static final String PREF = "adaptive_sleep_slice";
+
+ public ContextualAdaptiveSleepSlice(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public Slice getSlice() {
+ final long setupTime = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getLong(
+ PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
+ if (setupTime == DEFAULT_SETUP_TIME) {
+ // Set the first setup time.
+ mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
+ .edit()
+ .putLong(PREF_KEY_SETUP_TIME, System.currentTimeMillis())
+ .apply();
+ return null;
+ }
+
+ // Display the contextual card only if all the following 3 conditions hold:
+ // 1. The Screen Attention is enabled in Settings.
+ // 2. The device is not recently set up.
+ // 3. Current user hasn't opened Screen Attention's settings page before.
+ if (isSettingsAvailable() && !isUserInteracted() && !isRecentlySetup()) {
+ final IconCompat icon = IconCompat.createWithResource(mContext,
+ R.drawable.ic_settings_adaptive_sleep);
+ final CharSequence title = mContext.getText(R.string.adaptive_sleep_title);
+ final CharSequence subtitle = mContext.getText(
+ R.string.adaptive_sleep_contextual_slice_summary);
+
+ final SliceAction pAction = SliceAction.createDeeplink(getPrimaryAction(),
+ icon,
+ ListBuilder.ICON_IMAGE,
+ title);
+ final ListBuilder listBuilder = new ListBuilder(mContext,
+ CONTEXTUAL_ADAPTIVE_SLEEP_URI,
+ ListBuilder.INFINITY)
+ .setAccentColor(COLOR_NOT_TINTED)
+ .addRow(new ListBuilder.RowBuilder()
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
+ .setTitle(title)
+ .setSubtitle(subtitle)
+ .setPrimaryAction(pAction));
+ return listBuilder.build();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Uri getUri() {
+ return CONTEXTUAL_ADAPTIVE_SLEEP_URI;
+ }
+
+ @Override
+ public Intent getIntent() {
+ final CharSequence screenTitle = mContext.getText(R.string.adaptive_sleep_title);
+ final Uri contentUri = new Uri.Builder().appendPath(PREF_NAME).build();
+ return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
+ AdaptiveSleepSettings.class.getName(), PREF_NAME, screenTitle.toString(),
+ SettingsEnums.SLICE).setClassName(mContext.getPackageName(),
+ SubSettings.class.getName()).setData(contentUri);
+ }
+
+ private PendingIntent getPrimaryAction() {
+ final Intent intent = getIntent();
+ return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
+ }
+
+ /**
+ * @return {@code true} if the current user has opened the Screen Attention settings page
+ * before, otherwise {@code false}.
+ */
+ private boolean isUserInteracted() {
+ return mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getBoolean(
+ PREF_KEY_INTERACTED, false);
+ }
+
+ /**
+ * The device is recently set up means its first settings-open time is within 2 weeks ago.
+ *
+ * @return {@code true} if the device is recently set up, otherwise {@code false}.
+ */
+ private boolean isRecentlySetup() {
+ final long endTime = System.currentTimeMillis() - DEFERRED_TIME_DAYS;
+ final long firstSetupTime = mContext.getSharedPreferences(PREF,
+ Context.MODE_PRIVATE).getLong(PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
+ return firstSetupTime > endTime;
+ }
+
+ /**
+ * Check whether the screen attention settings is enabled. Contextual card will only appear
+ * when the screen attention settings is available.
+ *
+ * @return {@code true} if screen attention settings is enabled, otherwise {@code false}
+ */
+ @VisibleForTesting
+ boolean isSettingsAvailable() {
+ return isControllerAvailable(mContext) == AVAILABLE_UNSEARCHABLE;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.java b/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.java
new file mode 100644
index 00000000000..112f6557019
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSlice.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.homepage.contextualcards.slices;
+
+
+import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
+
+import android.app.PendingIntent;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.face.FaceManager;
+import android.net.Uri;
+import android.os.UserHandle;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.ListBuilder.RowBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.SubSettings;
+import com.android.settings.Utils;
+import com.android.settings.biometrics.face.FaceStatusPreferenceController;
+import com.android.settings.security.SecuritySettings;
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBuilderUtils;
+
+public class FaceSetupSlice implements CustomSliceable {
+
+ private final Context mContext;
+
+ public FaceSetupSlice(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public Slice getSlice() {
+ final FaceManager faceManager = Utils.getFaceManagerOrNull(mContext);
+ if (faceManager == null || faceManager.hasEnrolledTemplates(UserHandle.myUserId())) {
+ return null;
+ }
+
+ final CharSequence title = mContext.getText(
+ R.string.security_settings_face_settings_enroll);
+ final ListBuilder listBuilder = new ListBuilder(mContext,
+ CustomSliceRegistry.FACE_ENROLL_SLICE_URI, ListBuilder.INFINITY)
+ .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
+ final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_face_24dp);
+ return listBuilder
+ .addRow(buildRowBuilder(title,
+ mContext.getText(R.string.security_settings_face_settings_context_subtitle),
+ icon, mContext, getIntent()))
+ .build();
+ }
+
+ @Override
+ public Uri getUri() {
+ return CustomSliceRegistry.FACE_ENROLL_SLICE_URI;
+ }
+
+ @Override
+ public Intent getIntent() {
+ return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
+ SecuritySettings.class.getName(),
+ FaceStatusPreferenceController.KEY_FACE_SETTINGS,
+ mContext.getText(R.string.security_settings_face_settings_enroll).toString(),
+ SettingsEnums.SLICE)
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ }
+
+ private static RowBuilder buildRowBuilder(CharSequence title, CharSequence subTitle,
+ IconCompat icon, Context context, Intent intent) {
+ final SliceAction primarySliceAction = SliceAction.createDeeplink(
+ PendingIntent.getActivity(context, 0, intent, 0), icon, ListBuilder.ICON_IMAGE,
+ title);
+ return new RowBuilder()
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
+ .setTitle(title)
+ .setSubtitle(subTitle)
+ .setPrimaryAction(primarySliceAction);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index 0f76f24de56..bd3e2efbb6d 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -130,7 +130,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
}
private void update() {
- if (mPreference == null) {
+ if (mPreference == null || mPreference.isDisabledByAdmin()) {
return;
}
refreshSummary(mPreference);
diff --git a/src/com/android/settings/network/TetherProvisioningActivity.java b/src/com/android/settings/network/TetherProvisioningActivity.java
index 48c570791b2..53a86cb39a6 100644
--- a/src/com/android/settings/network/TetherProvisioningActivity.java
+++ b/src/com/android/settings/network/TetherProvisioningActivity.java
@@ -55,7 +55,7 @@ public class TetherProvisioningActivity extends Activity {
final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- final int subId = SubscriptionManager.getDefaultDataSubscriptionId();
+ final int subId = SubscriptionManager.getActiveDataSubscriptionId();
if (tetherSubId != subId) {
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
return;
@@ -67,6 +67,7 @@ public class TetherProvisioningActivity extends Activity {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(provisionApp[0], provisionApp[1]);
intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
if (DEBUG) {
Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
}
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 94b176107c2..79cdc2e6b60 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -16,7 +16,13 @@
package com.android.settings.network.telephony;
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
@@ -25,8 +31,12 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
@@ -37,17 +47,27 @@ import com.android.settings.R;
*/
public class EnabledNetworkModePreferenceController extends
TelephonyBasePreferenceController implements
- ListPreference.OnPreferenceChangeListener {
+ ListPreference.OnPreferenceChangeListener, LifecycleObserver {
private CarrierConfigManager mCarrierConfigManager;
+ private ContentObserver mPreferredNetworkModeObserver;
private TelephonyManager mTelephonyManager;
private boolean mIsGlobalCdma;
@VisibleForTesting
boolean mShow4GForLTE;
+ private Preference mPreference;
public EnabledNetworkModePreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+ mPreferredNetworkModeObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange) {
+ if (mPreference != null) {
+ updateState(mPreference);
+ }
+ }
+ };
}
@Override
@@ -78,6 +98,24 @@ public class EnabledNetworkModePreferenceController extends
return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
+ @OnLifecycleEvent(ON_START)
+ public void onStart() {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + mSubId), true,
+ mPreferredNetworkModeObserver);
+ }
+
+ @OnLifecycleEvent(ON_STOP)
+ public void onStop() {
+ mContext.getContentResolver().unregisterContentObserver(mPreferredNetworkModeObserver);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
@Override
public void updateState(Preference preference) {
super.updateState(preference);
@@ -102,7 +140,7 @@ public class EnabledNetworkModePreferenceController extends
return false;
}
- public void init(int subId) {
+ public void init(Lifecycle lifecycle, int subId) {
mSubId = subId;
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
@@ -115,6 +153,7 @@ public class EnabledNetworkModePreferenceController extends
? carrierConfig.getBoolean(
CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL)
: false;
+ lifecycle.addObserver(this);
}
private int getPreferredNetworkMode() {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index b8ed31f94b8..9912b4e9b61 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.view.Menu;
@@ -76,6 +77,13 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
}
};
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ updateSubscriptions(null);
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -86,13 +94,18 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
setContentView(R.layout.mobile_network_settings_container);
}
setActionBar(findViewById(R.id.mobile_action_bar));
- mPhoneChangeReceiver = new PhoneChangeReceiver(this, () -> {
- if (mCurSubscriptionId != SUB_ID_NULL) {
- // When the radio changes (ex: CDMA->GSM), refresh the fragment.
- // This is very rare.
+ mPhoneChangeReceiver = new PhoneChangeReceiver(this, new PhoneChangeReceiver.Client() {
+ @Override
+ public void onPhoneChange() {
+ // When the radio or carrier config changes (ex: CDMA->GSM), refresh the fragment.
switchFragment(new MobileNetworkSettings(), mCurSubscriptionId,
true /* forceUpdate */);
}
+
+ @Override
+ public int getSubscriptionId() {
+ return mCurSubscriptionId;
+ }
});
mSubscriptionManager = getSystemService(SubscriptionManager.class);
mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(true);
@@ -243,14 +256,12 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
@VisibleForTesting
static class PhoneChangeReceiver extends BroadcastReceiver {
- private static final IntentFilter RADIO_TECHNOLOGY_CHANGED_FILTER = new IntentFilter(
- TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
-
private Context mContext;
private Client mClient;
interface Client {
void onPhoneChange();
+ int getSubscriptionId();
}
public PhoneChangeReceiver(Context context, Client client) {
@@ -259,7 +270,10 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
}
public void register() {
- mContext.registerReceiver(this, RADIO_TECHNOLOGY_CHANGED_FILTER);
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+ intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mContext.registerReceiver(this, intentFilter);
}
public void unregister() {
@@ -268,9 +282,17 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
@Override
public void onReceive(Context context, Intent intent) {
- if (!isInitialStickyBroadcast()) {
- mClient.onPhoneChange();
+ if (isInitialStickyBroadcast()) {
+ return;
}
+ if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
+ if (!intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX) ||
+ intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1)
+ != mClient.getSubscriptionId()) {
+ return;
+ }
+ }
+ mClient.onPhoneChange();
}
}
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index c8e2247db15..8d83ef2a3f9 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -150,7 +150,7 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment {
use(CarrierPreferenceController.class).init(mSubId);
use(DataUsagePreferenceController.class).init(mSubId);
use(PreferredNetworkModePreferenceController.class).init(mSubId);
- use(EnabledNetworkModePreferenceController.class).init(mSubId);
+ use(EnabledNetworkModePreferenceController.class).init(getLifecycle(), mSubId);
use(DataServiceSetupPreferenceController.class).init(mSubId);
if (!FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2)) {
use(EuiccPreferenceController.class).init(mSubId);
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
index 4d4d3ef7f01..59984837224 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
@@ -61,16 +61,12 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
PhoneAccountHandle mSimCallManager;
private PhoneCallStateListener mPhoneStateListener;
private Preference mPreference;
- private boolean mEditableWfcRoamingMode;
- private boolean mUseWfcHomeModeForRoaming;
public WifiCallingPreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
- mEditableWfcRoamingMode = true;
- mUseWfcHomeModeForRoaming = false;
}
@Override
@@ -129,9 +125,18 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
preference.setTitle(title);
int resId = com.android.internal.R.string.wifi_calling_off_summary;
if (mImsManager.isWfcEnabledByUser()) {
- boolean wfcRoamingEnabled = mEditableWfcRoamingMode && !mUseWfcHomeModeForRoaming;
+ boolean useWfcHomeModeForRoaming = false;
+ if (mCarrierConfigManager != null) {
+ final PersistableBundle carrierConfig =
+ mCarrierConfigManager.getConfigForSubId(mSubId);
+ if (carrierConfig != null) {
+ useWfcHomeModeForRoaming = carrierConfig.getBoolean(
+ CarrierConfigManager
+ .KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
+ }
+ }
final boolean isRoaming = mTelephonyManager.isNetworkRoaming();
- int wfcMode = mImsManager.getWfcMode(isRoaming && wfcRoamingEnabled);
+ int wfcMode = mImsManager.getWfcMode(isRoaming && !useWfcHomeModeForRoaming);
switch (wfcMode) {
case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
@@ -159,16 +164,6 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont
mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
mSimCallManager = mContext.getSystemService(TelecomManager.class)
.getSimCallManagerForSubscription(mSubId);
- if (mCarrierConfigManager != null) {
- final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
- if (carrierConfig != null) {
- mEditableWfcRoamingMode = carrierConfig.getBoolean(
- CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
- mUseWfcHomeModeForRoaming = carrierConfig.getBoolean(
- CarrierConfigManager
- .KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
- }
- }
}
private class PhoneCallStateListener extends PhoneStateListener {
diff --git a/src/com/android/settings/notification/RingtonePreferenceControllerBase.java b/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
index 733d0d937d7..c82afb4d1f6 100644
--- a/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
+++ b/src/com/android/settings/notification/RingtonePreferenceControllerBase.java
@@ -55,7 +55,7 @@ public abstract class RingtonePreferenceControllerBase extends AbstractPreferenc
final CharSequence summary;
if (ringtoneUri == null) {
- summary = null;
+ summary = mContext.getString(com.android.internal.R.string.ringtone_silent);
} else {
summary = Ringtone.getTitle(
mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 28ded2d8bf9..3353d62053f 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -47,6 +47,7 @@ public final class ChooseLockSettingsHelper {
public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
public static final String EXTRA_KEY_FOR_FACE = "for_face";
public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
+ public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
/**
* Intent extra for passing the requested min password complexity to later steps in the set new
@@ -105,7 +106,8 @@ public final class ChooseLockSettingsHelper {
null /* header */,
null /* description */,
false /* returnCredentials */,
- false /* external */);
+ false /* external */,
+ false /* foregroundOnly */);
}
/**
@@ -124,7 +126,8 @@ public final class ChooseLockSettingsHelper {
null /* header */,
null /* description */,
returnCredentials /* returnCredentials */,
- false /* external */);
+ false /* external */,
+ false /* foregroundOnly */);
}
/**
@@ -148,7 +151,8 @@ public final class ChooseLockSettingsHelper {
false /* external */,
false /* hasChallenge */,
0 /* challenge */,
- Utils.enforceSameOwner(mActivity, userId) /* userId */);
+ Utils.enforceSameOwner(mActivity, userId) /* userId */,
+ false /* foregroundOnly */);
}
/**
@@ -162,12 +166,13 @@ public final class ChooseLockSettingsHelper {
* @param external specifies whether this activity is launched externally, meaning that it will
* get a dark theme, allow fingerprint authentication and it will forward
* activity result.
+ * @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
- boolean returnCredentials, boolean external) {
+ boolean returnCredentials, boolean external, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -177,7 +182,8 @@ public final class ChooseLockSettingsHelper {
external /* external */,
false /* hasChallenge */,
0 /* challenge */,
- Utils.getCredentialOwnerUserId(mActivity) /* userId */);
+ Utils.getCredentialOwnerUserId(mActivity) /* userId */,
+ foregroundOnly /* foregroundOnly */);
}
/**
@@ -207,7 +213,8 @@ public final class ChooseLockSettingsHelper {
external /* external */,
false /* hasChallenge */,
0 /* challenge */,
- Utils.enforceSameOwner(mActivity, userId) /* userId */);
+ Utils.enforceSameOwner(mActivity, userId) /* userId */,
+ false /* foregroundOnly */);
}
/**
@@ -217,12 +224,13 @@ public final class ChooseLockSettingsHelper {
* @param header header of the confirmation screen; shown as large text
* @param description description of the confirmation screen
* @param challenge a challenge to be verified against the device credential.
+ * @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
- long challenge) {
+ long challenge, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -232,7 +240,8 @@ public final class ChooseLockSettingsHelper {
false /* external */,
true /* hasChallenge */,
challenge /* challenge */,
- Utils.getCredentialOwnerUserId(mActivity) /* userId */);
+ Utils.getCredentialOwnerUserId(mActivity) /* userId */,
+ foregroundOnly /* foregroundOnly */);
}
/**
@@ -243,12 +252,13 @@ public final class ChooseLockSettingsHelper {
* @param description description of the confirmation screen
* @param challenge a challenge to be verified against the device credential.
* @param userId The userId for whom the lock should be confirmed.
+ * @param foregroundOnly if the confirmation activity should be finished if it loses foreground.
* @return true if one exists and we launched an activity to confirm it
* @see Activity#onActivityResult(int, int, android.content.Intent)
*/
public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
- long challenge, int userId) {
+ long challenge, int userId, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -258,7 +268,8 @@ public final class ChooseLockSettingsHelper {
false /* external */,
true /* hasChallenge */,
challenge /* challenge */,
- Utils.enforceSameOwner(mActivity, userId) /* userId */);
+ Utils.enforceSameOwner(mActivity, userId) /* userId */,
+ foregroundOnly);
}
/**
@@ -287,7 +298,8 @@ public final class ChooseLockSettingsHelper {
external /* external */,
true /* hasChallenge */,
challenge /* challenge */,
- Utils.enforceSameOwner(mActivity, userId) /* userId */);
+ Utils.enforceSameOwner(mActivity, userId) /* userId */,
+ false /* foregroundOnly */);
}
/**
@@ -316,7 +328,7 @@ public final class ChooseLockSettingsHelper {
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge,
- long challenge, int userId) {
+ long challenge, int userId, boolean foregroundOnly) {
return launchConfirmationActivity(
request /* request */,
title /* title */,
@@ -328,7 +340,8 @@ public final class ChooseLockSettingsHelper {
challenge /* challenge */,
userId /* userId */,
null /* alternateButton */,
- null /* extras */);
+ null /* extras */,
+ foregroundOnly /* foregroundOnly */);
}
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@@ -346,7 +359,8 @@ public final class ChooseLockSettingsHelper {
challenge /* challenge */,
userId /* userId */,
null /* alternateButton */,
- extras /* extras */);
+ extras /* extras */,
+ false /* foregroundOnly */);
}
public boolean launchFrpConfirmationActivity(int request, @Nullable CharSequence header,
@@ -362,13 +376,15 @@ public final class ChooseLockSettingsHelper {
0 /* challenge */,
LockPatternUtils.USER_FRP /* userId */,
alternateButton /* alternateButton */,
- null /* extras */);
+ null /* extras */,
+ false /* foregroundOnly */);
}
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean hasChallenge,
- long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras) {
+ long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras,
+ boolean foregroundOnly) {
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
boolean launched = false;
@@ -378,7 +394,8 @@ public final class ChooseLockSettingsHelper {
returnCredentials || hasChallenge
? ConfirmLockPattern.InternalActivity.class
: ConfirmLockPattern.class, returnCredentials, external,
- hasChallenge, challenge, userId, alternateButton, extras);
+ hasChallenge, challenge, userId, alternateButton, extras,
+ foregroundOnly);
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
@@ -390,7 +407,8 @@ public final class ChooseLockSettingsHelper {
returnCredentials || hasChallenge
? ConfirmLockPassword.InternalActivity.class
: ConfirmLockPassword.class, returnCredentials, external,
- hasChallenge, challenge, userId, alternateButton, extras);
+ hasChallenge, challenge, userId, alternateButton, extras,
+ foregroundOnly);
break;
}
return launched;
@@ -399,7 +417,8 @@ public final class ChooseLockSettingsHelper {
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class> activityClass, boolean returnCredentials,
boolean external, boolean hasChallenge, long challenge,
- int userId, @Nullable CharSequence alternateButton, Bundle extras) {
+ int userId, @Nullable CharSequence alternateButton, Bundle extras,
+ boolean foregroundOnly) {
final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
@@ -414,6 +433,7 @@ public final class ChooseLockSettingsHelper {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
if (extras != null) {
intent.putExtras(extras);
}
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
index 998b3fcdd18..5407776f3b1 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
@@ -172,6 +172,10 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
mBiometricManager.onConfirmDeviceCredentialError(
BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
getString(com.android.internal.R.string.biometric_error_user_canceled));
+ if (getIntent().getBooleanExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, false)) {
+ finish();
+ }
}
}
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 9a165297942..aa17f8e987f 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -111,7 +111,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
layout.setIcon(getContext().getDrawable(R.drawable.ic_lock));
- int titleResource = mForFingerprint ?
+ int titleResource = isForBiometric() ?
R.string.lock_settings_picker_title : R.string.setup_lock_settings_picker_title;
if (getActivity() != null) {
getActivity().setTitle(titleResource);
@@ -125,7 +125,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
@Override
protected void addHeaderView() {
- if (mForFingerprint || mForFace) {
+ if (isForBiometric()) {
setHeaderView(R.layout.setup_choose_lock_generic_biometrics_header);
} else {
setHeaderView(R.layout.setup_choose_lock_generic_header);
@@ -183,7 +183,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
@Override
protected void addPreferences() {
- if (mForFingerprint) {
+ if (isForBiometric()) {
super.addPreferences();
} else {
addPreferencesFromResource(R.xml.setup_security_settings_picker);
@@ -240,6 +240,10 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
return intent;
}
+
+ private boolean isForBiometric() {
+ return mForFingerprint || mForFace;
+ }
}
public static class InternalActivity extends ChooseLockGeneric.InternalActivity {
@@ -261,5 +265,4 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
}
}
}
-
}
diff --git a/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
index 809bfbdc21f..77aab34c9c3 100644
--- a/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
+++ b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
@@ -96,18 +96,23 @@ public final class EnableContentCaptureWithServiceSettingsPreferenceController
for (UserInfo info: userInfos) {
userHandles.add(info.getUserHandle());
}
-
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context, userHandles);
- builder.setTitle(com.android.settingslib.R.string.choose_profile)
- .setAdapter(adapter, (DialogInterface dialog, int which) -> {
- final UserHandle user = userHandles.get(which);
- // Show menu on top level items.
- final Intent intent = pref.getIntent();
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- context.startActivityAsUser(intent, user);
- })
- .show();
+ if (userHandles.size() == 1) {
+ final Intent intent = pref.getIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivityAsUser(intent, userHandles.get(0));
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context,
+ userHandles);
+ builder.setTitle(com.android.settingslib.R.string.choose_profile)
+ .setAdapter(adapter, (DialogInterface dialog, int which) -> {
+ final UserHandle user = userHandles.get(which);
+ // Show menu on top level items.
+ final Intent intent = pref.getIntent()
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ context.startActivityAsUser(intent, user);
+ })
+ .show();
+ }
}
}
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index dc3324b3d92..946a9d3dfda 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -26,6 +26,7 @@ import android.util.ArrayMap;
import androidx.annotation.VisibleForTesting;
+import com.android.settings.display.AdaptiveSleepPreferenceController;
import com.android.settings.flashlight.FlashlightSlice;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
@@ -34,7 +35,9 @@ import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSli
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
+import com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice;
import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
+import com.android.settings.homepage.contextualcards.slices.FaceSetupSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
import com.android.settings.location.LocationSlice;
@@ -64,6 +67,16 @@ public class CustomSliceRegistry {
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
.build();
+ /**
+ * Uri for Contextual Adaptive Sleep Slice
+ */
+ public static final Uri CONTEXTUAL_ADAPTIVE_SLEEP_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+ .appendPath(AdaptiveSleepPreferenceController.PREF_NAME)
+ .build();
+
/**
* Uri for Battery Fix Slice.
*/
@@ -150,6 +163,15 @@ public class CustomSliceRegistry {
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath("enhanced_4g_lte")
.build();
+ /**
+ * Slice Uri for Face Enrollment
+ */
+ public static final Uri FACE_ENROLL_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("face_unlock_greeting_card")
+ .build();
/**
* Backing Uri for the Flashlight Slice.
*/
@@ -328,21 +350,23 @@ public class CustomSliceRegistry {
sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
+ sUriToSlice.put(CONTEXTUAL_ADAPTIVE_SLEEP_URI, ContextualAdaptiveSleepSlice.class);
sUriToSlice.put(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI,
ContextualNotificationChannelSlice.class);
sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
sUriToSlice.put(DATA_USAGE_SLICE_URI, DataUsageSlice.class);
sUriToSlice.put(DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
sUriToSlice.put(EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
+ sUriToSlice.put(FACE_ENROLL_SLICE_URI, FaceSetupSlice.class);
sUriToSlice.put(FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
sUriToSlice.put(LOCATION_SLICE_URI, LocationSlice.class);
sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
+ sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
+ sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
- sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
- sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
}
public static Class extends CustomSliceable> getSliceClassByUri(Uri uri) {
diff --git a/src/com/android/settings/wifi/CellularFallbackPreferenceController.java b/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
index cbb8fb8e26a..01677891bb1 100644
--- a/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
+++ b/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
@@ -17,8 +17,11 @@
package com.android.settings.wifi;
import android.content.Context;
+import android.content.res.Resources;
import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.TogglePreferenceController;
/**
@@ -33,7 +36,7 @@ public class CellularFallbackPreferenceController extends TogglePreferenceContro
@Override
public int getAvailabilityStatus() {
- return !avoidBadWifiConfig() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ return avoidBadWifiConfig() ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
}
@Override
@@ -49,12 +52,28 @@ public class CellularFallbackPreferenceController extends TogglePreferenceContro
}
private boolean avoidBadWifiConfig() {
- return mContext.getResources().getInteger(
- com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
+ final int activeDataSubscriptionId = getActiveDataSubscriptionId();
+ if (activeDataSubscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return true;
+ }
+
+ final Resources resources = getResourcesForSubId(activeDataSubscriptionId);
+ return resources.getInteger(com.android.internal.R.integer.config_networkAvoidBadWifi) == 1;
+ }
+
+ @VisibleForTesting
+ int getActiveDataSubscriptionId() {
+ return SubscriptionManager.getActiveDataSubscriptionId();
+ }
+
+ @VisibleForTesting
+ Resources getResourcesForSubId(int subscriptionId) {
+ return SubscriptionManager.getResourcesForSubId(mContext, subscriptionId,
+ false /* useRootLocale */);
}
private boolean avoidBadWifiCurrentSettings() {
return "1".equals(Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NETWORK_AVOID_BAD_WIFI));
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 5e49b2e7498..a915766bbe6 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -682,7 +682,11 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
}
mMacAddressPref.setVisible(true);
- mMacAddressPref.setSummary(macAddress);
+ if (macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) {
+ mMacAddressPref.setSummary(R.string.device_info_not_available);
+ } else {
+ mMacAddressPref.setSummary(macAddress);
+ }
}
private String getMacAddress() {
diff --git a/src/com/android/settings/wifi/tether/TetherService.java b/src/com/android/settings/wifi/tether/TetherService.java
index 34daccf6aea..058bba788ec 100644
--- a/src/com/android/settings/wifi/tether/TetherService.java
+++ b/src/com/android/settings/wifi/tether/TetherService.java
@@ -85,7 +85,7 @@ public class TetherService extends Service {
public void onCreate() {
super.onCreate();
if (DEBUG) Log.d(TAG, "Creating TetherService");
- String provisionResponse = getResourceForDefaultDataSubId().getString(
+ String provisionResponse = getResourceForActiveDataSubId().getString(
com.android.internal.R.string.config_mobile_hotspot_provision_response);
registerReceiver(mReceiver, new IntentFilter(provisionResponse),
android.Manifest.permission.CONNECTIVITY_INTERNAL, null);
@@ -105,7 +105,7 @@ public class TetherService extends Service {
if (intent.hasExtra(EXTRA_SUBID)) {
final int tetherSubId = intent.getIntExtra(EXTRA_SUBID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
+ final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
if (tetherSubId != subId) {
Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
if (!mInProvisionCheck) {
@@ -273,11 +273,13 @@ public class TetherService extends Service {
}
private Intent getProvisionBroadcastIntent(int index) {
- String provisionAction = getResourceForDefaultDataSubId().getString(
+ String provisionAction = getResourceForActiveDataSubId().getString(
com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui);
+ final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
Intent intent = new Intent(provisionAction);
int type = mCurrentTethers.get(index);
intent.putExtra(TETHER_CHOICE, type);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
@@ -309,7 +311,7 @@ public class TetherService extends Service {
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
- int period = getResourceForDefaultDataSubId().getInteger(
+ int period = getResourceForActiveDataSubId().getInteger(
com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
long periodMs = period * MS_PER_HOUR;
long firstTime = SystemClock.elapsedRealtime() + periodMs;
@@ -362,7 +364,7 @@ public class TetherService extends Service {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
- String provisionResponse = getResourceForDefaultDataSubId().getString(
+ String provisionResponse = getResourceForActiveDataSubId().getString(
com.android.internal.R.string.config_mobile_hotspot_provision_response);
if (provisionResponse.equals(intent.getAction())) {
@@ -429,14 +431,14 @@ public class TetherService extends Service {
mUsageStatsManager.setAppInactive(packageName, isInactive);
}
- int getDefaultDataSubscriptionId() {
- return SubscriptionManager.getDefaultDataSubscriptionId();
+ int getActiveDataSubscriptionId() {
+ return SubscriptionManager.getActiveDataSubscriptionId();
}
}
@VisibleForTesting
- Resources getResourceForDefaultDataSubId() {
- final int subId = getTetherServiceWrapper().getDefaultDataSubscriptionId();
+ Resources getResourceForActiveDataSubId() {
+ final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
return Utils.getResourcesForSubId(this, subId);
}
}
diff --git a/tests/robotests/res/values/overlayable_icons_test.xml b/tests/robotests/res/values/overlayable_icons_test.xml
index bf87f3bb7a7..0dab9cf4ac5 100644
--- a/tests/robotests/res/values/overlayable_icons_test.xml
+++ b/tests/robotests/res/values/overlayable_icons_test.xml
@@ -26,8 +26,6 @@
- @drawable/ic_arrow_back
- @drawable/ic_arrow_down_24dp
- @drawable/ic_battery_charging_full
- - @drawable/ic_battery_saver_accent_24dp
- - @drawable/ic_battery_status_bad_24dp
- @drawable/ic_battery_status_good_24dp
- @drawable/ic_battery_status_maybe_24dp
- @drawable/ic_call_24dp
@@ -38,13 +36,13 @@
- @drawable/ic_content_copy_grey600_24dp
- @drawable/ic_data_saver
- @drawable/ic_delete
- - @drawable/ic_delete_accent
- @drawable/ic_devices_other
- @drawable/ic_devices_other_opaque_black
- @drawable/ic_do_not_disturb_on_24dp
- @drawable/ic_eject_24dp
- @drawable/ic_expand_less
- @drawable/ic_expand_more_inverse
+ - @drawable/ic_find_in_page_24px
- @drawable/ic_folder_vd_theme_24
- @drawable/ic_friction_lock_closed
- @drawable/ic_gray_scale_24dp
@@ -71,9 +69,13 @@
- @drawable/ic_settings_data_usage
- @drawable/ic_settings_date_time
- @drawable/ic_settings_delete
+ - @drawable/ic_settings_disable
- @drawable/ic_settings_display_white
+ - @drawable/ic_settings_enable
- @drawable/ic_settings_home
+ - @drawable/ic_settings_language
- @drawable/ic_settings_location
+ - @drawable/ic_settings_multiuser
- @drawable/ic_settings_night_display
- @drawable/ic_settings_open
- @drawable/ic_settings_print
@@ -82,15 +84,16 @@
- @drawable/ic_settings_sim
- @drawable/ic_settings_system_dashboard_white
- @drawable/ic_settings_wireless
- - @drawable/ic_settings_wireless_white
- @drawable/ic_storage
- @drawable/ic_storage_white
- @drawable/ic_suggestion_night_display
- @drawable/ic_sync
+ - @drawable/ic_sync_problem_24dp
- @drawable/ic_system_update
- @drawable/ic_videogame_vd_theme_24
- @drawable/ic_volume_ringer_vibrate
- @drawable/ic_volume_up_24dp
- @drawable/ic_vpn_key
+ - @drawable/ic_wifi_tethering
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java
index 809d2cfefd1..065544b2f68 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppStoragePreferenceControllerTest.java
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -99,6 +100,16 @@ public class AppStoragePreferenceControllerTest {
verify(preference).setSummary(any());
}
+ @Test
+ public void updateState_entryIsNull_shouldNotUpdatePreferenceSummary() {
+ when(mFragment.getAppEntry()).thenReturn(null);
+ Preference preference = mock(Preference.class);
+
+ mController.updateState(preference);
+
+ verify(preference, never()).setSummary(any());
+ }
+
@Test
public void getStorageSummary_shouldWorkForExternal() {
final StorageStatsSource.AppStorageStats stats =
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java
new file mode 100644
index 00000000000..7f7fa4fed13
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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 com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.face.FaceManager;
+import android.os.UserManager;
+import android.provider.Settings;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class FaceSettingsLockscreenBypassPreferenceControllerTest {
+
+ @Mock
+ private FaceManager mFaceManager;
+ private SwitchPreference mPreference;
+ @Mock
+ private UserManager mUserManager;
+
+ private Context mContext;
+ private FaceSettingsLockscreenBypassPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPreference = new SwitchPreference(mContext);
+
+ mController = new FaceSettingsLockscreenBypassPreferenceController(mContext, "test_key");
+ ReflectionHelpers.setField(mController, "mFaceManager", mFaceManager);
+ ReflectionHelpers.setField(mController, "mUserManager", mUserManager);
+ }
+
+ @Test
+ public void isAvailable_whenHardwareDetected() {
+ assertThat(mController.isAvailable()).isFalse();
+ when(mFaceManager.isHardwareDetected()).thenReturn(true);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_isManagedProfile_shouldReturnUnsupported() {
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_settingIsUpdated() {
+ boolean defaultValue = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_faceAuthDismissesKeyguard);
+ boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, defaultValue ? 1 : 0) != 0;
+
+ assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
+ boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 0) != 0;
+ assertThat(newState).isEqualTo(!state);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
index adddc961e06..950d96237d6 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
@@ -31,12 +31,9 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.util.FeatureFlagUtils;
import androidx.preference.Preference;
-import com.android.settings.core.FeatureFlags;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -91,7 +88,7 @@ public class MainlineModuleVersionPreferenceControllerTest {
@Test
public void getAvailabilityStatus_hasMainlineModulePackageInfo_available() throws Exception {
- setupModulePackage();
+ setupModulePackage("test version 123");
final MainlineModuleVersionPreferenceController controller =
new MainlineModuleVersionPreferenceController(mContext, "key");
@@ -101,7 +98,7 @@ public class MainlineModuleVersionPreferenceControllerTest {
@Test
public void updateStates_canHandleIntent_setIntentToPreference() throws Exception {
- setupModulePackage();
+ setupModulePackage("test version 123");
when(mPackageManager.resolveActivity(MODULE_UPDATE_INTENT, 0))
.thenReturn(new ResolveInfo());
@@ -115,7 +112,7 @@ public class MainlineModuleVersionPreferenceControllerTest {
@Test
public void updateStates_cannotHandleIntent_setNullToPreference() throws Exception {
- setupModulePackage();
+ setupModulePackage("test version 123");
when(mPackageManager.resolveActivity(MODULE_UPDATE_INTENT, 0))
.thenReturn(null);
@@ -127,9 +124,38 @@ public class MainlineModuleVersionPreferenceControllerTest {
assertThat(mPreference.getIntent()).isNull();
}
- private void setupModulePackage() throws Exception {
+ @Test
+ public void getSummary_versionIsNull_returnNull() throws Exception {
+ setupModulePackage(null);
+
+ final MainlineModuleVersionPreferenceController controller =
+ new MainlineModuleVersionPreferenceController(mContext, "key");
+
+ assertThat(controller.getSummary()).isNull();
+ }
+
+ @Test
+ public void getSummary_versionIsMonth_returnMonth() throws Exception {
+ setupModulePackage("2019-05");
+
+ final MainlineModuleVersionPreferenceController controller =
+ new MainlineModuleVersionPreferenceController(mContext, "key");
+
+ assertThat(controller.getSummary()).isEqualTo("May 01, 2019");
+ }
+
+ @Test
+ public void getSummary_versionIsDate_returnDate() throws Exception {
+ setupModulePackage("2019-05-13");
+
+ final MainlineModuleVersionPreferenceController controller =
+ new MainlineModuleVersionPreferenceController(mContext, "key");
+
+ assertThat(controller.getSummary()).isEqualTo("May 13, 2019");
+ }
+
+ private void setupModulePackage(String version) throws Exception {
final String provider = "test.provider";
- final String version = "test version 123";
final PackageInfo info = new PackageInfo();
info.versionName = version;
when(mContext.getString(
diff --git a/tests/robotests/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceControllerTest.java
new file mode 100644
index 00000000000..f2edf980443
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceControllerTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.display;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import androidx.preference.Preference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class AdaptiveSleepPermissionPreferenceControllerTest {
+ private final static String PACKAGE_NAME = "package_name";
+ private AdaptiveSleepPermissionPreferenceController mController;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private Preference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Context context = Mockito.spy(RuntimeEnvironment.application);
+ doReturn(mPackageManager).when(context).getPackageManager();
+ doReturn(PACKAGE_NAME).when(mPackageManager).getAttentionServicePackageName();
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
+ Manifest.permission.CAMERA, PACKAGE_NAME);
+ mController = new AdaptiveSleepPermissionPreferenceController(context, "test_key");
+ doReturn(mController.getPreferenceKey()).when(mPreference).getKey();
+ }
+
+ @Test
+ public void getAvailabilityStatus_returnAvailableUnsearchable() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
+ }
+
+ @Test
+ public void updateStates_permissionGranted_preferenceInvisible() {
+ mController.updateState(mPreference);
+
+ verify(mPreference).setVisible(false);
+ }
+
+ @Test
+ public void updateStates_permissionRevoked_preferenceVisible() {
+ doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
+ Manifest.permission.CAMERA, PACKAGE_NAME);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setVisible(true);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/SystemNavigationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationPreferenceControllerTest.java
index 79f18502c81..3163f9ab801 100644
--- a/tests/robotests/src/com/android/settings/gestures/SystemNavigationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationPreferenceControllerTest.java
@@ -24,7 +24,6 @@ import static com.android.settings.gestures.SystemNavigationPreferenceController
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
@@ -181,46 +180,4 @@ public class SystemNavigationPreferenceControllerTest {
assertThat(TextUtils.equals(mController.getSummary(), mContext.getText(
com.android.settings.R.string.swipe_up_to_switch_apps_title))).isTrue();
}
-
- @Test
- public void testIsGestureNavSupportedByDefaultLauncher_noDefaultLauncher() {
- when(mMockPackageManager.getHomeActivities(any())).thenReturn(null);
- assertThat(SystemNavigationPreferenceController
- .isGestureNavSupportedByDefaultLauncher(mMockContext)).isTrue();
- }
-
- @Test
- public void testIsGestureNavSupportedByDefaultLauncher_supported() {
- when(mMockPackageManager.getHomeActivities(any())).thenReturn(
- ComponentName.unflattenFromString(TEST_RECENTS_COMPONENT_NAME));
- assertThat(SystemNavigationPreferenceController
- .isGestureNavSupportedByDefaultLauncher(mMockContext)).isTrue();
- }
-
- @Test
- public void testIsGestureNavSupportedByDefaultLauncher_notSupported() {
- when(mMockPackageManager.getHomeActivities(any())).thenReturn(
- new ComponentName("unsupported", "launcher"));
- assertThat(SystemNavigationPreferenceController
- .isGestureNavSupportedByDefaultLauncher(mMockContext)).isFalse();
- }
-
- @Test
- public void testGetDefaultHomeAppName_noDefaultLauncher() {
- when(mMockPackageManager.getHomeActivities(any())).thenReturn(null);
- assertThat(SystemNavigationPreferenceController
- .getDefaultHomeAppName(mMockContext)).isEqualTo("");
- }
-
- @Test
- public void testGetDefaultHomeAppName_defaultLauncherExists() throws Exception {
- when(mMockPackageManager.getHomeActivities(any())).thenReturn(
- new ComponentName("supported", "launcher"));
- ApplicationInfo info = new ApplicationInfo();
- when(mMockPackageManager.getApplicationInfo("supported", 0)).thenReturn(info);
- when(mMockPackageManager.getApplicationLabel(info)).thenReturn("Test Home App");
-
- assertThat(SystemNavigationPreferenceController
- .getDefaultHomeAppName(mMockContext)).isEqualTo("Test Home App");
- }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSliceTest.java
new file mode 100644
index 00000000000..54fb2c3281a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSliceTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.homepage.contextualcards.slices;
+
+import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.DEFERRED_TIME_DAYS;
+import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
+import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_SETUP_TIME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceProvider;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.slices.CustomSliceRegistry;
+
+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 class ContextualAdaptiveSleepSliceTest {
+
+ private static final String pkgName = "adaptive_sleep";
+ private Context mContext;
+ private ContextualAdaptiveSleepSlice mContextualAdaptiveSleepSlice;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private SharedPreferences mSharedPreferences;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ mContext = spy(RuntimeEnvironment.application);
+ mContextualAdaptiveSleepSlice = spy(new ContextualAdaptiveSleepSlice(mContext));
+
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(mSharedPreferences).when(mContext).getSharedPreferences(eq(PREF), anyInt());
+ doReturn(true).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
+ doReturn(pkgName).when(mPackageManager).getAttentionServicePackageName();
+ doReturn(-DEFERRED_TIME_DAYS).when(mSharedPreferences).getLong(eq(PREF_KEY_SETUP_TIME),
+ anyLong());
+ }
+
+ @Test
+ public void getUri_shouldReturnContextualAdaptiveSleepSliceUri() {
+ final Uri uri = mContextualAdaptiveSleepSlice.getUri();
+
+ assertThat(uri).isEqualTo(CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI);
+ }
+
+ @Test
+ public void getSlice_ShowIfFeatureIsAvailable() {
+ final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
+
+ assertThat(slice).isNotNull();
+ }
+
+ @Test
+ public void getSlice_DoNotShowIfFeatureIsUnavailable() {
+ doReturn(false).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
+
+ final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
+
+ assertThat(slice).isNull();
+ }
+
+ @Test
+ public void getSlice_ShowIfNotRecentlySetup() {
+ final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
+
+ assertThat(slice).isNotNull();
+ }
+
+ @Test
+ public void getSlice_DoNotShowIfRecentlySetup() {
+ doReturn(System.currentTimeMillis()).when(mSharedPreferences).getLong(
+ eq(PREF_KEY_SETUP_TIME), anyLong());
+
+ final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
+
+ assertThat(slice).isNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSliceTest.java
new file mode 100644
index 00000000000..71b5c7a9b78
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/FaceSetupSliceTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.homepage.contextualcards.slices;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.face.FaceManager;
+import android.os.UserHandle;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceProvider;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class FaceSetupSliceTest {
+
+ private Context mContext;
+ private PackageManager mPackageManager;
+
+ @Before
+ public void setUp() {
+ // Set-up specs for SliceMetadata.
+ SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ mContext = spy(RuntimeEnvironment.application);
+ mPackageManager = mock(PackageManager.class);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ }
+
+ @Test
+ public void getSlice_noFaceManager_shouldReturnNull() {
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
+ final FaceSetupSlice setupSlice = new FaceSetupSlice(mContext);
+ assertThat(setupSlice.getSlice()).isNull();
+ }
+
+ @Test
+ public void getSlice_faceEnrolled_shouldReturnNull() {
+ final FaceManager faceManager = mock(FaceManager.class);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
+ when(faceManager.hasEnrolledTemplates(UserHandle.myUserId())).thenReturn(true);
+ when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(faceManager);
+ final FaceSetupSlice setupSlice = new FaceSetupSlice(mContext);
+ assertThat(setupSlice.getSlice()).isNull();
+ }
+
+ @Test
+ public void getSlice_faceNotEnrolled_shouldReturnNonNull() {
+ final FaceManager faceManager = mock(FaceManager.class);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
+ when(faceManager.hasEnrolledTemplates(UserHandle.myUserId())).thenReturn(false);
+ when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(faceManager);
+ final FaceSetupSlice setupSlice = new FaceSetupSlice(mContext);
+ assertThat(setupSlice.getSlice()).isNotNull();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
index 99c9134c77d..e24b0f22a5b 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
@@ -42,6 +42,7 @@ import android.text.TextUtils;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.widget.AddPreference;
+import com.android.settingslib.RestrictedLockUtils;
import org.junit.After;
import org.junit.Before;
@@ -373,4 +374,12 @@ public class MobileNetworkSummaryControllerTest {
verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
assertThat(captor.getValue()).isTrue();
}
+
+ @Test
+ public void onResume_disabledByAdmin_prefStaysDisabled() {
+ mPreference.setDisabledByAdmin(new RestrictedLockUtils.EnforcedAdmin());
+ mController.displayPreference(mPreferenceScreen);
+ mController.onResume();
+ verify(mPreference, never()).setEnabled(eq(true));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
index ba8be908c79..6a12afd1e50 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.network.telephony;
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
@@ -23,19 +25,25 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.content.Context;
+import android.net.Uri;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +56,7 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class EnabledNetworkModePreferenceControllerTest {
private static final int SUB_ID = 2;
+ public static final String KEY = "enabled_network";
@Mock
private TelephonyManager mTelephonyManager;
@@ -60,11 +69,14 @@ public class EnabledNetworkModePreferenceControllerTest {
private EnabledNetworkModePreferenceController mController;
private ListPreference mPreference;
private Context mContext;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
-
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
mContext = spy(RuntimeEnvironment.application);
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
@@ -79,8 +91,8 @@ public class EnabledNetworkModePreferenceControllerTest {
mPreference = new ListPreference(mContext);
mPreference.setEntries(R.array.enabled_networks_choices);
mPreference.setEntryValues(R.array.enabled_networks_values);
- mController = new EnabledNetworkModePreferenceController(mContext, "enabled_network");
- mController.init(SUB_ID);
+ mController = new EnabledNetworkModePreferenceController(mContext, KEY);
+ mController.init(mLifecycle, SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
}
@@ -106,7 +118,7 @@ public class EnabledNetworkModePreferenceControllerTest {
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL,
true);
- mController.init(SUB_ID);
+ mController.init(mLifecycle, SUB_ID);
assertThat(mController.mShow4GForLTE).isTrue();
}
@@ -161,4 +173,31 @@ public class EnabledNetworkModePreferenceControllerTest {
Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID, 0)).isNotEqualTo(
TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
}
+
+ @Test
+ public void preferredNetworkModeNotification_preferenceUpdates() {
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ doReturn(mPreference).when(screen).findPreference(KEY);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
+ TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
+ mController.displayPreference(screen);
+ mController.updateState(mPreference);
+ mLifecycle.handleLifecycleEvent(ON_START);
+
+ assertThat(Integer.parseInt(mPreference.getValue())).isEqualTo(
+ TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA);
+ assertThat(mPreference.getSummary()).isEqualTo("3G");
+
+
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
+ TelephonyManager.NETWORK_MODE_GSM_ONLY);
+ final Uri uri = Settings.Global.getUriFor(Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID);
+ mContext.getContentResolver().notifyChange(uri, null);
+
+ assertThat(Integer.parseInt(mPreference.getValue())).isEqualTo(
+ TelephonyManager.NETWORK_MODE_GSM_ONLY);
+ assertThat(mPreference.getSummary()).isEqualTo("2G");
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
index f38f2a2bb0c..43897d503d9 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
@@ -22,7 +22,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,6 +34,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -40,6 +44,8 @@ import android.view.View;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.view.menu.ContextMenuBuilder;
import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.android.settings.network.SubscriptionUtil;
import com.google.android.material.bottomnavigation.BottomNavigationView;
@@ -159,19 +165,56 @@ public class MobileNetworkActivityTest {
@Test
public void phoneChangeReceiver_ignoresStickyBroadcastFromBeforeRegistering() {
Activity activity = Robolectric.setupActivity(Activity.class);
- final int[] onChangeCallbackCount = {0};
+ MobileNetworkActivity.PhoneChangeReceiver.Client client = mock(
+ MobileNetworkActivity.PhoneChangeReceiver.Client.class);
MobileNetworkActivity.PhoneChangeReceiver receiver =
- new MobileNetworkActivity.PhoneChangeReceiver(activity, () -> {
- onChangeCallbackCount[0]++;
- });
+ new MobileNetworkActivity.PhoneChangeReceiver(activity, client);
Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
activity.sendStickyBroadcast(intent);
receiver.register();
- assertThat(onChangeCallbackCount[0]).isEqualTo(0);
+ verify(client, never()).onPhoneChange();
activity.sendStickyBroadcast(intent);
- assertThat(onChangeCallbackCount[0]).isEqualTo(1);
+ verify(client, times(1)).onPhoneChange();
+ }
+
+ @Test
+ public void phoneChangeReceiver_ignoresCarrierConfigChangeForWrongSubscriptionId() {
+ Activity activity = Robolectric.setupActivity(Activity.class);
+
+ MobileNetworkActivity.PhoneChangeReceiver.Client client = mock(
+ MobileNetworkActivity.PhoneChangeReceiver.Client.class);
+ doReturn(2).when(client).getSubscriptionId();
+
+ MobileNetworkActivity.PhoneChangeReceiver receiver =
+ new MobileNetworkActivity.PhoneChangeReceiver(activity, client);
+
+ receiver.register();
+
+ Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, 3);
+ activity.sendBroadcast(intent);
+ verify(client, never()).onPhoneChange();
+ }
+
+ @Test
+ public void phoneChangeReceiver_dispatchesCarrierConfigChangeForCorrectSubscriptionId() {
+ Activity activity = Robolectric.setupActivity(Activity.class);
+
+ MobileNetworkActivity.PhoneChangeReceiver.Client client = mock(
+ MobileNetworkActivity.PhoneChangeReceiver.Client.class);
+ doReturn(2).when(client).getSubscriptionId();
+
+ MobileNetworkActivity.PhoneChangeReceiver receiver =
+ new MobileNetworkActivity.PhoneChangeReceiver(activity, client);
+
+ receiver.register();
+
+ Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, 2);
+ activity.sendBroadcast(intent);
+ verify(client).onPhoneChange();
}
@@ -207,4 +250,19 @@ public class MobileNetworkActivityTest {
assertThat(bundle.getInt(Settings.EXTRA_SUB_ID)).isEqualTo(PREV_SUB_ID);
}
+
+ @Test
+ public void onNewIntent_newSubscriptionId_fragmentReplaced() {
+ FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
+
+ mSubscriptionInfos.add(mSubscriptionInfo);
+ mSubscriptionInfos.add(mSubscriptionInfo2);
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(mSubscriptionInfos);
+ mMobileNetworkActivity.mCurSubscriptionId = PREV_SUB_ID;
+
+ final Intent newIntent = new Intent();
+ newIntent.putExtra(Settings.EXTRA_SUB_ID, CURRENT_SUB_ID);
+ mMobileNetworkActivity.onNewIntent(newIntent);
+ assertThat(mMobileNetworkActivity.mCurSubscriptionId).isEqualTo(CURRENT_SUB_ID);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
index 42422f9e8e5..f795d618d33 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
@@ -127,10 +127,10 @@ public class WifiCallingPreferenceControllerTest {
}
@Test
- public void updateState_wfcNonRoaming() {
+ public void updateState_nonRoaming_wfcCellularPreferred() {
assertNull(mController.mSimCallManager);
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
- // update the config value by calling init again.
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, true);
mController.init(SUB_ID);
mController.mImsManager = mImsManager;
@@ -147,9 +147,10 @@ public class WifiCallingPreferenceControllerTest {
}
@Test
- public void updateState_wfcRoaming() {
+ public void updateState_roaming_wfcWifiPreferred() {
assertNull(mController.mSimCallManager);
-
+ // useWfcHomeModeForRoaming is false by default. In order to check wfc in roaming mode. We
+ // need the device roaming, and not using home mode in roaming network.
when(mImsManager.getWfcMode(true)).thenReturn(
ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED);
when(mImsManager.getWfcMode(false)).thenReturn(
diff --git a/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
index c5bd555fa9a..6f3230cff4f 100644
--- a/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
@@ -18,36 +18,54 @@ package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
+import android.telephony.SubscriptionManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class CellularFallbackPreferenceControllerTest {
private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
-
private CellularFallbackPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new CellularFallbackPreferenceController(mContext, KEY_CELLULAR_FALLBACK);
+
+ mController = spy(new CellularFallbackPreferenceController(RuntimeEnvironment.application,
+ KEY_CELLULAR_FALLBACK));
+ }
+
+ @Test
+ public void isAvailable_invalidActiveSubscriptionId_shouldReturnFalse() {
+ doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ .when(mController).getActiveDataSubscriptionId();
+
+ assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_avoidBadWifiConfigIsFalse_shouldReturnTrue() {
- when(mContext.getResources().getInteger(
+ final Resources resources = mock(Resources.class);
+
+ doReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
+ .when(mController).getActiveDataSubscriptionId();
+ doReturn(resources).when(mController).getResourcesForSubId(anyInt());
+ when(resources.getInteger(
com.android.internal.R.integer.config_networkAvoidBadWifi))
.thenReturn(0);
@@ -56,10 +74,15 @@ public class CellularFallbackPreferenceControllerTest {
@Test
public void isAvailable_avoidBadWifiConfigIsTrue_shouldReturnFalse() {
- when(mContext.getResources().getInteger(
+ final Resources resources = mock(Resources.class);
+
+ doReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
+ .when(mController).getActiveDataSubscriptionId();
+ doReturn(resources).when(mController).getResourcesForSubId(anyInt());
+ when(resources.getInteger(
com.android.internal.R.integer.config_networkAvoidBadWifi))
.thenReturn(1);
assertThat(mController.isAvailable()).isFalse();
}
-}
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 9a1dd4c0f82..010fb749f74 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -114,7 +114,7 @@ public class WifiDetailPreferenceControllerTest {
private static final int TX_LINK_SPEED = 123;
private static final int RX_LINK_SPEED = 54;
private static final String SSID = "ssid";
- private static final String MAC_ADDRESS = WifiInfo.DEFAULT_MAC_ADDRESS;
+ private static final String MAC_ADDRESS = "01:23:45:67:89:ab";
private static final String RANDOMIZED_MAC_ADDRESS = "RANDOMIZED_MAC_ADDRESS";
private static final String FACTORY_MAC_ADDRESS = "FACTORY_MAC_ADDRESS";
private static final String SECURITY = "None";
diff --git a/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java b/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
index 0739ef0ce23..24d1bcc85e2 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
@@ -458,7 +458,7 @@ public class TetherServiceTest extends ServiceTestCase {
}
@Override
- int getDefaultDataSubscriptionId() {
+ int getActiveDataSubscriptionId() {
return INVALID_SUBSCRIPTION_ID;
}
}