diff --git a/AndroidManifest.xml b/AndroidManifest.xml index be4810ff57d..26f0c4fcabc 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1517,6 +1517,8 @@ + + @@ -1947,8 +1951,7 @@ + android:exported="true"> diff --git a/color-check-baseline.xml b/color-check-baseline.xml index ba4d2f69b1d..96f0210b36d 100644 --- a/color-check-baseline.xml +++ b/color-check-baseline.xml @@ -13,38 +13,6 @@ file="."/> - - - - - - - - + + + + + errorLine1=" <color name="setup_wizard_wifi_color_dark">#89ffffff</color>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + + + + - - - - + errorLine1=" <color name="fingerprint_title_color">#ffffffff</color>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - @@ -297,7 +265,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -313,7 +281,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -329,7 +297,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -343,6 +311,54 @@ explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes. This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app." errorLine1=" <color name="icon_accent">#ffabffec</color>" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + + + + + + + + + + + + + + + + + errorLine1=" <color name="message_text_outgoing">#ff323232</color>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="timestamp_text_outgoing">#99323232</color>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" <color name="timestamp_text_incoming">#99ffffff</color>" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - @@ -585,7 +553,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -601,7 +569,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -617,7 +585,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -633,7 +601,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -649,7 +617,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -665,7 +633,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -681,7 +649,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -697,7 +665,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -713,7 +681,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -729,7 +697,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -745,7 +713,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -761,7 +729,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -777,7 +745,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -793,7 +761,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -809,7 +777,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -825,7 +793,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -841,7 +809,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -857,7 +825,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -873,7 +841,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -889,7 +857,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -905,7 +873,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -921,7 +889,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -937,7 +905,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -953,7 +921,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -969,7 +937,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -985,7 +953,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1001,7 +969,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1017,7 +985,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1033,7 +1001,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1049,7 +1017,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1065,7 +1033,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1081,7 +1049,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1097,7 +1065,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1113,7 +1081,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1129,7 +1097,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1145,7 +1113,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1161,7 +1129,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1177,7 +1145,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1193,7 +1161,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1209,7 +1177,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1225,7 +1193,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1241,7 +1209,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1257,7 +1225,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1273,7 +1241,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1289,7 +1257,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1305,7 +1273,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1321,7 +1289,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1337,7 +1305,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1353,7 +1321,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1369,7 +1337,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1385,7 +1353,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1401,7 +1369,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1417,7 +1385,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1433,7 +1401,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1449,7 +1417,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1465,7 +1433,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1481,7 +1449,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1497,7 +1465,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1513,7 +1481,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1529,7 +1497,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1545,7 +1513,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1561,7 +1529,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1577,7 +1545,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1593,7 +1561,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1609,7 +1577,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1625,7 +1593,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1641,7 +1609,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1657,7 +1625,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1673,7 +1641,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1689,7 +1657,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1705,7 +1673,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1721,7 +1689,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1737,7 +1705,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1753,7 +1721,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1769,7 +1737,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1785,7 +1753,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1801,7 +1769,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1817,7 +1785,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1833,7 +1801,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1849,7 +1817,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1865,7 +1833,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1881,7 +1849,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1897,7 +1865,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1913,7 +1881,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1929,7 +1897,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1945,7 +1913,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1961,7 +1929,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1977,7 +1945,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1993,7 +1961,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2009,7 +1977,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2025,7 +1993,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2041,7 +2009,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2057,7 +2025,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2073,7 +2041,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2089,7 +2057,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2829,6 +2797,22 @@ column="9"/> + + + + + + + + - - - - + + + + @@ -4553,7 +4553,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4569,7 +4569,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> @@ -4585,26 +4585,10 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - - - - - - - - @@ -4729,10 +4697,42 @@ errorLine2=" ^"> + + + + + + + + - - - - - - - - - - - - - - - diff --git a/res/layout/accessibility_qs_tooltips.xml b/res/layout/accessibility_qs_tooltip.xml similarity index 87% rename from res/layout/accessibility_qs_tooltips.xml rename to res/layout/accessibility_qs_tooltip.xml index 2bc9f5f4210..41501aadbdd 100644 --- a/res/layout/accessibility_qs_tooltips.xml +++ b/res/layout/accessibility_qs_tooltip.xml @@ -20,13 +20,13 @@ android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical" - android:background="@drawable/accessibility_qs_tooltips_background"> + android:background="@drawable/accessibility_qs_tooltip_background"> @@ -34,7 +34,7 @@ android:id="@+id/qs_content" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="@dimen/accessibility_qs_tooltips_margin" + android:padding="@dimen/accessibility_qs_tooltip_margin" android:textColor="@android:color/black" android:fontFamily="@*android:string/config_headlineFontFamilyMedium" android:textSize="16sp" /> diff --git a/res/layout/accessibility_text_reading_reset_button.xml b/res/layout/accessibility_text_reading_reset_button.xml index 43800df0b5f..dd9128b4eda 100644 --- a/res/layout/accessibility_text_reading_reset_button.xml +++ b/res/layout/accessibility_text_reading_reset_button.xml @@ -28,9 +28,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:background="@drawable/accessibility_text_reading_reset_button_background" android:paddingHorizontal="24dp" android:paddingVertical="14dp" android:text="@string/accessibility_text_reading_reset_button_title" - android:textAppearance="?android:attr/textAppearanceMedium" /> + style="@style/ActionPrimaryButton"/> diff --git a/res/layout/profile_select_tablayout.xml b/res/layout/profile_select_tablayout.xml deleted file mode 100644 index 3e83bb9b2c4..00000000000 --- a/res/layout/profile_select_tablayout.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - diff --git a/res/layout/support_details_dialog.xml b/res/layout/support_details_dialog.xml index 0233a1b4694..2390f90e2be 100644 --- a/res/layout/support_details_dialog.xml +++ b/res/layout/support_details_dialog.xml @@ -33,6 +33,8 @@ android:layout_width="@dimen/admin_details_dialog_icon_size" android:layout_height="@dimen/admin_details_dialog_icon_size" android:scaleType="fitCenter" + android:src="@drawable/ic_lock_closed" + android:tint="?android:attr/colorAccent" android:contentDescription="@null"/> 32dp 18dp - - 20dp - 27dp + + 20dp + 27dp 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 383d977ce83..c1a6dfeaca9 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5555,9 +5555,9 @@ Open %1$s - %1$s added to Quick Settings. Swipe down to turn it on or off anytime. + %1$s added to Quick Settings. Swipe down to turn it on or off anytime. - You can also add %1$s to Quick Settings from the top of your screen + You can also add %1$s to Quick Settings from the top of your screen Color correction added to Quick Settings. Swipe down to turn it on or off anytime. @@ -5575,7 +5575,7 @@ You can also add one-handed mode to Quick Settings from the top of your screen - Dismiss + Dismiss Adjust how colors display on your phone @@ -14026,4 +14026,13 @@ *This is a temporary placeholder fallback activity. + + + Spatial audio + + Immersive audio seems like it\u0027s coming from all around you. Only works with some media. + + Make audio more realistic + + Shift positioning of audio so it sounds more natural. diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml index 9df195584d6..b21d5c931e5 100644 --- a/res/xml/bluetooth_device_details_fragment.xml +++ b/res/xml/bluetooth_device_details_fragment.xml @@ -52,6 +52,9 @@ + + diff --git a/res/xml/notification_access_permission_details.xml b/res/xml/notification_access_permission_details.xml index cec383c90f7..9867b6d4c0a 100644 --- a/res/xml/notification_access_permission_details.xml +++ b/res/xml/notification_access_permission_details.xml @@ -26,7 +26,7 @@ android:layout="@layout/settings_entity_header" settings:controller="com.android.settings.applications.specialaccess.notificationaccess.HeaderPreferenceController"/> - diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java index 33b6deb82b9..d272a0be49f 100644 --- a/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java +++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsPrimarySwitchPreferenceController.java @@ -116,7 +116,7 @@ public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceControlle mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(mContext); mTooltipWindow.setup(getTileTooltipContent(), - R.drawable.accessibility_auto_added_qs_tooltips_illustration); + R.drawable.accessibility_auto_added_qs_tooltip_illustration); mTooltipWindow.showAtTopCenter(mPreference.getSwitch()); AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext, tileComponentName); mNeedsQSTooltipReshow = false; diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java index 6b6872f9275..bb6dba8f055 100644 --- a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java +++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java @@ -61,7 +61,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { super.onInitializeAccessibilityNodeInfo(host, info); final AccessibilityAction clickAction = new AccessibilityAction( AccessibilityNodeInfo.ACTION_CLICK, - mContext.getString(R.string.accessibility_quick_settings_tooltips_dismiss)); + mContext.getString(R.string.accessibility_quick_settings_tooltip_dismiss)); info.addAction(clickAction); } @@ -100,7 +100,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { setBackgroundDrawable(new ColorDrawable(mContext.getColor(android.R.color.transparent))); final LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class); final View popupView = - inflater.inflate(R.layout.accessibility_qs_tooltips, /* root= */ null); + inflater.inflate(R.layout.accessibility_qs_tooltip, /* root= */ null); popupView.setFocusable(/* focusable= */ true); popupView.setAccessibilityDelegate(mAccessibilityDelegate); setContentView(popupView); @@ -179,7 +179,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { @VisibleForTesting int getAvailableWindowWidth() { final Resources res = mContext.getResources(); - final int padding = res.getDimensionPixelSize(R.dimen.accessibility_qs_tooltips_margin); + final int padding = res.getDimensionPixelSize(R.dimen.accessibility_qs_tooltip_margin); final int screenWidth = res.getDisplayMetrics().widthPixels; return screenWidth - padding * 2; } diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java index 9c54a0c8fc5..a25c4a61207 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java @@ -506,8 +506,8 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF } final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT - ? R.drawable.accessibility_qs_tooltips_illustration - : R.drawable.accessibility_auto_added_qs_tooltips_illustration; + ? R.drawable.accessibility_qs_tooltip_illustration + : R.drawable.accessibility_auto_added_qs_tooltip_illustration; mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); mTooltipWindow.setup(content, imageResId); mTooltipWindow.showAtTopCenter(getView()); diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java index 036b2ea755e..3adef6dd1d6 100644 --- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java +++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java @@ -141,8 +141,8 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature } final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT - ? R.string.accessibility_service_qs_tooltips_content - : R.string.accessibility_service_auto_added_qs_tooltips_content; + ? R.string.accessibility_service_qs_tooltip_content + : R.string.accessibility_service_auto_added_qs_tooltip_content; return getString(titleResId, tileName); } diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java index 1a63f1fc9b8..e31403686c8 100644 --- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java @@ -252,8 +252,8 @@ public class ToggleAccessibilityServicePreferenceFragment extends } final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT - ? R.string.accessibility_service_qs_tooltips_content - : R.string.accessibility_service_auto_added_qs_tooltips_content; + ? R.string.accessibility_service_qs_tooltip_content + : R.string.accessibility_service_auto_added_qs_tooltip_content; return getString(titleResId, tileName); } diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index 9738321fc0c..ccdc78bd26f 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -877,8 +877,8 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference } final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT - ? R.drawable.accessibility_qs_tooltips_illustration - : R.drawable.accessibility_auto_added_qs_tooltips_illustration; + ? R.drawable.accessibility_qs_tooltip_illustration + : R.drawable.accessibility_auto_added_qs_tooltip_illustration; mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); mTooltipWindow.setup(content, imageResId); mTooltipWindow.showAtTopCenter(getView()); diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java index a43b9fd9145..0767e65bbcb 100644 --- a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java +++ b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java @@ -27,10 +27,10 @@ import android.os.AsyncTask; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.SwitchPreference; import com.android.settings.core.BasePreferenceController; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.RestrictedSwitchPreference; public class ApprovalPreferenceController extends BasePreferenceController { @@ -78,9 +78,11 @@ public class ApprovalPreferenceController extends BasePreferenceController { @Override public void updateState(Preference pref) { - final SwitchPreference preference = (SwitchPreference) pref; + final RestrictedSwitchPreference preference = + (RestrictedSwitchPreference) pref; final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm); - preference.setChecked(isServiceEnabled(mCn)); + final boolean isEnabled = isServiceEnabled(mCn); + preference.setChecked(isEnabled); preference.setOnPreferenceChangeListener((p, newValue) -> { final boolean access = (Boolean) newValue; if (!access) { @@ -103,6 +105,7 @@ public class ApprovalPreferenceController extends BasePreferenceController { return false; } }); + preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled); } public void disable(final ComponentName cn) { diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java index f1e312a419c..f5ad76b2d9d 100644 --- a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java +++ b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java @@ -55,6 +55,13 @@ public class CombinedBiometricStatusUtils { return Utils.hasFingerprintHardware(mContext) && Utils.hasFaceHardware(mContext); } + /** + * Returns whether at least one face template or fingerprint has been enrolled. + */ + public boolean hasEnrolled() { + return hasEnrolledFingerprints() || hasEnrolledFace(); + } + /** * Returns the {@link EnforcedAdmin} in case parental consent is required to change both * face and fingerprint settings. @@ -84,8 +91,7 @@ public class CombinedBiometricStatusUtils { public String getSummary() { final int numFingerprintsEnrolled = mFingerprintManager != null ? mFingerprintManager.getEnrolledFingerprints(mUserId).size() : 0; - final boolean faceEnrolled = mFaceManager != null - && mFaceManager.hasEnrolledTemplates(mUserId); + final boolean faceEnrolled = hasEnrolledFace(); if (faceEnrolled && numFingerprintsEnrolled > 1) { return mContext.getString( @@ -105,6 +111,14 @@ public class CombinedBiometricStatusUtils { } } + private boolean hasEnrolledFingerprints() { + return mFingerprintManager != null && mFingerprintManager.hasEnrolledFingerprints(mUserId); + } + + private boolean hasEnrolledFace() { + return mFaceManager != null && mFaceManager.hasEnrolledTemplates(mUserId); + } + /** * Returns the class name of the Settings page corresponding to combined biometric settings. */ diff --git a/src/com/android/settings/biometrics/face/FaceStatusUtils.java b/src/com/android/settings/biometrics/face/FaceStatusUtils.java index 4e255439a42..1749aca2051 100644 --- a/src/com/android/settings/biometrics/face/FaceStatusUtils.java +++ b/src/com/android/settings/biometrics/face/FaceStatusUtils.java @@ -75,7 +75,10 @@ public class FaceStatusUtils { : FaceEnrollIntroduction.class.getName(); } - private boolean hasEnrolled() { + /** + * Returns whether at least one face template has been enrolled. + */ + public boolean hasEnrolled() { return mFaceManager.hasEnrolledTemplates(mUserId); } } diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java index d23195d594c..5707f328601 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtils.java @@ -82,7 +82,10 @@ public class FingerprintStatusUtils { : FingerprintEnrollIntroduction.class.getName(); } - private boolean hasEnrolled() { + /** + * Returns whether at least one fingerprint has been enrolled. + */ + public boolean hasEnrolled() { return mFingerprintManager.hasEnrolledFingerprints(mUserId); } } diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java new file mode 100644 index 00000000000..89d923d616a --- /dev/null +++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2022 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.bluetooth; + +import android.content.Context; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceInfo; +import android.media.AudioManager; +import android.media.Spatializer; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import com.android.settings.R; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.core.lifecycle.Lifecycle; + +/** + * The controller of the Spatial audio setting in the bluetooth detail settings. + */ +public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsController + implements Preference.OnPreferenceClickListener { + + private static final String TAG = "BluetoothSpatialAudioController"; + private static final String KEY_SPATIAL_AUDIO_GROUP = "spatial_audio_group"; + private static final String KEY_SPATIAL_AUDIO = "spatial_audio"; + private static final String KEY_HEAD_TRACKING = "head_tracking"; + + private final Spatializer mSpatializer; + + @VisibleForTesting + PreferenceCategory mProfilesContainer; + @VisibleForTesting + AudioDeviceAttributes mAudioDevice; + + public BluetoothDetailsSpatialAudioController( + Context context, + PreferenceFragmentCompat fragment, + CachedBluetoothDevice device, + Lifecycle lifecycle) { + super(context, fragment, device, lifecycle); + AudioManager audioManager = context.getSystemService(AudioManager.class); + mSpatializer = audioManager.getSpatializer(); + mAudioDevice = new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, + mCachedDevice.getAddress()); + + } + + @Override + public boolean isAvailable() { + return mSpatializer.isAvailableForDevice(mAudioDevice) ? true : false; + } + + @Override + public boolean onPreferenceClick(Preference preference) { + SwitchPreference switchPreference = (SwitchPreference) preference; + String key = switchPreference.getKey(); + if (TextUtils.equals(key, KEY_SPATIAL_AUDIO)) { + if (switchPreference.isChecked()) { + mSpatializer.addCompatibleAudioDevice(mAudioDevice); + } else { + mSpatializer.removeCompatibleAudioDevice(mAudioDevice); + } + refresh(); + return true; + } else if (TextUtils.equals(key, KEY_HEAD_TRACKING)) { + mSpatializer.setHeadTrackerEnabled(switchPreference.isChecked(), mAudioDevice); + return true; + } else { + Log.w(TAG, "invalid key name."); + return false; + } + } + + @Override + public String getPreferenceKey() { + return KEY_SPATIAL_AUDIO_GROUP; + } + + @Override + protected void init(PreferenceScreen screen) { + mProfilesContainer = screen.findPreference(getPreferenceKey()); + mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category); + refresh(); + } + + @Override + protected void refresh() { + SwitchPreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO); + if (spatialAudioPref == null) { + spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext()); + mProfilesContainer.addPreference(spatialAudioPref); + } + + boolean isSpatialAudioOn = mSpatializer.getCompatibleAudioDevices().contains(mAudioDevice); + Log.d(TAG, "refresh() isSpatialAudioOn : " + isSpatialAudioOn); + spatialAudioPref.setChecked(isSpatialAudioOn); + + SwitchPreference headTrackingPref = mProfilesContainer.findPreference(KEY_HEAD_TRACKING); + if (headTrackingPref == null) { + headTrackingPref = createHeadTrackingPreference(mProfilesContainer.getContext()); + mProfilesContainer.addPreference(headTrackingPref); + } + + boolean isHeadTrackingAvailable = + isSpatialAudioOn && mSpatializer.hasHeadTracker(mAudioDevice); + Log.d(TAG, "refresh() has head tracker : " + mSpatializer.hasHeadTracker(mAudioDevice)); + headTrackingPref.setVisible(isHeadTrackingAvailable); + if (isHeadTrackingAvailable) { + headTrackingPref.setChecked(mSpatializer.isHeadTrackerEnabled(mAudioDevice)); + } + } + + @VisibleForTesting + SwitchPreference createSpatialAudioPreference(Context context) { + SwitchPreference pref = new SwitchPreference(context); + pref.setKey(KEY_SPATIAL_AUDIO); + pref.setTitle(context.getString(R.string.bluetooth_details_spatial_audio_title)); + pref.setSummary(context.getString(R.string.bluetooth_details_spatial_audio_summary)); + pref.setOnPreferenceClickListener(this); + return pref; + } + + @VisibleForTesting + SwitchPreference createHeadTrackingPreference(Context context) { + SwitchPreference pref = new SwitchPreference(context); + pref.setKey(KEY_HEAD_TRACKING); + pref.setTitle(context.getString(R.string.bluetooth_details_head_tracking_title)); + pref.setSummary(context.getString(R.string.bluetooth_details_head_tracking_summary)); + pref.setOnPreferenceClickListener(this); + return pref; + } +} diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java index 4980ba313fb..653248263bd 100644 --- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java @@ -187,6 +187,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment lifecycle)); controllers.add(new BluetoothDetailsCompanionAppsController(context, this, mCachedDevice, lifecycle)); + controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice, + lifecycle)); controllers.add(new BluetoothDetailsProfilesController(context, this, mManager, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice, diff --git a/src/com/android/settings/development/compat/PlatformCompatDashboard.java b/src/com/android/settings/development/compat/PlatformCompatDashboard.java index c617e179496..f8cbf21b36b 100644 --- a/src/com/android/settings/development/compat/PlatformCompatDashboard.java +++ b/src/com/android/settings/development/compat/PlatformCompatDashboard.java @@ -31,6 +31,7 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.text.TextUtils; import android.util.ArraySet; import androidx.annotation.VisibleForTesting; @@ -66,6 +67,8 @@ public class PlatformCompatDashboard extends DashboardFragment { private AndroidBuildClassifier mAndroidBuildClassifier = new AndroidBuildClassifier(); + private boolean mShouldStartAppPickerOnResume = true; + @VisibleForTesting String mSelectedApp; @@ -98,13 +101,67 @@ public class PlatformCompatDashboard extends DashboardFragment { } @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + public void onCreate(Bundle icicle) { + super.onCreate(icicle); try { mChanges = getPlatformCompat().listUIChanges(); } catch (RemoteException e) { throw new RuntimeException("Could not list changes!", e); } + if (icicle != null) { + mShouldStartAppPickerOnResume = false; + mSelectedApp = icicle.getString(COMPAT_APP); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_COMPAT_CHANGE_APP) { + mShouldStartAppPickerOnResume = false; + switch (resultCode) { + case Activity.RESULT_OK: + mSelectedApp = data.getAction(); + break; + case Activity.RESULT_CANCELED: + if (TextUtils.isEmpty(mSelectedApp)) { + finish(); + } + break; + case AppPicker.RESULT_NO_MATCHING_APPS: + mSelectedApp = null; + break; + } + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void onResume() { + super.onResume(); + if (isFinishingOrDestroyed()) { + return; + } + if (!mShouldStartAppPickerOnResume) { + if (TextUtils.isEmpty(mSelectedApp)) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.platform_compat_dialog_title_no_apps) + .setMessage(R.string.platform_compat_dialog_text_no_apps) + .setPositiveButton(R.string.okay, (dialog, which) -> finish()) + .setOnDismissListener(dialog -> finish()) + .setCancelable(false) + .show(); + return; + } + try { + final ApplicationInfo applicationInfo = getApplicationInfo(); + addPreferences(applicationInfo); + return; + } catch (PackageManager.NameNotFoundException e) { + mShouldStartAppPickerOnResume = true; + mSelectedApp = null; + } + } startAppPicker(); } @@ -114,31 +171,6 @@ public class PlatformCompatDashboard extends DashboardFragment { outState.putString(COMPAT_APP, mSelectedApp); } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_COMPAT_CHANGE_APP) { - if (resultCode == Activity.RESULT_OK) { - mSelectedApp = data.getAction(); - try { - final ApplicationInfo applicationInfo = getApplicationInfo(); - addPreferences(applicationInfo); - } catch (PackageManager.NameNotFoundException e) { - startAppPicker(); - } - } else if (resultCode == AppPicker.RESULT_NO_MATCHING_APPS) { - new AlertDialog.Builder(getContext()) - .setTitle(R.string.platform_compat_dialog_title_no_apps) - .setMessage(R.string.platform_compat_dialog_text_no_apps) - .setPositiveButton(R.string.okay, (dialog, which) -> finish()) - .setOnDismissListener(dialog -> finish()) - .setCancelable(false) - .show(); - } - return; - } - super.onActivityResult(requestCode, resultCode, data); - } - private void addPreferences(ApplicationInfo applicationInfo) { getPreferenceScreen().removeAll(); getPreferenceScreen().addPreference(createAppPreference(applicationInfo)); diff --git a/src/com/android/settings/safetycenter/BiometricsSafetySource.java b/src/com/android/settings/safetycenter/BiometricsSafetySource.java index c302915cb91..74d8e01b746 100644 --- a/src/com/android/settings/safetycenter/BiometricsSafetySource.java +++ b/src/com/android/settings/safetycenter/BiometricsSafetySource.java @@ -65,6 +65,7 @@ public final class BiometricsSafetySource { combinedBiometricStatusUtils.getSettingsClassName(), disablingAdmin, Bundle.EMPTY), disablingAdmin == null /* enabled */, + combinedBiometricStatusUtils.hasEnrolled(), safetyEvent); return; } @@ -82,6 +83,7 @@ public final class BiometricsSafetySource { faceStatusUtils.getSettingsClassName(), disablingAdmin, Bundle.EMPTY), disablingAdmin == null /* enabled */, + faceStatusUtils.hasEnrolled(), safetyEvent); return; @@ -101,6 +103,7 @@ public final class BiometricsSafetySource { fingerprintStatusUtils.getSettingsClassName(), disablingAdmin, Bundle.EMPTY), disablingAdmin == null /* enabled */, + fingerprintStatusUtils.hasEnrolled(), safetyEvent); } } @@ -114,12 +117,14 @@ public final class BiometricsSafetySource { } private static void setBiometricSafetySourceData(Context context, String title, String summary, - Intent clickIntent, boolean enabled, SafetyEvent safetyEvent) { + Intent clickIntent, boolean enabled, boolean hasEnrolled, SafetyEvent safetyEvent) { final PendingIntent pendingIntent = createPendingIntent(context, clickIntent); + final int statusLevel = + enabled && hasEnrolled ? SafetySourceStatus.STATUS_LEVEL_OK + : SafetySourceStatus.STATUS_LEVEL_NONE; - final SafetySourceStatus status = new SafetySourceStatus.Builder(title, summary, - SafetySourceStatus.STATUS_LEVEL_NONE, pendingIntent) - .setEnabled(enabled).build(); + final SafetySourceStatus status = new SafetySourceStatus.Builder( + title, summary, statusLevel, pendingIntent).setEnabled(enabled).build(); final SafetySourceData safetySourceData = new SafetySourceData.Builder().setStatus(status).build(); diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java index 6f955b2120a..10277927019 100644 --- a/src/com/android/settings/wifi/WifiUtils.java +++ b/src/com/android/settings/wifi/WifiUtils.java @@ -41,6 +41,8 @@ public class WifiUtils extends com.android.settingslib.wifi.WifiUtils { private static final int SSID_ASCII_MIN_LENGTH = 1; private static final int SSID_ASCII_MAX_LENGTH = 32; + private static final int PSK_PASSPHRASE_ASCII_MIN_LENGTH = 8; + private static final int PSK_PASSPHRASE_ASCII_MAX_LENGTH = 63; public static boolean isSSIDTooLong(String ssid) { if (TextUtils.isEmpty(ssid)) { @@ -62,6 +64,13 @@ public class WifiUtils extends com.android.settingslib.wifi.WifiUtils { public static boolean isHotspotPasswordValid(String password, int securityType) { final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); try { + if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK + || securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) { + if (password.length() < PSK_PASSPHRASE_ASCII_MIN_LENGTH + || password.length() > PSK_PASSPHRASE_ASCII_MAX_LENGTH) { + return false; + } + } configBuilder.setPassphrase(password, securityType); } catch (IllegalArgumentException e) { return false; diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java index 3fec81a16b3..49602bcb2e1 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java @@ -67,7 +67,7 @@ public class AccessibilityQuickSettingsTooltipWindowTest { @Test public void initTooltipView_atMostAvailableTextWidth() { final String quickSettingsTooltipsContent = mContext.getString( - R.string.accessibility_service_qs_tooltips_content, TEST_PACKAGE_NAME); + R.string.accessibility_service_qs_tooltip_content, TEST_PACKAGE_NAME); mTooltipView.setup(quickSettingsTooltipsContent, TEST_RES_ID); final int getMaxWidth = mTooltipView.getAvailableWindowWidth(); diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivityTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivityTest.java deleted file mode 100644 index 65b06477f88..00000000000 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardActivityTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 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.accessibility; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.Intent; - -import androidx.test.filters.SmallTest; - -import com.android.settings.R; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.Robolectric; -import org.robolectric.RobolectricTestRunner; - -@RunWith(RobolectricTestRunner.class) -@SmallTest -public class AccessibilitySettingsForSetupWizardActivityTest { - - @Test - public void createSetupAccessibilityActivity_shouldBeSUWTheme() { - final Intent intent = new Intent(); - AccessibilitySettingsForSetupWizardActivity activity = - Robolectric.buildActivity(AccessibilitySettingsForSetupWizardActivity.class, - intent).get(); - - assertThat(activity.getThemeResId()).isEqualTo(R.style.GlifV3Theme_Light); - } -} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java index f7c546fa015..c1950be2506 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java @@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atLeast; @@ -31,6 +33,7 @@ import static java.util.Collections.singletonList; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityShortcutInfo; +import android.app.AppOpsManager; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -110,6 +113,8 @@ public class AccessibilitySettingsTest { @Mock private PreferenceManager mPreferenceManager; private ShadowAccessibilityManager mShadowAccessibilityManager; + @Mock + private AppOpsManager mAppOpsManager; @Before public void setup() { @@ -121,6 +126,9 @@ public class AccessibilitySettingsTest { when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); mContext.setTheme(R.style.Theme_AppCompat); + when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager); + when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS), + anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ALLOWED); } @Test diff --git a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java index 4660f77f275..8d5724bb197 100644 --- a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java @@ -101,7 +101,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest { final CharSequence tileName = mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( - mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); + mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName)); } @Test @@ -115,7 +115,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest { mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( mContext.getString( - R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + R.string.accessibility_service_auto_added_qs_tooltip_content, tileName)); } @Test @@ -130,7 +130,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest { final CharSequence tileName = mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( - mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); + mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName)); } @Test @@ -146,7 +146,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest { mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( mContext.getString( - R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + R.string.accessibility_service_auto_added_qs_tooltip_content, tileName)); } private void setupTileService(String packageName, String name, String tileName) { diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java index ad5171ddaf5..226952990cf 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java @@ -101,7 +101,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { final CharSequence tileName = mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( - mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); + mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName)); } @Test @@ -115,7 +115,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( mContext.getString( - R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + R.string.accessibility_service_auto_added_qs_tooltip_content, tileName)); } @Test @@ -130,7 +130,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { final CharSequence tileName = mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( - mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName)); + mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName)); } @Test @@ -146,7 +146,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { mFragment.loadTileLabel(mContext, mFragment.getTileComponentName()); assertThat(tileTooltipContent.toString()).isEqualTo( mContext.getString( - R.string.accessibility_service_auto_added_qs_tooltips_content, tileName)); + R.string.accessibility_service_auto_added_qs_tooltip_content, tileName)); } private void setupTileService(String packageName, String name, String tileName) { diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java new file mode 100644 index 00000000000..ef812473565 --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2022 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.bluetooth; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.media.AudioDeviceAttributes; +import android.media.AudioManager; +import android.media.Spatializer; + +import androidx.preference.PreferenceCategory; +import androidx.preference.SwitchPreference; + +import com.android.settingslib.core.lifecycle.Lifecycle; + +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 java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetailsControllerTestBase { + + private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C"; + private static final String KEY_SPATIAL_AUDIO = "spatial_audio"; + private static final String KEY_HEAD_TRACKING = "head_tracking"; + + @Mock + private AudioManager mAudioManager; + @Mock + private Spatializer mSpatializer; + @Mock + private Lifecycle mSpatialAudioLifecycle; + @Mock + private PreferenceCategory mProfilesContainer; + + private BluetoothDetailsSpatialAudioController mController; + private SwitchPreference mSpatialAudioPref; + private SwitchPreference mHeadTrackingPref; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); + when(mAudioManager.getSpatializer()).thenReturn(mSpatializer); + when(mCachedDevice.getAddress()).thenReturn(MAC_ADDRESS); + + mController = new BluetoothDetailsSpatialAudioController(mContext, mFragment, + mCachedDevice, mSpatialAudioLifecycle); + mController.mProfilesContainer = mProfilesContainer; + + mSpatialAudioPref = mController.createSpatialAudioPreference(mContext); + mHeadTrackingPref = mController.createHeadTrackingPreference(mContext); + + when(mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO)).thenReturn(mSpatialAudioPref); + when(mProfilesContainer.findPreference(KEY_HEAD_TRACKING)).thenReturn(mHeadTrackingPref); + } + + @Test + public void isAvailable_spatialAudioIsAvailable_returnsTrue() { + when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true); + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_spatialAudioIsNotAvailable_returnsFalse() { + when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(false); + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void refresh_spatialAudioIsTurnedOn_checksSpatialAudioPreference() { + List compatibleAudioDevices = new ArrayList<>(); + compatibleAudioDevices.add(mController.mAudioDevice); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + + mController.refresh(); + + assertThat(mSpatialAudioPref.isChecked()).isTrue(); + } + + @Test + public void refresh_spatialAudioIsTurnedOff_unchecksSpatialAudioPreference() { + List compatibleAudioDevices = new ArrayList<>(); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + + mController.refresh(); + + assertThat(mSpatialAudioPref.isChecked()).isFalse(); + } + + @Test + public void refresh_spatialAudioOnAndHeadTrackingIsAvailable_showsHeadTrackingPreference() { + List compatibleAudioDevices = new ArrayList<>(); + compatibleAudioDevices.add(mController.mAudioDevice); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true); + + mController.refresh(); + + assertThat(mHeadTrackingPref.isVisible()).isTrue(); + } + + @Test + public void + refresh_spatialAudioOnAndHeadTrackingIsNotAvailable_hidesHeadTrackingPreference() { + List compatibleAudioDevices = new ArrayList<>(); + compatibleAudioDevices.add(mController.mAudioDevice); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false); + + mController.refresh(); + + assertThat(mHeadTrackingPref.isVisible()).isFalse(); + } + + @Test + public void refresh_spatialAudioOff_hidesHeadTrackingPreference() { + List compatibleAudioDevices = new ArrayList<>(); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + + mController.refresh(); + + assertThat(mHeadTrackingPref.isVisible()).isFalse(); + } + + @Test + public void refresh_headTrackingIsTurnedOn_checksHeadTrackingPreference() { + List compatibleAudioDevices = new ArrayList<>(); + compatibleAudioDevices.add(mController.mAudioDevice); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true); + when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true); + + mController.refresh(); + + assertThat(mHeadTrackingPref.isChecked()).isTrue(); + } + + @Test + public void refresh_headTrackingIsTurnedOff_unchecksHeadTrackingPreference() { + List compatibleAudioDevices = new ArrayList<>(); + compatibleAudioDevices.add(mController.mAudioDevice); + when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true); + when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false); + + mController.refresh(); + + assertThat(mHeadTrackingPref.isChecked()).isFalse(); + } + + @Test + public void turnedOnSpatialAudio_invokesAddCompatibleAudioDevice() { + mSpatialAudioPref.setChecked(true); + mController.onPreferenceClick(mSpatialAudioPref); + verify(mSpatializer).addCompatibleAudioDevice(mController.mAudioDevice); + } + + @Test + public void turnedOffSpatialAudio_invokesRemoveCompatibleAudioDevice() { + mSpatialAudioPref.setChecked(false); + mController.onPreferenceClick(mSpatialAudioPref); + verify(mSpatializer).removeCompatibleAudioDevice(mController.mAudioDevice); + } + + @Test + public void turnedOnHeadTracking_invokesSetHeadTrackerEnabled_setsTrue() { + mHeadTrackingPref.setChecked(true); + mController.onPreferenceClick(mHeadTrackingPref); + verify(mSpatializer).setHeadTrackerEnabled(true, mController.mAudioDevice); + } + + @Test + public void turnedOffHeadTracking_invokesSetHeadTrackerEnabled_setsFalse() { + mHeadTrackingPref.setChecked(false); + mController.onPreferenceClick(mHeadTrackingPref); + verify(mSpatializer).setHeadTrackerEnabled(false, mController.mAudioDevice); + } +} diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java index 064f8134c67..249b713987c 100644 --- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java @@ -18,12 +18,15 @@ package com.android.settings.applications.specialaccess.notificationaccess; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.AppOpsManager; import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; @@ -31,12 +34,12 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settingslib.RestrictedSwitchPreference; import org.junit.Before; import org.junit.Test; @@ -55,6 +58,8 @@ public class ApprovalPreferenceControllerTest { @Mock NotificationManager mNm; @Mock + AppOpsManager mAppOpsManager; + @Mock PackageManager mPm; PackageInfo mPkgInfo; ComponentName mCn = new ComponentName("a", "b"); @@ -75,15 +80,47 @@ public class ApprovalPreferenceControllerTest { mController.setNm(mNm); mController.setParent(mFragment); mController.setPkgInfo(mPkgInfo); + } @Test public void updateState_checked() { + when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( + AppOpsManager.MODE_ALLOWED); when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true); - SwitchPreference pref = new SwitchPreference(mContext); + RestrictedSwitchPreference pref = new RestrictedSwitchPreference( + mContext); + pref.setAppOps(mAppOpsManager); mController.updateState(pref); assertThat(pref.isChecked()).isTrue(); + assertThat(pref.isEnabled()).isTrue(); + } + + @Test + public void restrictedSettings_appOpsDisabled() { + when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( + AppOpsManager.MODE_ERRORED); + when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false); + RestrictedSwitchPreference pref = new RestrictedSwitchPreference( + mContext); + pref.setAppOps(mAppOpsManager); + + mController.updateState(pref); + assertThat(pref.isEnabled()).isFalse(); + } + + @Test + public void restrictedSettings_serviceAlreadyEnabled() { + when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( + AppOpsManager.MODE_ERRORED); + when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true); + RestrictedSwitchPreference pref = new RestrictedSwitchPreference( + mContext); + pref.setAppOps(mAppOpsManager); + + mController.updateState(pref); + assertThat(pref.isEnabled()).isTrue(); } @Test diff --git a/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java index 7d89079a017..10f11101ddf 100644 --- a/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java +++ b/tests/unit/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtilsTest.java @@ -57,8 +57,7 @@ public class CombinedBiometricStatusUtilsTest { private static final ComponentName COMPONENT_NAME = new ComponentName("package", "class"); private static final int USER_ID = UserHandle.myUserId(); - private static final UserHandle USER_HANDLE = new UserHandle(USER_ID);; - + private static final UserHandle USER_HANDLE = new UserHandle(USER_ID); @Mock private PackageManager mPackageManager; @@ -122,6 +121,54 @@ public class CombinedBiometricStatusUtilsTest { assertThat(mCombinedBiometricStatusUtils.isAvailable()).isTrue(); } + @Test + public void hasEnrolled_withoutFingerprintHardware_withoutFaceHardware_returnsFalse() { + when(mFingerprintManager.isHardwareDetected()).thenReturn(false); + when(mFaceManager.isHardwareDetected()).thenReturn(false); + + assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isFalse(); + } + + @Test + public void hasEnrolled_withoutFingerprintEnroll_withoutFaceEnroll_returnsFalse() { + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + + assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isFalse(); + } + + @Test + public void hasEnrolled_withoutFingerprintEnroll_withFaceEnroll_returnsTrue() { + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + + assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue(); + } + + @Test + public void hasEnrolled_withFingerprintEnroll_withoutFaceEnroll_returnsTrue() { + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + + assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue(); + } + + @Test + public void hasEnrolled_withFingerprintEnroll_withFaceEnroll_returnsTrue() { + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + + assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue(); + } + @Test public void getDisabledAdmin_whenFingerprintDisabled_whenFaceDisabled_returnsEnforcedAdmin() { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java index 8697da73466..9f9dd9355ec 100644 --- a/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java +++ b/tests/unit/src/com/android/settings/biometrics/face/FaceStatusUtilsTest.java @@ -114,6 +114,20 @@ public class FaceStatusUtilsTest { assertThat(mFaceStatusUtils.isAvailable()).isFalse(); } + @Test + public void hasEnrolled_withEnrolledTemplates_returnsTrue() { + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + + assertThat(mFaceStatusUtils.hasEnrolled()).isTrue(); + } + + @Test + public void hasEnrolled_withoutEnrolledTemplates_returnsFalse() { + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + + assertThat(mFaceStatusUtils.hasEnrolled()).isFalse(); + } + @Test public void getDisabledAdmin_whenFaceDisabled_returnsEnforcedAdmin() { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java index cbe42982155..4ecf82e3479 100644 --- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java +++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintStatusUtilsTest.java @@ -118,6 +118,20 @@ public class FingerprintStatusUtilsTest { assertThat(mFingerprintStatusUtils.isAvailable()).isFalse(); } + @Test + public void hasEnrolled_withEnrolledFingerprints_returnsTrue() { + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true); + + assertThat(mFingerprintStatusUtils.hasEnrolled()).isTrue(); + } + + @Test + public void hasEnrolled_withoutEnrolledFingerprints_returnsFalse() { + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + + assertThat(mFingerprintStatusUtils.hasEnrolled()).isFalse(); + } + @Test public void getDisabledAdmin_whenFingerprintDisabled_returnsEnforcedAdmin() { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) diff --git a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java index 13778f7bd0e..3030f0c1220 100644 --- a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java @@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -112,8 +113,8 @@ public class BiometricsSafetySourceTest { BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( - any(), any(), any(), any()); + verify(mSafetyCenterManagerWrapper, never()) + .setSafetySourceData(any(), any(), any(), any()); } @Test @@ -124,8 +125,8 @@ public class BiometricsSafetySourceTest { BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( - any(), any(), any(), any()); + verify(mSafetyCenterManagerWrapper, never()) + .setSafetySourceData(any(), any(), any(), any()); } @Test @@ -137,11 +138,9 @@ public class BiometricsSafetySourceTest { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - verify(mSafetyCenterManagerWrapper).setSafetySourceData( - any(), captor.capture(), any(), any()); - assertThat(captor.getValue()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), any(), any()); } @Test @@ -153,11 +152,9 @@ public class BiometricsSafetySourceTest { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - ArgumentCaptor captor = ArgumentCaptor.forClass(SafetyEvent.class); - verify(mSafetyCenterManagerWrapper).setSafetySourceData( - any(), any(), any(), captor.capture()); - assertThat(captor.getValue()).isEqualTo(EVENT_SOURCE_STATE_CHANGED); + verify(mSafetyCenterManagerWrapper) + .setSafetySourceData(any(), any(), any(), eq(EVENT_SOURCE_STATE_CHANGED)); } @Test @@ -429,6 +426,128 @@ public class BiometricsSafetySourceTest { Settings.CombinedBiometricSettingsActivity.class.getName()); } + @Test + public void setSafetySourceData_faceAndFingerprint_whenFaceEnrolled_setsOkStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK); + } + + @Test + public void setSafetySourceData_faceAndFingerprint_whenFingerprintEnrolled_setsOkStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK); + } + + @Test + public void setSafetySourceData_faceAndFingerprint_whenNotEnrolled_setsNoneStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE); + } + + @Test + public void setSafetySourceData_fingerprint_whenEnrolled_setsOKStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(false); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK); + } + + @Test + public void setSafetySourceData_fingerprint_whenNotEnrolled_setsNoneStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(false); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE); + } + + @Test + public void setSafetySourceData_face_whenEnrolled_setsOKStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(false); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK); + } + + @Test + public void setSafetySourceData_face_whenNotEnrolled_setsNoneStatus() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(false); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); + + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); + SafetySourceStatus safetySourceStatus = captor.getValue().getStatus(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE); + } + private void assertSafetySourceDisabledDataSetWithSingularSummary(String expectedTitleResName, String expectedSummaryResName) { assertSafetySourceDisabledDataSet( @@ -478,13 +597,16 @@ public class BiometricsSafetySourceTest { private void assertSafetySourceDisabledDataSet(String expectedTitle, String expectedSummary) { ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); verify(mSafetyCenterManagerWrapper).setSafetySourceData( - any(), any(), captor.capture(), any()); + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle); assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary); assertThat(safetySourceStatus.isEnabled()).isFalse(); + assertThat(safetySourceStatus.getStatusLevel()) + .isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE); + final Intent clickIntent = safetySourceStatus.getPendingIntent().getIntent(); assertThat(clickIntent).isNotNull(); assertThat(clickIntent.getAction()).isEqualTo(ACTION_SHOW_ADMIN_SUPPORT_DETAILS); @@ -494,7 +616,7 @@ public class BiometricsSafetySourceTest { String expectedSettingsClassName) { ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); verify(mSafetyCenterManagerWrapper).setSafetySourceData( - any(), any(), captor.capture(), any()); + any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -509,7 +631,6 @@ public class BiometricsSafetySourceTest { .isEqualTo(expectedSettingsClassName); } - private List createFingerprintList(int size) { final List fingerprintList = new ArrayList<>(size); for (int i = 0; i < size; i++) {