From bc67cf5102925c8e5b5680acc95e1d8554f58878 Mon Sep 17 00:00:00 2001 From: menghanli Date: Mon, 14 Feb 2022 09:26:36 +0800 Subject: [PATCH 01/13] Polish humanize strings for one-handed mode page - Add an intro for purpose or behavior - Update footer description on usage, availability, or limitations Bug: 218408813 Test: manual testing Change-Id: I1712a3dcc08bf71ca8caf4097a23d465156bec22 --- res/values/strings.xml | 8 +++++++- res/xml/one_handed_settings.xml | 17 +++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 917c666b41f..730db4baa4a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11811,8 +11811,14 @@ Swipe down to Use the shortcut to + + Pull down the top half of your screen so it\u2019s easier to reach with one hand - To use one handed mode, swipe down from the bottom edge of the screen. To use this feature, make sure gesture navigation is turned on in system navigation settings. + + How to use one-handed mode\n + • Make sure gesture navigation is selected in system navigation settings\n + • Swipe down near the bottom edge of the screen + Pull screen into reach diff --git a/res/xml/one_handed_settings.xml b/res/xml/one_handed_settings.xml index 523cf4db253..7406993d7fc 100644 --- a/res/xml/one_handed_settings.xml +++ b/res/xml/one_handed_settings.xml @@ -22,6 +22,10 @@ android:persistent="false" android:title="@string/one_handed_title"> + + - - + settings:controller="com.android.settings.gesture_one_handed_mode_footer_textgestures.OneHandedActionPullDownPrefController"/> - + + From b72d5aba2d9a3db415294f7f47bf568b35dd4f45 Mon Sep 17 00:00:00 2001 From: Daniel Hsieh Date: Wed, 2 Mar 2022 07:38:38 +0000 Subject: [PATCH 02/13] Change magnify typing setting item's string. Change magnify typing setting item's title and description. Bug: 221952566 Test: Manually, I check the string on the screen. Change-Id: I3cc9885aaf99745ce9edfef08ec122294487e8d0 --- res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 3363f929c25..9090fb97f8d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5189,9 +5189,9 @@ Magnification shortcut - Follow typing + Magnify typing - Magnification area automatically follows the text as you type + Magnifier follows text as you type About magnification From e23cd8ad0b0e141cfec086a81b7ac796ed070d4e Mon Sep 17 00:00:00 2001 From: Karishma Vakil Date: Mon, 21 Feb 2022 09:35:51 +0000 Subject: [PATCH 03/13] [SafetyCenter] Update Settings to align with renamed SafetyCenterManager APIs Test: atest SettingsUnitTests Bug: 219195246 Bug: 219078602 Bug: 218852160 Change-Id: Ieaa1c9d04a0a9805abb10025f170cd9283b4a906 Merged-In: Ieaa1c9d04a0a9805abb10025f170cd9283b4a906 --- .../settings/biometrics/face/FaceUpdater.java | 4 +- .../fingerprint/FingerprintUpdater.java | 4 +- .../safetycenter/BiometricsSafetySource.java | 43 +++-- .../safetycenter/LockScreenSafetySource.java | 26 ++- .../SafetyCenterManagerWrapper.java | 20 +- .../SafetySourceBroadcastReceiver.java | 34 +++- .../BiometricsSafetySourceTest.java | 174 +++++++++++------- .../LockScreenSafetySourceTest.java | 144 ++++++++++----- .../SafetySourceBroadcastReceiverTest.java | 93 +++++++--- 9 files changed, 357 insertions(+), 185 deletions(-) diff --git a/src/com/android/settings/biometrics/face/FaceUpdater.java b/src/com/android/settings/biometrics/face/FaceUpdater.java index bb77caefb27..3a1f77c4352 100644 --- a/src/com/android/settings/biometrics/face/FaceUpdater.java +++ b/src/com/android/settings/biometrics/face/FaceUpdater.java @@ -104,7 +104,7 @@ public class FaceUpdater { public void onEnrollmentProgress(int remaining) { mCallback.onEnrollmentProgress(remaining); if (remaining == 0) { - BiometricsSafetySource.sendSafetyData(mContext); // biometrics data changed + BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed } } } @@ -131,7 +131,7 @@ public class FaceUpdater { @Override public void onRemovalSucceeded(@Nullable Face fp, int remaining) { mCallback.onRemovalSucceeded(fp, remaining); - BiometricsSafetySource.sendSafetyData(mContext); // biometrics data changed + BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed } } } diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java index 75d8f7b80b2..66ed0856828 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java @@ -88,7 +88,7 @@ public class FingerprintUpdater { public void onEnrollmentProgress(int remaining) { mCallback.onEnrollmentProgress(remaining); if (remaining == 0) { - BiometricsSafetySource.sendSafetyData(mContext); // biometrics data changed + BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed } } } @@ -115,7 +115,7 @@ public class FingerprintUpdater { @Override public void onRemovalSucceeded(@Nullable Fingerprint fp, int remaining) { mCallback.onRemovalSucceeded(fp, remaining); - BiometricsSafetySource.sendSafetyData(mContext); // biometrics data changed + BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed } } } diff --git a/src/com/android/settings/safetycenter/BiometricsSafetySource.java b/src/com/android/settings/safetycenter/BiometricsSafetySource.java index 6a93bda03c4..59408c7328b 100644 --- a/src/com/android/settings/safetycenter/BiometricsSafetySource.java +++ b/src/com/android/settings/safetycenter/BiometricsSafetySource.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; +import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceStatus; @@ -38,11 +39,10 @@ public final class BiometricsSafetySource { public static final String SAFETY_SOURCE_ID = "Biometrics"; - private BiometricsSafetySource() { - } + private BiometricsSafetySource() {} - /** Sends biometric safety data to Safety Center. */ - public static void sendSafetyData(Context context) { + /** Sets biometric safety data for Safety Center. */ + public static void setSafetySourceData(Context context, SafetyEvent safetyEvent) { if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { return; } @@ -54,13 +54,14 @@ public final class BiometricsSafetySource { if (combinedBiometricStatusUtils.isAvailable()) { final RestrictedLockUtils.EnforcedAdmin disablingAdmin = combinedBiometricStatusUtils.getDisablingAdmin(); - sendBiometricSafetySourceData(context, + setBiometricSafetySourceData(context, context.getString(R.string.security_settings_biometric_preference_title), combinedBiometricStatusUtils.getSummary(), biometricNavigationUtils.getBiometricSettingsIntent(context, combinedBiometricStatusUtils.getSettingsClassName(), disablingAdmin, Bundle.EMPTY), - disablingAdmin == null /* enabled */); + disablingAdmin == null /* enabled */, + safetyEvent); return; } @@ -70,13 +71,15 @@ public final class BiometricsSafetySource { if (faceStatusUtils.isAvailable()) { final RestrictedLockUtils.EnforcedAdmin disablingAdmin = faceStatusUtils.getDisablingAdmin(); - sendBiometricSafetySourceData(context, + setBiometricSafetySourceData(context, context.getString(R.string.security_settings_face_preference_title), faceStatusUtils.getSummary(), biometricNavigationUtils.getBiometricSettingsIntent(context, faceStatusUtils.getSettingsClassName(), disablingAdmin, Bundle.EMPTY), - disablingAdmin == null /* enabled */); + disablingAdmin == null /* enabled */, + safetyEvent); + return; } @@ -87,27 +90,37 @@ public final class BiometricsSafetySource { if (fingerprintStatusUtils.isAvailable()) { final RestrictedLockUtils.EnforcedAdmin disablingAdmin = fingerprintStatusUtils.getDisablingAdmin(); - sendBiometricSafetySourceData(context, + setBiometricSafetySourceData(context, context.getString(R.string.security_settings_fingerprint_preference_title), fingerprintStatusUtils.getSummary(), biometricNavigationUtils.getBiometricSettingsIntent(context, fingerprintStatusUtils.getSettingsClassName(), disablingAdmin, Bundle.EMPTY), - disablingAdmin == null /* enabled */); + disablingAdmin == null /* enabled */, + safetyEvent); } } - private static void sendBiometricSafetySourceData(Context context, String title, String summary, - Intent clickIntent, boolean enabled) { + /** Notifies Safety Center of a change in biometrics settings. */ + public static void onBiometricsChanged(Context context) { + setSafetySourceData( + context, + new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build() + ); + } + + private static void setBiometricSafetySourceData(Context context, String title, String summary, + Intent clickIntent, boolean enabled, SafetyEvent safetyEvent) { final PendingIntent pendingIntent = createPendingIntent(context, clickIntent); final SafetySourceStatus status = new SafetySourceStatus.Builder(title, summary, SafetySourceStatus.STATUS_LEVEL_NONE, pendingIntent) .setEnabled(enabled).build(); - final SafetySourceData safetySourceData = new SafetySourceData.Builder(SAFETY_SOURCE_ID) - .setStatus(status).build(); + final SafetySourceData safetySourceData = + new SafetySourceData.Builder().setStatus(status).build(); - SafetyCenterManagerWrapper.get().sendSafetyCenterUpdate(context, safetySourceData); + SafetyCenterManagerWrapper.get().setSafetySourceData( + context, SAFETY_SOURCE_ID, safetySourceData, safetyEvent); } private static PendingIntent createPendingIntent(Context context, Intent intent) { diff --git a/src/com/android/settings/safetycenter/LockScreenSafetySource.java b/src/com/android/settings/safetycenter/LockScreenSafetySource.java index d0108210476..ad0bd3a8de4 100644 --- a/src/com/android/settings/safetycenter/LockScreenSafetySource.java +++ b/src/com/android/settings/safetycenter/LockScreenSafetySource.java @@ -16,11 +16,14 @@ package com.android.settings.safetycenter; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED; + import android.app.PendingIntent; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.os.UserHandle; +import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.safetycenter.SafetySourceStatus; @@ -42,9 +45,10 @@ public final class LockScreenSafetySource { private LockScreenSafetySource() { } - /** Sends lock screen safety data to Safety Center. */ - public static void sendSafetyData(Context context, - ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils) { + /** Sets lock screen safety data for Safety Center. */ + public static void setSafetySourceData(Context context, + ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils, + SafetyEvent safetyEvent) { if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { return; } @@ -71,21 +75,27 @@ public final class LockScreenSafetySource { .setEnabled( !screenLockPreferenceDetailsUtils.isPasswordQualityManaged(userId, admin)) .setIconAction(gearMenuIconAction).build(); - final SafetySourceData.Builder safetySourceDataBuilder = new SafetySourceData.Builder( - SAFETY_SOURCE_ID).setStatus(status); + final SafetySourceData.Builder safetySourceDataBuilder = + new SafetySourceData.Builder().setStatus(status); if (!screenLockPreferenceDetailsUtils.isLockPatternSecure()) { safetySourceDataBuilder.addIssue(createNoScreenLockIssue(context, pendingIntent)); } final SafetySourceData safetySourceData = safetySourceDataBuilder.build(); - SafetyCenterManagerWrapper.get().sendSafetyCenterUpdate(context, safetySourceData); + SafetyCenterManagerWrapper.get().setSafetySourceData( + context, + SAFETY_SOURCE_ID, + safetySourceData, + safetyEvent + ); } /** Notifies Safety Center of a change in lock screen settings. */ public static void onLockScreenChange(Context context) { - sendSafetyData( + setSafetySourceData( context, - new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER)); + new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER), + new SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()); } private static IconAction createGearMenuIconAction(Context context, diff --git a/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java b/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java index e4a1d673c4d..e7205260833 100644 --- a/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java +++ b/src/com/android/settings/safetycenter/SafetyCenterManagerWrapper.java @@ -18,6 +18,7 @@ package com.android.settings.safetycenter; import android.content.Context; import android.safetycenter.SafetyCenterManager; +import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.util.Log; @@ -26,7 +27,12 @@ import com.android.internal.annotations.VisibleForTesting; /** A wrapper for the SafetyCenterManager system service. */ public class SafetyCenterManagerWrapper { - private static final String TAG = "SafetyCenterManagerWrapper"; + /** + * Tag for logging. + * + *

The tag is restricted to 23 characters (the maximum allowed for Android logging). + */ + private static final String TAG = "SafetyCenterManagerWrap"; @VisibleForTesting public static SafetyCenterManagerWrapper sInstance; @@ -41,8 +47,10 @@ public class SafetyCenterManagerWrapper { return sInstance; } - /** Sends updated safety source data to Safety Center. */ - public void sendSafetyCenterUpdate(Context context, SafetySourceData safetySourceData) { + /** Sets the latest safety source data for Safety Center. */ + public void setSafetySourceData(Context context, String safetySourceId, + SafetySourceData safetySourceData, + SafetyEvent safetyEvent) { SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class); @@ -52,7 +60,11 @@ public class SafetyCenterManagerWrapper { } try { - safetyCenterManager.sendSafetyCenterUpdate(safetySourceData); + safetyCenterManager.setSafetySourceData( + safetySourceId, + safetySourceData, + safetyEvent + ); } catch (Exception e) { Log.e(TAG, "Failed to send SafetySourceData", e); return; diff --git a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java index a0d18c7d09f..38458d92571 100644 --- a/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java +++ b/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiver.java @@ -19,11 +19,14 @@ package com.android.settings.safetycenter; import static android.content.Intent.ACTION_BOOT_COMPLETED; import static android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES; import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED; import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.safetycenter.SafetyEvent; import com.android.settings.security.ScreenLockPreferenceDetailsUtils; @@ -34,6 +37,11 @@ import java.util.List; /** Broadcast receiver for handling requests from Safety Center for fresh data. */ public class SafetySourceBroadcastReceiver extends BroadcastReceiver { + private static final SafetyEvent EVENT_REFRESH_REQUESTED = + new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED).build(); + private static final SafetyEvent EVENT_DEVICE_REBOOTED = + new SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build(); + @Override public void onReceive(Context context, Intent intent) { if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { @@ -44,31 +52,37 @@ public class SafetySourceBroadcastReceiver extends BroadcastReceiver { String[] sourceIdsExtra = intent.getStringArrayExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS); if (sourceIdsExtra != null && sourceIdsExtra.length > 0) { - refreshSafetySources(context, ImmutableList.copyOf(sourceIdsExtra)); + refreshSafetySources( + context, + ImmutableList.copyOf(sourceIdsExtra), + EVENT_REFRESH_REQUESTED); } return; } if (ACTION_BOOT_COMPLETED.equals(intent.getAction())) { - refreshAllSafetySources(context); + refreshAllSafetySources(context, EVENT_DEVICE_REBOOTED); } } - private static void refreshSafetySources(Context context, List sourceIds) { + private static void refreshSafetySources(Context context, List sourceIds, + SafetyEvent safetyEvent) { if (sourceIds.contains(LockScreenSafetySource.SAFETY_SOURCE_ID)) { - LockScreenSafetySource.sendSafetyData(context, - new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER)); + LockScreenSafetySource.setSafetySourceData(context, + new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER), + safetyEvent); } if (sourceIds.contains(BiometricsSafetySource.SAFETY_SOURCE_ID)) { - BiometricsSafetySource.sendSafetyData(context); + BiometricsSafetySource.setSafetySourceData(context, safetyEvent); } } - private static void refreshAllSafetySources(Context context) { - LockScreenSafetySource.sendSafetyData(context, - new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER)); - BiometricsSafetySource.sendSafetyData(context); + private static void refreshAllSafetySources(Context context, SafetyEvent safetyEvent) { + LockScreenSafetySource.setSafetySourceData(context, + new ScreenLockPreferenceDetailsUtils(context, SettingsEnums.SAFETY_CENTER), + safetyEvent); + BiometricsSafetySource.setSafetySourceData(context, safetyEvent); } } diff --git a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java index 4a91e8faa19..13778f7bd0e 100644 --- a/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/BiometricsSafetySourceTest.java @@ -17,6 +17,7 @@ package com.android.settings.safetycenter; import static android.provider.Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED; import static com.google.common.truth.Truth.assertThat; @@ -36,6 +37,7 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.os.UserHandle; +import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceStatus; @@ -66,6 +68,8 @@ public class BiometricsSafetySourceTest { private static final ComponentName COMPONENT_NAME = new ComponentName("package", "class"); private static final UserHandle USER_HANDLE = new UserHandle(UserHandle.myUserId()); + private static final SafetyEvent EVENT_SOURCE_STATE_CHANGED = + new SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build(); private Context mApplicationContext; @@ -103,27 +107,61 @@ public class BiometricsSafetySourceTest { } @Test - public void sendSafetyData_whenSafetyCenterIsDisabled_sendsNoData() { + public void setSafetyData_whenSafetyCenterIsDisabled_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_whenSafetyCenterIsEnabled_withoutBiometrics_sendsNoData() { + public void setSafetySourceData_whenSafetyCenterIsEnabled_withoutBiometrics_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); when(mFingerprintManager.isHardwareDetected()).thenReturn(false); when(mFaceManager.isHardwareDetected()).thenReturn(false); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_withFingerprintNotEnrolled_whenDisabledByAdmin_sendsData() { + public void setSafetySourceData_setsDataForBiometricSource() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(false); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + 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); + } + + @Test + public void setSafetySourceData_setsDataWithCorrectSafetyEvent() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + when(mFaceManager.isHardwareDetected()).thenReturn(false); + when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); + 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); + } + + @Test + public void setSafetySourceData_withFingerprintNotEnrolled_whenDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(false); @@ -131,31 +169,31 @@ public class BiometricsSafetySourceTest { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceDisabledDataSentWithSingularSummary( + assertSafetySourceDisabledDataSetWithSingularSummary( "security_settings_fingerprint_preference_title", "security_settings_fingerprint_preference_summary_none"); } @Test - public void sendSafetyData_withFingerprintNotEnrolled_whenNotDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFingerprintNotEnrolled_whenNotDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(false); when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_fingerprint_preference_title", "security_settings_fingerprint_preference_summary_none", FingerprintEnrollIntroduction.class.getName()); } @Test - public void sendSafetyData_withFingerprintsEnrolled_whenDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFingerprintsEnrolled_whenDisabledByAdmin_setsData() { final int enrolledFingerprintsCount = 2; when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); @@ -166,16 +204,16 @@ public class BiometricsSafetySourceTest { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceDisabledDataSentWithPluralSummary( + assertSafetySourceDisabledDataSetWithPluralSummary( "security_settings_fingerprint_preference_title", "security_settings_fingerprint_preference_summary", enrolledFingerprintsCount); } @Test - public void sendSafetyData_withFingerprintsEnrolled_whenNotDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFingerprintsEnrolled_whenNotDisabledByAdmin_setsData() { final int enrolledFingerprintsCount = 2; when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); @@ -185,16 +223,16 @@ public class BiometricsSafetySourceTest { .thenReturn(createFingerprintList(enrolledFingerprintsCount)); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithPluralSummary( + assertSafetySourceEnabledDataSetWithPluralSummary( "security_settings_fingerprint_preference_title", "security_settings_fingerprint_preference_summary", enrolledFingerprintsCount, FingerprintSettings.class.getName()); } @Test - public void sendSafetyData_withFaceNotEnrolled_whenDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFaceNotEnrolled_whenDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(false); when(mFaceManager.isHardwareDetected()).thenReturn(true); @@ -202,31 +240,31 @@ public class BiometricsSafetySourceTest { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceDisabledDataSentWithSingularSummary( + assertSafetySourceDisabledDataSetWithSingularSummary( "security_settings_face_preference_title", "security_settings_face_preference_summary_none"); } @Test - public void sendSafetyData_withFaceNotEnrolled_whenNotDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFaceNotEnrolled_whenNotDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(false); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_face_preference_title", "security_settings_face_preference_summary_none", FaceEnrollIntroduction.class.getName()); } @Test - public void sendSafetyData_withFaceEnrolled_whenDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFaceEnrolled_whenDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(false); when(mFaceManager.isHardwareDetected()).thenReturn(true); @@ -234,78 +272,78 @@ public class BiometricsSafetySourceTest { when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceDisabledDataSentWithSingularSummary( + assertSafetySourceDisabledDataSetWithSingularSummary( "security_settings_face_preference_title", "security_settings_face_preference_summary"); } @Test - public void sendSafetyData_withFaceEnrolled_whenNotDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFaceEnrolled_whenNotDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(false); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_face_preference_title", "security_settings_face_preference_summary", Settings.FaceSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenBothNotDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFaceAndFingerprint_whenBothNotDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_biometric_preference_summary_none_enrolled", Settings.CombinedBiometricSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenFaceDisabledByAdmin_sendsData() { + public void setSafetySourceData_withFaceAndFingerprint_whenFaceDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_biometric_preference_summary_none_enrolled", Settings.CombinedBiometricSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenFingerprintDisabledByAdmin_sendsData() { + public void setSafetySourceData_faceAndFingerprint_whenFingerprintDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_biometric_preference_summary_none_enrolled", Settings.CombinedBiometricSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenBothDisabledByAdmin_sendsData() { + public void setSafetySourceData_faceAndFingerprint_whenBothDisabledByAdmin_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(true); @@ -313,15 +351,15 @@ public class BiometricsSafetySourceTest { .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceDisabledDataSentWithSingularSummary( + assertSafetySourceDisabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_biometric_preference_summary_none_enrolled"); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenFaceEnrolled_withMpFingers_sendsData() { + public void setSafetySourceData_faceAndFingerprint_whenFaceEnrolled_withMpFingers_setsData() { final int enrolledFingerprintsCount = 2; when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); @@ -330,16 +368,16 @@ public class BiometricsSafetySourceTest { when(mFingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn( createFingerprintList(enrolledFingerprintsCount)); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_biometric_preference_summary_both_fp_multiple", Settings.CombinedBiometricSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenFaceEnrolled_withOneFinger_sendsData() { + public void setSafetySourceData_faceAndFingerprint_whenFaceEnrolled_withOneFinger_setsData() { final int enrolledFingerprintsCount = 1; when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); @@ -348,16 +386,16 @@ public class BiometricsSafetySourceTest { when(mFingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn( createFingerprintList(enrolledFingerprintsCount)); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_biometric_preference_summary_both_fp_single", Settings.CombinedBiometricSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenFaceEnrolled_withNoFingers_sendsData() { + public void setSafetySourceData_faceAndFingerprint_whenFaceEnrolled_withNoFingers_setsData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.isHardwareDetected()).thenReturn(true); @@ -365,16 +403,16 @@ public class BiometricsSafetySourceTest { when(mFingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn( Collections.emptyList()); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithSingularSummary( + assertSafetySourceEnabledDataSetWithSingularSummary( "security_settings_biometric_preference_title", "security_settings_face_preference_summary", Settings.CombinedBiometricSettingsActivity.class.getName()); } @Test - public void sandSafetyData_withFaceAndFingerprint_whenNoFaceEnrolled_withFingers_sendsData() { + public void setSafetySourceData_faceAndFingerprint_whenNoFaceEnrolled_withFingers_setsData() { final int enrolledFingerprintsCount = 1; when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); @@ -383,38 +421,38 @@ public class BiometricsSafetySourceTest { when(mFingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn( createFingerprintList(enrolledFingerprintsCount)); - BiometricsSafetySource.sendSafetyData(mApplicationContext); + BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED); - assertSafetySourceEnabledDataSentWithPluralSummary( + assertSafetySourceEnabledDataSetWithPluralSummary( "security_settings_biometric_preference_title", "security_settings_fingerprint_preference_summary", enrolledFingerprintsCount, Settings.CombinedBiometricSettingsActivity.class.getName()); } - private void assertSafetySourceDisabledDataSentWithSingularSummary(String expectedTitleResName, + private void assertSafetySourceDisabledDataSetWithSingularSummary(String expectedTitleResName, String expectedSummaryResName) { - assertSafetySourceDisabledDataSent( + assertSafetySourceDisabledDataSet( ResourcesUtils.getResourcesString(mApplicationContext, expectedTitleResName), ResourcesUtils.getResourcesString(mApplicationContext, expectedSummaryResName) ); } - private void assertSafetySourceEnabledDataSentWithSingularSummary(String expectedTitleResName, + private void assertSafetySourceEnabledDataSetWithSingularSummary(String expectedTitleResName, String expectedSummaryResName, String expectedSettingsClassName) { - assertSafetySourceEnabledDataSent( + assertSafetySourceEnabledDataSet( ResourcesUtils.getResourcesString(mApplicationContext, expectedTitleResName), ResourcesUtils.getResourcesString(mApplicationContext, expectedSummaryResName), expectedSettingsClassName ); } - private void assertSafetySourceDisabledDataSentWithPluralSummary(String expectedTitleResName, + private void assertSafetySourceDisabledDataSetWithPluralSummary(String expectedTitleResName, String expectedSummaryResName, int expectedSummaryQuantity) { final int stringResId = ResourcesUtils.getResourcesId( ApplicationProvider.getApplicationContext(), "plurals", expectedSummaryResName); - assertSafetySourceDisabledDataSent( + assertSafetySourceDisabledDataSet( ResourcesUtils.getResourcesString(mApplicationContext, expectedTitleResName), mApplicationContext.getResources().getQuantityString(stringResId, expectedSummaryQuantity /* quantity */, @@ -422,13 +460,13 @@ public class BiometricsSafetySourceTest { ); } - private void assertSafetySourceEnabledDataSentWithPluralSummary(String expectedTitleResName, + private void assertSafetySourceEnabledDataSetWithPluralSummary(String expectedTitleResName, String expectedSummaryResName, int expectedSummaryQuantity, String expectedSettingsClassName) { final int stringResId = ResourcesUtils.getResourcesId( ApplicationProvider.getApplicationContext(), "plurals", expectedSummaryResName); - assertSafetySourceEnabledDataSent( + assertSafetySourceEnabledDataSet( ResourcesUtils.getResourcesString(mApplicationContext, expectedTitleResName), mApplicationContext.getResources().getQuantityString(stringResId, expectedSummaryQuantity /* quantity */, @@ -437,13 +475,13 @@ public class BiometricsSafetySourceTest { ); } - private void assertSafetySourceDisabledDataSent(String expectedTitle, String expectedSummary) { + private void assertSafetySourceDisabledDataSet(String expectedTitle, String expectedSummary) { ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); - assertThat(safetySourceData.getId()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID); assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle); assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary); assertThat(safetySourceStatus.isEnabled()).isFalse(); @@ -452,14 +490,14 @@ public class BiometricsSafetySourceTest { assertThat(clickIntent.getAction()).isEqualTo(ACTION_SHOW_ADMIN_SUPPORT_DETAILS); } - private void assertSafetySourceEnabledDataSent(String expectedTitle, String expectedSummary, + private void assertSafetySourceEnabledDataSet(String expectedTitle, String expectedSummary, String expectedSettingsClassName) { ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); - assertThat(safetySourceData.getId()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID); assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle); assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary); assertThat(safetySourceStatus.isEnabled()).isTrue(); diff --git a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java index 90a24aa5a11..db2702d58b2 100644 --- a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java @@ -16,6 +16,8 @@ package com.android.settings.safetycenter; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -26,6 +28,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; +import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.safetycenter.SafetySourceStatus; @@ -53,6 +56,8 @@ public class LockScreenSafetySourceTest { private static final String SUMMARY = "summary"; private static final String FAKE_ACTION_CHOOSE_LOCK_GENERIC_FRAGMENT = "choose_lock_generic"; private static final String FAKE_ACTION_SCREEN_LOCK_SETTINGS = "screen_lock_settings"; + private static final SafetyEvent EVENT_SOURCE_STATE_CHANGED = + new SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build(); private Context mApplicationContext; @@ -81,42 +86,74 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenScreenLockIsEnabled_whenSafetyCenterIsDisabled_sendsNoData() { + public void setSafetySourceData_whenScreenLockEnabled_safetyCenterDisabled_doesNotSetData() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); when(mScreenLockPreferenceDetailsUtils.isAvailable()).thenReturn(true); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_whenScreenLockIsDisabled_sendsNoData() { + public void setSafetySourceData_whenScreenLockIsDisabled_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isAvailable()).thenReturn(false); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_whenScreenLockIsEnabled_sendsData() { + public void setSafetySourceData_setsDataForLockscreenSafetySource() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); + ArgumentCaptor idCaptor = ArgumentCaptor.forClass(String.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), idCaptor.capture(), any(), any()); + String safetySourceId = idCaptor.getValue(); + + assertThat(safetySourceId).isEqualTo(LockScreenSafetySource.SAFETY_SOURCE_ID); + } + + @Test + public void setSafetySourceData_setsDataWithCorrectSafetyEvent() { + whenScreenLockIsEnabled(); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); + ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(SafetyEvent.class); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), any(), eventCaptor.capture()); + SafetyEvent safetyEvent = eventCaptor.getValue(); + + assertThat(safetyEvent).isEqualTo(EVENT_SOURCE_STATE_CHANGED); + } + + @Test + public void setSafetySourceData_whenScreenLockIsEnabled_setData() { + whenScreenLockIsEnabled(); + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); - assertThat(safetySourceData.getId()).isEqualTo(LockScreenSafetySource.SAFETY_SOURCE_ID); assertThat(safetySourceStatus.getTitle().toString()) .isEqualTo(ResourcesUtils.getResourcesString( mApplicationContext, @@ -129,16 +166,17 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenLockPatternIsSecure_sendsStatusLevelOk() { + public void setSafetySourceData_whenLockPatternIsSecure_setStatusLevelOk() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).thenReturn(true); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -147,16 +185,17 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenLockPatternIsNotSecure_sendsStatusLevelRecommendation() { + public void setSafetySourceData_whenLockPatternIsNotSecure_setStatusLevelRecommendation() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).thenReturn(false); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -165,32 +204,34 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenLockPatternIsSecure_sendsNoIssues() { + public void setSafetySourceData_whenLockPatternIsSecure_doesNotSetIssues() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).thenReturn(true); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); assertThat(safetySourceData.getIssues()).isEmpty(); } @Test - public void sendSafetyData_whenLockPatternIsNotSecure_sendsIssue() { + public void setSafetySourceData_whenLockPatternIsNotSecure_setIssue() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).thenReturn(false); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); assertThat(safetySourceData.getIssues()).hasSize(1); @@ -218,17 +259,18 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenPasswordQualityIsManaged_sendsDisabled() { + public void setSafetySourceData_whenPasswordQualityIsManaged_setDisabled() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isPasswordQualityManaged(anyInt(), any())) .thenReturn(true); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -236,17 +278,18 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenPasswordQualityIsNotManaged_sendsEnabled() { + public void setSafetySourceData_whenPasswordQualityIsNotManaged_setEnabled() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.isPasswordQualityManaged(anyInt(), any())) .thenReturn(false); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -254,7 +297,7 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenShouldShowGearMenu_sendsGearMenuActionIcon() { + public void setSafetySourceData_whenShouldShowGearMenu_setGearMenuActionIcon() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); final Intent launchScreenLockSettings = new Intent(FAKE_ACTION_SCREEN_LOCK_SETTINGS); @@ -262,12 +305,13 @@ public class LockScreenSafetySourceTest { .thenReturn(launchScreenLockSettings); when(mScreenLockPreferenceDetailsUtils.shouldShowGearMenu()).thenReturn(true); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); final ArgumentCaptor captor = ArgumentCaptor.forClass( SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); final IconAction iconAction = captor.getValue().getStatus().getIconAction(); assertThat(iconAction.getIconType()).isEqualTo(IconAction.ICON_TYPE_GEAR); @@ -276,16 +320,17 @@ public class LockScreenSafetySourceTest { } @Test - public void sendSafetyData_whenShouldNotShowGearMenu_sendsNoGearMenuActionIcon() { + public void setSafetySourceData_whenShouldNotShowGearMenu_doesNotSetGearMenuActionIcon() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); when(mScreenLockPreferenceDetailsUtils.shouldShowGearMenu()).thenReturn(false); - LockScreenSafetySource.sendSafetyData(mApplicationContext, - mScreenLockPreferenceDetailsUtils); + LockScreenSafetySource.setSafetySourceData(mApplicationContext, + mScreenLockPreferenceDetailsUtils, EVENT_SOURCE_STATE_CHANGED); ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), captor.capture()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData( + any(), any(), captor.capture(), any()); SafetySourceData safetySourceData = captor.getValue(); SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -293,23 +338,24 @@ public class LockScreenSafetySourceTest { } @Test - public void onLockScreenChange_whenSafetyCenterEnabled_sendsData() { + public void onLockScreenChange_whenSafetyCenterEnabled_setData() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); LockScreenSafetySource.onLockScreenChange(mApplicationContext); - verify(mSafetyCenterManagerWrapper).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper).setSafetySourceData(any(), any(), any(), any()); } @Test - public void onLockScreenChange_whenSafetyCenterDisabled_sendsNoData() { + public void onLockScreenChange_whenSafetyCenterDisabled_doesNotSetData() { whenScreenLockIsEnabled(); when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); LockScreenSafetySource.onLockScreenChange(mApplicationContext); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } private void whenScreenLockIsEnabled() { diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java index f042c2279fa..8a4214ced2e 100644 --- a/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/SafetySourceBroadcastReceiverTest.java @@ -18,6 +18,8 @@ package com.android.settings.safetycenter; import static android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES; import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED; +import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED; import static com.google.common.truth.Truth.assertThat; @@ -29,7 +31,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; -import android.safetycenter.SafetySourceData; +import android.safetycenter.SafetyEvent; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -45,6 +47,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Arrays; import java.util.List; @RunWith(AndroidJUnit4.class) @@ -74,17 +77,18 @@ public class SafetySourceBroadcastReceiverTest { } @Test - public void sendSafetyData_whenSafetyCenterIsEnabled_withNoIntentAction_sendsNoData() { + public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent().putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[]{}); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_whenSafetyCenterIsDisabled_sendsNoData() { + public void onReceive_onRefresh_whenSafetyCenterIsDisabled_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false); Intent intent = new Intent() @@ -95,21 +99,23 @@ public class SafetySourceBroadcastReceiverTest { new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_whenSafetyCenterIsEnabled_withNullSourceIds_sendsNoData() { + public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNullSourceIds_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent().setAction(ACTION_REFRESH_SAFETY_SOURCES); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_whenSafetyCenterIsEnabled_withNoSourceIds_sendsNoData() { + public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoSourceIds_doesNotSetData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent() @@ -118,11 +124,12 @@ public class SafetySourceBroadcastReceiverTest { new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - verify(mSafetyCenterManagerWrapper, never()).sendSafetyCenterUpdate(any(), any()); + verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData( + any(), any(), any(), any()); } @Test - public void sendSafetyData_withLockscreenSourceId_sendsLockscreenData() { + public void onReceive_onRefresh_setsRefreshEvent() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent() @@ -132,16 +139,34 @@ public class SafetySourceBroadcastReceiverTest { new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID }); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetyEvent.class); verify(mSafetyCenterManagerWrapper, times(1)) - .sendSafetyCenterUpdate(any(), captor.capture()); - SafetySourceData safetySourceData = captor.getValue(); + .setSafetySourceData(any(), any(), any(), captor.capture()); - assertThat(safetySourceData.getId()).isEqualTo(LockScreenSafetySource.SAFETY_SOURCE_ID); + assertThat(captor.getValue()).isEqualTo( + new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED).build()); } @Test - public void sendSafetyData_withBiometricsSourceId_sendsBiometricData() { + public void onReceive_onRefresh_withLockscreenSourceId_setsLockscreenData() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + Intent intent = + new Intent() + .setAction(ACTION_REFRESH_SAFETY_SOURCES) + .putExtra( + EXTRA_REFRESH_SAFETY_SOURCE_IDS, + new String[]{ LockScreenSafetySource.SAFETY_SOURCE_ID }); + + new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(mSafetyCenterManagerWrapper, times(1)) + .setSafetySourceData(any(), captor.capture(), any(), any()); + + assertThat(captor.getValue()).isEqualTo(LockScreenSafetySource.SAFETY_SOURCE_ID); + } + + @Test + public void onReceive_onRefresh_withBiometricsSourceId_setsBiometricData() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent() @@ -151,28 +176,42 @@ public class SafetySourceBroadcastReceiverTest { new String[]{ BiometricsSafetySource.SAFETY_SOURCE_ID }); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); verify(mSafetyCenterManagerWrapper, times(1)) - .sendSafetyCenterUpdate(any(), captor.capture()); - SafetySourceData safetySourceData = captor.getValue(); + .setSafetySourceData(any(), captor.capture(), any(), any()); - assertThat(safetySourceData.getId()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID); + assertThat(captor.getValue()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID); } @Test - public void sendSafetyData_onBootCompleted_sendsBiometricAndLockscreenData() { + public void onReceive_onBootCompleted_setsBootCompleteEvent() { when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); Intent intent = new Intent().setAction(Intent.ACTION_BOOT_COMPLETED); new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); - ArgumentCaptor captor = ArgumentCaptor.forClass(SafetySourceData.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(SafetyEvent.class); verify(mSafetyCenterManagerWrapper, times(2)) - .sendSafetyCenterUpdate(any(), captor.capture()); - List safetySourceDataList = captor.getAllValues(); + .setSafetySourceData(any(), any(), any(), captor.capture()); - assertThat(safetySourceDataList.stream().anyMatch( - data -> data.getId().equals(LockScreenSafetySource.SAFETY_SOURCE_ID))).isTrue(); - assertThat(safetySourceDataList.stream().anyMatch( - data -> data.getId().equals(BiometricsSafetySource.SAFETY_SOURCE_ID))).isTrue(); + SafetyEvent bootEvent = new SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build(); + assertThat(captor.getAllValues()) + .containsExactlyElementsIn(Arrays.asList(bootEvent, bootEvent)); + } + + @Test + public void onReceive_onBootCompleted_sendsBiometricAndLockscreenData() { + when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true); + Intent intent = new Intent().setAction(Intent.ACTION_BOOT_COMPLETED); + + new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(mSafetyCenterManagerWrapper, times(2)) + .setSafetySourceData(any(), captor.capture(), any(), any()); + List safetySourceIdList = captor.getAllValues(); + + assertThat(safetySourceIdList.stream().anyMatch( + id -> id.equals(LockScreenSafetySource.SAFETY_SOURCE_ID))).isTrue(); + assertThat(safetySourceIdList.stream().anyMatch( + id -> id.equals(BiometricsSafetySource.SAFETY_SOURCE_ID))).isTrue(); } } From 9d86fbc7a7ed31e792c4d39969c428e715b93fc0 Mon Sep 17 00:00:00 2001 From: Peter_Liang Date: Thu, 3 Mar 2022 15:09:53 +0800 Subject: [PATCH 04/13] Fix that symbol at top left corner mismatch with remaining options in vision settings. Replaced it with the visibility icon Bug: 222242580 Test: manual test Change-Id: I41682802678456d5fb93fb0e19d034e725e1da17 --- .../TextReadingPreferenceFragmentForSetupWizard.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java index c6793302dab..0ff960f23e5 100644 --- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java +++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java @@ -42,7 +42,7 @@ public class TextReadingPreferenceFragmentForSetupWizard extends TextReadingPref final GlifPreferenceLayout layout = (GlifPreferenceLayout) view; final String title = getContext().getString( R.string.accessibility_text_reading_options_title); - final Drawable icon = getContext().getDrawable(R.drawable.ic_font_download); + final Drawable icon = getContext().getDrawable(R.drawable.ic_accessibility_visibility); icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorPrimary)); AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title, /* description= */ null, icon); From 0dea418d575db2d7b141ac4a93094e5533d3b59c Mon Sep 17 00:00:00 2001 From: Amy Hsu Date: Wed, 9 Feb 2022 13:58:16 +0800 Subject: [PATCH 05/13] Add ScreenResolutionController to Settings app Settings for resolution switch Bug: b/199559703 Test: Check resolution switch UI in Settings app atest SettingsUnitTests:ScreenResolutionControllerTest atest SettingsUnitTests:ScreenResolutionFragmentTest Change-Id: I46d3be3b82ca512b8672efaa489df2cdaab26d6d Merged-In: I46d3be3b82ca512b8672efaa489df2cdaab26d6d --- res/drawable/screen_resolution_1080p.xml | 19 ++ res/drawable/screen_resolution_1440p.xml | 19 ++ res/values/config.xml | 12 + res/values/strings.xml | 14 ++ res/xml/display_settings.xml | 7 + res/xml/screen_resolution_settings.xml | 21 ++ .../display/ScreenResolutionController.java | 87 +++++++ .../display/ScreenResolutionFragment.java | 217 ++++++++++++++++++ .../ScreenResolutionControllerTest.java | 86 +++++++ .../display/ScreenResolutionFragmentTest.java | 90 ++++++++ 10 files changed, 572 insertions(+) create mode 100644 res/drawable/screen_resolution_1080p.xml create mode 100644 res/drawable/screen_resolution_1440p.xml create mode 100644 res/xml/screen_resolution_settings.xml create mode 100644 src/com/android/settings/display/ScreenResolutionController.java create mode 100644 src/com/android/settings/display/ScreenResolutionFragment.java create mode 100644 tests/unit/src/com/android/settings/display/ScreenResolutionControllerTest.java create mode 100644 tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java diff --git a/res/drawable/screen_resolution_1080p.xml b/res/drawable/screen_resolution_1080p.xml new file mode 100644 index 00000000000..a9d89ee9997 --- /dev/null +++ b/res/drawable/screen_resolution_1080p.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/res/drawable/screen_resolution_1440p.xml b/res/drawable/screen_resolution_1440p.xml new file mode 100644 index 00000000000..a9d89ee9997 --- /dev/null +++ b/res/drawable/screen_resolution_1440p.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/res/values/config.xml b/res/values/config.xml index bf78fd7fc98..415d1fa9afa 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -583,6 +583,18 @@ --> + + + @string/screen_resolution_option_high + @string/screen_resolution_option_highest + + + + + @string/screen_resolution_summary_high + @string/screen_resolution_summary_highest + + false diff --git a/res/values/strings.xml b/res/values/strings.xml index 9454b5ce789..c7b71b18e55 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2908,6 +2908,18 @@ On - Face-based Enable Face Detection + + + Screen resolution + + High resolution + + Highest resolution + + 1080p FHD+ + + 1440p QHD+ + Colors @@ -8265,6 +8277,8 @@ apps, default ignore optimizations, doze, app standby vibrant, RGB, sRGB, color, natural, standard + + FHD, QHD, resolution, 1080p, 1440p color, temperature, D65, D73, white, yellow, blue, warm, cool slide to unlock, password, pattern, PIN diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml index ba52a301666..03d073b2e67 100644 --- a/res/xml/display_settings.xml +++ b/res/xml/display_settings.xml @@ -117,6 +117,13 @@ settings:keywords="@string/keywords_auto_rotate" settings:controller="com.android.settings.display.DeviceStateAutoRotateOverviewController"/> + + + + + diff --git a/src/com/android/settings/display/ScreenResolutionController.java b/src/com/android/settings/display/ScreenResolutionController.java new file mode 100644 index 00000000000..dca12757e18 --- /dev/null +++ b/src/com/android/settings/display/ScreenResolutionController.java @@ -0,0 +1,87 @@ +/* + * 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.display; + +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.view.Display; + +import androidx.annotation.VisibleForTesting; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +/** Controller that switch the screen resolution. */ +public class ScreenResolutionController extends BasePreferenceController { + + static final int FHD_WIDTH = 1080; + static final int QHD_WIDTH = 1440; + + private Display mDisplay; + + public ScreenResolutionController(Context context, String key) { + super(context, key); + + mDisplay = + mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY); + } + + /** Check if the width is supported by the display. */ + private boolean isSupportedMode(int width) { + for (Display.Mode mode : getSupportedModes()) { + if (mode.getPhysicalWidth() == width) return true; + } + return false; + } + + /** Return true if the device contains two (or more) resolutions. */ + protected boolean checkSupportedResolutions() { + return isSupportedMode(FHD_WIDTH) && isSupportedMode(QHD_WIDTH); + } + + @Override + public int getAvailabilityStatus() { + return (checkSupportedResolutions()) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public CharSequence getSummary() { + String summary = null; + switch (getDisplayWidth()) { + case FHD_WIDTH: + summary = mContext.getString(R.string.screen_resolution_summary_high); + break; + case QHD_WIDTH: + summary = mContext.getString(R.string.screen_resolution_summary_highest); + break; + default: + summary = mContext.getString(R.string.screen_resolution_title); + } + + return summary; + } + + @VisibleForTesting + public int getDisplayWidth() { + return mDisplay.getMode().getPhysicalWidth(); + } + + @VisibleForTesting + public Display.Mode[] getSupportedModes() { + return mDisplay.getSupportedModes(); + } +} diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java new file mode 100644 index 00000000000..31957723752 --- /dev/null +++ b/src/com/android/settings/display/ScreenResolutionFragment.java @@ -0,0 +1,217 @@ +/* + * 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.display; + +import static com.android.settings.display.ScreenResolutionController.FHD_WIDTH; +import static com.android.settings.display.ScreenResolutionController.QHD_WIDTH; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Point; +import android.graphics.drawable.Drawable; +import android.hardware.display.DisplayManager; +import android.text.TextUtils; +import android.view.Display; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.widget.RadioButtonPickerFragment; +import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.widget.CandidateInfo; +import com.android.settingslib.widget.IllustrationPreference; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** Preference fragment used for switch screen resolution */ +@SearchIndexable +public class ScreenResolutionFragment extends RadioButtonPickerFragment { + + private static final String TAG = "ScreenResolution"; + + private Resources mResources; + private static final int FHD_INDEX = 0; + private static final int QHD_INDEX = 1; + private Display mDefaultDisplay; + private String[] mScreenResolutionOptions; + private Set mResolutions; + + private IllustrationPreference mImagePreference; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + + mDefaultDisplay = + context.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY); + mResources = context.getResources(); + mScreenResolutionOptions = + mResources.getStringArray(R.array.config_screen_resolution_options_strings); + mResolutions = getAllSupportedResolution(); + mImagePreference = new IllustrationPreference(context); + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.screen_resolution_settings; + } + + @Override + protected void addStaticPreferences(PreferenceScreen screen) { + updateIllustrationImage(mImagePreference); + screen.addPreference(mImagePreference); + } + + @Override + protected List getCandidates() { + final List candidates = new ArrayList<>(); + + for (int i = 0; i < mScreenResolutionOptions.length; i++) { + candidates.add( + new ScreenResolutionCandidateInfo( + mScreenResolutionOptions[i], + mScreenResolutionOptions[i], + true /* enabled */)); + } + + return candidates; + } + + /** Get all supported resolutions on the device. */ + private Set getAllSupportedResolution() { + Set resolutions = new HashSet<>(); + for (Display.Mode mode : mDefaultDisplay.getSupportedModes()) { + resolutions.add(new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight())); + } + + return resolutions; + } + + /** Get prefer display mode. */ + private Display.Mode getPreferMode(int width) { + for (Point resolution : mResolutions) { + if (resolution.x == width) { + return new Display.Mode( + resolution.x, resolution.y, getDisplayMode().getRefreshRate()); + } + } + + return getDisplayMode(); + } + + /** Get current display mode. */ + @VisibleForTesting + public Display.Mode getDisplayMode() { + return mDefaultDisplay.getMode(); + } + + /** Using display manager to set the display mode. */ + @VisibleForTesting + public void setDisplayMode(int width) { + mDefaultDisplay.setUserPreferredDisplayMode(getPreferMode(width)); + } + + /** Get the key corresponding to the resolution. */ + @VisibleForTesting + String getKeyForResolution(int width) { + return width == FHD_WIDTH + ? mScreenResolutionOptions[FHD_INDEX] + : width == QHD_WIDTH ? mScreenResolutionOptions[QHD_INDEX] : null; + } + + @Override + protected String getDefaultKey() { + int physicalWidth = getDisplayMode().getPhysicalWidth(); + + return getKeyForResolution(physicalWidth); + } + + @Override + protected boolean setDefaultKey(String key) { + if (mScreenResolutionOptions[FHD_INDEX].equals(key)) { + setDisplayMode(FHD_WIDTH); + + } else if (mScreenResolutionOptions[QHD_INDEX].equals(key)) { + setDisplayMode(QHD_WIDTH); + } + + updateIllustrationImage(mImagePreference); + return true; + } + + /** Update the resolution image according display mode. */ + private void updateIllustrationImage(IllustrationPreference preference) { + String key = getDefaultKey(); + + if (TextUtils.equals(mScreenResolutionOptions[FHD_INDEX], key)) { + preference.setLottieAnimationResId(R.drawable.screen_resolution_1080p); + } else if (TextUtils.equals(mScreenResolutionOptions[QHD_INDEX], key)) { + preference.setLottieAnimationResId(R.drawable.screen_resolution_1440p); + } + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.SCREEN_RESOLUTION; + } + + static class ScreenResolutionCandidateInfo extends CandidateInfo { + private final CharSequence mLabel; + private final String mKey; + + ScreenResolutionCandidateInfo(CharSequence label, String key, boolean enabled) { + super(enabled); + mLabel = label; + mKey = key; + } + + @Override + public CharSequence loadLabel() { + return mLabel; + } + + @Override + public Drawable loadIcon() { + return null; + } + + @Override + public String getKey() { + return mKey; + } + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.screen_resolution_settings) { + + boolean mIsFHDSupport = false; + boolean mIsQHDSupport = false; + + @Override + protected boolean isPageSearchEnabled(Context context) { + ScreenResolutionController mController = + new ScreenResolutionController(context, "fragment"); + return mController.checkSupportedResolutions(); + } + }; +} diff --git a/tests/unit/src/com/android/settings/display/ScreenResolutionControllerTest.java b/tests/unit/src/com/android/settings/display/ScreenResolutionControllerTest.java new file mode 100644 index 00000000000..a32904ecb35 --- /dev/null +++ b/tests/unit/src/com/android/settings/display/ScreenResolutionControllerTest.java @@ -0,0 +1,86 @@ +/* + * 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.display; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.view.Display; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.core.BasePreferenceController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class ScreenResolutionControllerTest { + + private static final int FHD_WIDTH = 1080; + private static final int QHD_WIDTH = 1440; + + private ScreenResolutionController mController; + + @Before + public void setUp() { + Context context = spy(ApplicationProvider.getApplicationContext()); + mController = spy(new ScreenResolutionController(context, "test")); + } + + @Test + public void getAvailabilityStatus_hasFhdAndQhdModes_returnAvailable() { + Display.Mode modeA = new Display.Mode(0, FHD_WIDTH, 0, 0); + Display.Mode modeB = new Display.Mode(0, QHD_WIDTH, 0, 0); + Display.Mode[] modes = {modeA, modeB}; + doReturn(modes).when(mController).getSupportedModes(); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void getAvailabilityStatus_hasOneMode_returnUnsupported() { + Display.Mode modeA = new Display.Mode(0, FHD_WIDTH, 0, 0); + Display.Mode[] modes = {modeA}; + doReturn(modes).when(mController).getSupportedModes(); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + public void updateState_screenResolutionFHD_shouldSetSummaryToFHD() { + int width = FHD_WIDTH; + doReturn(width).when(mController).getDisplayWidth(); + + assertThat(mController.getSummary().toString()).isEqualTo("1080p FHD+"); + } + + @Test + public void updateState_screenResolutionQHD_shouldSetSummaryToQHD() { + int width = QHD_WIDTH; + doReturn(width).when(mController).getDisplayWidth(); + + assertThat(mController.getSummary().toString()).isEqualTo("1440p QHD+"); + } +} diff --git a/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java b/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java new file mode 100644 index 00000000000..225a1d9a216 --- /dev/null +++ b/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java @@ -0,0 +1,90 @@ +/* + * 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.display; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.view.Display; + +import androidx.test.annotation.UiThreadTest; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class ScreenResolutionFragmentTest { + + private Context mContext; + private ScreenResolutionFragment mFragment; + + private static final int FHD_WIDTH = 1080; + private static final int QHD_WIDTH = 1440; + + @Before + @UiThreadTest + public void setup() { + mContext = spy(ApplicationProvider.getApplicationContext()); + mFragment = spy(new ScreenResolutionFragment()); + } + + @Test + @UiThreadTest + public void getDefaultKey_FHD() { + Display.Mode mode = new Display.Mode(0, FHD_WIDTH, 0, 0); + doReturn(mode).when(mFragment).getDisplayMode(); + + mFragment.onAttach(mContext); + assertThat(mFragment.getDefaultKey()).isEqualTo(mFragment.getKeyForResolution(FHD_WIDTH)); + } + + @Test + @UiThreadTest + public void getDefaultKey_QHD() { + Display.Mode mode = new Display.Mode(0, QHD_WIDTH, 0, 0); + doReturn(mode).when(mFragment).getDisplayMode(); + + mFragment.onAttach(mContext); + assertThat(mFragment.getDefaultKey()).isEqualTo(mFragment.getKeyForResolution(QHD_WIDTH)); + } + + @Test + @UiThreadTest + public void setDefaultKey_FHD() { + mFragment.onAttach(mContext); + + mFragment.setDefaultKey(mFragment.getKeyForResolution(FHD_WIDTH)); + + verify(mFragment).setDisplayMode(FHD_WIDTH); + } + + @Test + @UiThreadTest + public void setDefaultKey_QHD() { + mFragment.onAttach(mContext); + + mFragment.setDefaultKey(mFragment.getKeyForResolution(QHD_WIDTH)); + + verify(mFragment).setDisplayMode(QHD_WIDTH); + } +} From 0b948c827bdf5ded239473300117f057af57de24 Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Thu, 3 Mar 2022 14:00:12 +0800 Subject: [PATCH 06/13] [MEP] psim's logical slot index is 0 psim's logical slot index is 0, so changing the API and adding test cases. Bug: 221839363 Test: atest UiccSlotUtilTest Change-Id: I1588bd4a2f552a6b41844883b6ad50f1bfec95de (cherry picked from commit b162438b5df150def448eb56f96d56f1b66e8d16) --- .../settings/network/UiccSlotUtil.java | 85 +++++- .../settings/network/UiccSlotUtilTest.java | 276 +++++++++++++++++- 2 files changed, 334 insertions(+), 27 deletions(-) diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java index d28d93a8474..c4f495c904f 100644 --- a/src/com/android/settings/network/UiccSlotUtil.java +++ b/src/com/android/settings/network/UiccSlotUtil.java @@ -25,6 +25,7 @@ import android.telephony.UiccSlotInfo; import android.telephony.UiccSlotMapping; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.utils.ThreadUtils; import com.google.common.collect.ImmutableList; @@ -33,6 +34,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -126,7 +128,10 @@ public class UiccSlotUtil { performSwitchToSlot(telMgr, prepareUiccSlotMappings(uiccSlotMappings, - inactiveRemovableSlot, /*removable sim's port Id*/ 0, removedSubInfo, + /*slot is psim*/ true, + inactiveRemovableSlot, + /*removable sim's port Id*/ TelephonyManager.DEFAULT_PORT_INDEX, + removedSubInfo, telMgr.isMultiSimEnabled()), context); } @@ -159,7 +164,7 @@ public class UiccSlotUtil { } performSwitchToSlot(telMgr, - prepareUiccSlotMappings(uiccSlotMappings, + prepareUiccSlotMappings(uiccSlotMappings, /*slot is not psim*/ false, physicalSlotId, port, removedSubInfo, telMgr.isMultiSimEnabled()), context); } @@ -251,9 +256,27 @@ public class UiccSlotUtil { return INVALID_PHYSICAL_SLOT_ID; } - private static Collection prepareUiccSlotMappings( - Collection uiccSlotMappings, int physicalSlotId, int port, - SubscriptionInfo removedSubInfo, boolean isMultiSimEnabled) { + // Device | |Slot | + // Working| |Mapping| + // State |Type |Mode |Friendly name + //-------------------------------------------------------------------------- + // Single |SIM pSIM [RIL 0] |1 |pSIM active + // Single |SIM MEP Port #0 [RIL0] |2 |eSIM Port0 active + // Single |SIM MEP Port #1 [RIL0] |2.1 |eSIM Port1 active + // DSDS |pSIM [RIL 0] + MEP Port #0 [RIL 1] |3 |pSIM+Port0 + // DSDS |pSIM [RIL 0] + MEP Port #1 [RIL 1] |3.1 |pSIM+Port1 + // DSDS |MEP Port #0 [RIL 0] + MEP Port #1 [RIL1]|3.2 |Dual-Ports-A + // DSDS |MEP Port #1 [RIL 0] + MEP Port #0 [RIL1]|4 |Dual-Ports-B + // + // The rules are: + // 1. pSIM's logical slots always is [RIL 0]. + // 2. assign the new active port to the same stack that will be de-activated + // For example: mode#3->mode#4 + + @VisibleForTesting + static Collection prepareUiccSlotMappings( + Collection uiccSlotMappings, boolean isPsim, int physicalSlotId, + int port, SubscriptionInfo removedSubInfo, boolean isMultiSimEnabled) { Collection newUiccSlotMappings = new ArrayList<>(); if (!isMultiSimEnabled) { // In the 'SS mode', the port is 0. @@ -268,25 +291,59 @@ public class UiccSlotUtil { + "PhysicalSlotId%d-Port%d", removedSubInfo.getSubscriptionId(), removedSubInfo.getSimSlotIndex(), removedSubInfo.getPortIndex(), physicalSlotId, port)); + + int logicalSlotIndex = 0; + if (isPsim) { + // The target slot is psim + newUiccSlotMappings.add( + new UiccSlotMapping(port, physicalSlotId, logicalSlotIndex++)); + } + Collection tempUiccSlotMappings = + uiccSlotMappings.stream() + .sorted(Comparator.comparingInt(UiccSlotMapping::getLogicalSlotIndex)) + .collect(Collectors.toList()); + for (UiccSlotMapping uiccSlotMapping : tempUiccSlotMappings) { + if (isSubInfoMappingIntoUiccSlotMapping(uiccSlotMapping, removedSubInfo)) { + if (!isPsim) { + // Replace this uiccSlotMapping + newUiccSlotMappings.add(new UiccSlotMapping(port, physicalSlotId, + uiccSlotMapping.getLogicalSlotIndex())); + } + continue; + } + + // If the psim is inserted, then change the + // logicalSlotIndex for another uiccSlotMappings. + newUiccSlotMappings.add(isPsim + ? new UiccSlotMapping( + uiccSlotMapping.getPortIndex(), + uiccSlotMapping.getPhysicalSlotIndex(), + logicalSlotIndex++ + ) : uiccSlotMapping); + } + } else { + // For no inserted psim case in DSDS+MEP, there is only one esim in device and + // then user inserts another esim in DSDS+MEP. + // If the target is esim, then replace the psim. + Log.i(TAG, "The removedSubInfo is null"); newUiccSlotMappings = uiccSlotMappings.stream().map(uiccSlotMapping -> { - if (uiccSlotMapping.getLogicalSlotIndex() - == removedSubInfo.getSimSlotIndex() - && uiccSlotMapping.getPortIndex() - == removedSubInfo.getPortIndex()) { + if (!isPsim && uiccSlotMapping.getPhysicalSlotIndex() != physicalSlotId) { return new UiccSlotMapping(port, physicalSlotId, uiccSlotMapping.getLogicalSlotIndex()); } return uiccSlotMapping; }).collect(Collectors.toList()); - } else { - // DSDS+no MEP - // The removable slot should be in UiccSlotMapping. - newUiccSlotMappings = uiccSlotMappings; - Log.i(TAG, "The removedSubInfo is null"); } Log.i(TAG, "The SimSlotMapping: " + newUiccSlotMappings); return newUiccSlotMappings; } + + private static boolean isSubInfoMappingIntoUiccSlotMapping(UiccSlotMapping uiccSlotMapping, + SubscriptionInfo subscriptionInfo) { + return uiccSlotMapping != null + && uiccSlotMapping.getLogicalSlotIndex() == subscriptionInfo.getSimSlotIndex() + && uiccSlotMapping.getPortIndex() == subscriptionInfo.getPortIndex(); + } } diff --git a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java index 1a6879dea0b..8a0a4b0d3b9 100644 --- a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java +++ b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java @@ -24,9 +24,11 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; +import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.UiccPortInfo; import android.telephony.UiccSlotInfo; +import android.telephony.UiccSlotMapping; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -39,8 +41,12 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.Iterator; +import java.util.List; @RunWith(AndroidJUnit4.class) public class UiccSlotUtilTest { @@ -48,6 +54,9 @@ public class UiccSlotUtilTest { @Mock private TelephonyManager mTelephonyManager; + private static final int ESIM_PHYSICAL_SLOT = 0; + private static final int PSIM_PHYSICAL_SLOT = 1; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -58,7 +67,7 @@ public class UiccSlotUtilTest { @Test public void getSlotInfos_oneSimSlotDevice_returnTheCorrectSlotInfoList() { - when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(oneSimSlotDevice_ActivePsim()); + when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(oneSimSlotDeviceActivePsim()); ImmutableList testUiccSlotInfos = UiccSlotUtil.getSlotInfos(mTelephonyManager); @@ -68,7 +77,7 @@ public class UiccSlotUtilTest { @Test public void getSlotInfos_twoSimSlotsDevice_returnTheCorrectSlotInfoList() { when(mTelephonyManager.getUiccSlotsInfo()).thenReturn( - twoSimSlotsDevice_ActivePsimActiveEsim()); + twoSimSlotsDeviceActivePsimActiveEsim()); ImmutableList testUiccSlotInfos = UiccSlotUtil.getSlotInfos(mTelephonyManager); @@ -78,7 +87,7 @@ public class UiccSlotUtilTest { @Test public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot0_returnTheCorrectEsimSlot() { when(mTelephonyManager.getUiccSlotsInfo()).thenReturn( - twoSimSlotsDevice_ActiveEsimActivePsim()); + twoSimSlotsDeviceActiveEsimActivePsim()); int testSlot = UiccSlotUtil.getEsimSlotId(mContext); assertThat(testSlot).isEqualTo(0); @@ -87,7 +96,7 @@ public class UiccSlotUtilTest { @Test public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot1_returnTheCorrectEsimSlot() { when(mTelephonyManager.getUiccSlotsInfo()).thenReturn( - twoSimSlotsDevice_ActivePsimActiveEsim()); + twoSimSlotsDeviceActivePsimActiveEsim()); int testSlot = UiccSlotUtil.getEsimSlotId(mContext); assertThat(testSlot).isEqualTo(1); @@ -96,12 +105,253 @@ public class UiccSlotUtilTest { @Test public void getEsimSlotId_noEimSlotDevice_returnTheCorrectEsimSlot() { when(mTelephonyManager.getUiccSlotsInfo()).thenReturn( - oneSimSlotDevice_ActivePsim()); + oneSimSlotDeviceActivePsim()); int testSlot = UiccSlotUtil.getEsimSlotId(mContext); assertThat(testSlot).isEqualTo(-1); } + @Test + public void prepareUiccSlotMappings_fromPsimActiveToEsimPort0Active_esimPort0Active() { + Collection uiccSlotMappings = createUiccSlotMappingSsModePsimActive(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingSsModeEsimPort0Active(); + + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, null, false); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromEsimPort0ActiveToPsimActive_psimActive() { + Collection uiccSlotMappings = + createUiccSlotMappingSsModeEsimPort0Active(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingSsModePsimActive(); + + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, null, false); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromPsimAndPort0ToPsimAndPort1_psimAndPort1() { + Collection uiccSlotMappings = createUiccSlotMappingPsimAndPort0(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingPsimAndPort1(); + SubscriptionInfo subInfo = createSubscriptionInfo(1, 0); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromPsimAndPort1ToPsimAndPort0_psimAndPort0() { + Collection uiccSlotMappings = createUiccSlotMappingPsimAndPort1(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingPsimAndPort0(); + + SubscriptionInfo subInfo = createSubscriptionInfo(1, 1); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromPsimAndPort0ToDualPortsB_dualPortsB() { + Collection uiccSlotMappings = createUiccSlotMappingPsimAndPort0(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingDualPortsB(); + + SubscriptionInfo subInfo = createSubscriptionInfo(0, 0); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromPsimAndPort1ToDualPortsA_dualPortsA() { + Collection uiccSlotMappings = createUiccSlotMappingPsimAndPort1(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingDualPortsA(); + + SubscriptionInfo subInfo = createSubscriptionInfo(0, 0); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_noPsimAndFromPsimAndPort0ToDualPortsB_dualPortsB() { + Collection uiccSlotMappings = createUiccSlotMappingPsimAndPort0(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingDualPortsB(); + + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, null, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_noPsimAndFromPsimAndPort1ToDualPortsA_dualPortsA() { + Collection uiccSlotMappings = createUiccSlotMappingPsimAndPort1(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingDualPortsA(); + + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, null, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromDualPortsAToPsimAndPort1_psimAndPort1() { + Collection uiccSlotMappings = createUiccSlotMappingDualPortsA(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingPsimAndPort1(); + + SubscriptionInfo subInfo = createSubscriptionInfo(0, 0); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromDualPortsAToPsimAndPort0_psimAndPort0() { + Collection uiccSlotMappings = createUiccSlotMappingDualPortsA(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingPsimAndPort0(); + + SubscriptionInfo subInfo = createSubscriptionInfo(1, 1); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromDualPortsBToPsimAndPort1_psimAndPort1() { + Collection uiccSlotMappings = createUiccSlotMappingDualPortsB(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingPsimAndPort1(); + + SubscriptionInfo subInfo = createSubscriptionInfo(1, 0); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + @Test + public void prepareUiccSlotMappings_fromDualPortsBToPsimAndPort0_psimAndPort0() { + Collection uiccSlotMappings = createUiccSlotMappingDualPortsB(); + Collection verifyUiccSlotMappings = + createUiccSlotMappingPsimAndPort0(); + + SubscriptionInfo subInfo = createSubscriptionInfo(0, 1); + Collection testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings( + uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, subInfo, true); + + compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings); + } + + private SubscriptionInfo createSubscriptionInfo(int logicalSlotIndex, int portIndex) { + return new SubscriptionInfo( + 0, "", logicalSlotIndex, "", "", 0, 0, "", 0, null, "", "", "", + true /* isEmbedded */, + null, "", 25, + false, null, false, 0, 0, 0, null, null, true, portIndex); + } + + private void compareTwoUiccSlotMappings(Collection testUiccSlotMappings, + Collection verifyUiccSlotMappings) { + assertThat(testUiccSlotMappings.size()).isEqualTo(verifyUiccSlotMappings.size()); + Iterator testIterator = testUiccSlotMappings.iterator(); + Iterator verifyIterator = verifyUiccSlotMappings.iterator(); + while (testIterator.hasNext()) { + UiccSlotMapping testUiccSlotMapping = testIterator.next(); + UiccSlotMapping verifyUiccSlotMapping = verifyIterator.next(); + assertThat(testUiccSlotMapping.getLogicalSlotIndex()).isEqualTo( + verifyUiccSlotMapping.getLogicalSlotIndex()); + assertThat(testUiccSlotMapping.getPortIndex()).isEqualTo( + verifyUiccSlotMapping.getPortIndex()); + assertThat(testUiccSlotMapping.getPhysicalSlotIndex()).isEqualTo( + verifyUiccSlotMapping.getPhysicalSlotIndex()); + } + } + + // Device | |Slot | + // Working| |Mapping| + // State |Type |Mode |Friendly name + //-------------------------------------------------------------------------- + // Single |SIM pSIM [RIL 0] |1 |pSIM active + // Single |SIM MEP Port #0 [RIL0] |2 |eSIM Port0 active + // Single |SIM MEP Port #1 [RIL0] |2.1 |eSIM Port1 active + // DSDS |pSIM [RIL 0] + MEP Port #0 [RIL 1] |3 |pSIM+Port0 + // DSDS |pSIM [RIL 0] + MEP Port #1 [RIL 1] |3.1 |pSIM+Port1 + // DSDS |MEP Port #0 [RIL 0] + MEP Port #1 [RIL1]|3.2 |Dual-Ports-A + // DSDS |MEP Port #1 [RIL 0] + MEP Port #0 [RIL1]|4 |Dual-Ports-B + private List createUiccSlotMappingSsModePsimActive() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0)); + + return slotMap; + } + + private List createUiccSlotMappingSsModeEsimPort0Active() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 0)); + + return slotMap; + } + + private List createUiccSlotMappingSsModeEsimPort1Active() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 0)); + + return slotMap; + } + + private List createUiccSlotMappingPsimAndPort0() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0)); + slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 1)); + + return slotMap; + } + + private List createUiccSlotMappingPsimAndPort1() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0)); + slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 1)); + + return slotMap; + } + + private List createUiccSlotMappingDualPortsA() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 0)); + slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 1)); + + return slotMap; + } + + private List createUiccSlotMappingDualPortsB() { + List slotMap = new ArrayList<>(); + slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 0)); + slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 1)); + + return slotMap; + } + /** * The "oneSimSlotDevice" has below cases * 1) The device is one psim slot and no esim slot @@ -112,27 +362,27 @@ public class UiccSlotUtilTest { * 2) The device is two psim slots */ - private UiccSlotInfo[] oneSimSlotDevice_ActivePsim() { + private UiccSlotInfo[] oneSimSlotDeviceActivePsim() { return new UiccSlotInfo[]{createUiccSlotInfo(false, true, 0, true)}; } - private UiccSlotInfo[] oneSimSlotDevice_ActiveEsim() { + private UiccSlotInfo[] oneSimSlotDeviceActiveEsim() { return new UiccSlotInfo[]{createUiccSlotInfo(true, false, 1, true)}; } - private UiccSlotInfo[] twoSimSlotsDevice_ActivePsimActiveEsim() { + private UiccSlotInfo[] twoSimSlotsDeviceActivePsimActiveEsim() { return new UiccSlotInfo[]{ createUiccSlotInfo(false, true, 0, true), createUiccSlotInfo(true, false, 1, true)}; } - private UiccSlotInfo[] twoSimSlotsDevice_ActiveEsimActivePsim() { + private UiccSlotInfo[] twoSimSlotsDeviceActiveEsimActivePsim() { return new UiccSlotInfo[]{ createUiccSlotInfo(true, false, 0, true), createUiccSlotInfo(false, true, 1, true)}; } - private UiccSlotInfo[] twoSimSlotsDevice_twoActiveEsims() { + private UiccSlotInfo[] twoSimSlotsDeviceTwoActiveEsims() { // device supports MEP, so device can enable two esims. // If device has psim slot, the UiccSlotInfo of psim always be in UiccSlotInfo[]. return new UiccSlotInfo[]{ @@ -140,19 +390,19 @@ public class UiccSlotUtilTest { createUiccSlotInfoForEsimMep(0, true, 1, true)}; } - private UiccSlotInfo[] twoSimSlotsDevice_ActivePsimInactiveEsim() { + private UiccSlotInfo[] twoSimSlotsDeviceActivePsimInactiveEsim() { return new UiccSlotInfo[]{ createUiccSlotInfo(false, true, 0, true), createUiccSlotInfo(true, false, -1, false)}; } - private UiccSlotInfo[] twoSimSlotsDevice_InactivePsimActiveEsim() { + private UiccSlotInfo[] twoSimSlotsDeviceInactivePsimActiveEsim() { return new UiccSlotInfo[]{ createUiccSlotInfo(false, true, 0, false), createUiccSlotInfo(true, false, 1, true)}; } - private UiccSlotInfo[] twoSimSlotsDevice_NoInsertPsimActiveEsim() { + private UiccSlotInfo[] twoSimSlotsDeviceNoInsertPsimActiveEsim() { return new UiccSlotInfo[]{ createUiccSlotInfo(false, true, -1, false), createUiccSlotInfo(true, false, 1, true)}; From 3fc4642ab4cb46362a8e6374f46ca8d1e2aa3b10 Mon Sep 17 00:00:00 2001 From: Yasin Kilicdere Date: Thu, 10 Feb 2022 23:11:31 +0000 Subject: [PATCH 07/13] Fix Guest string was not translated in UMS.userWithName() This CL reverts the changes made in ag/14282598 since the issue is solved from the source and removes 'String name' parameter from UM.createGuest() calls. Bug: 185309160 Test: atest UserDetailsSettingsTest Change-Id: I92acad938d79e21b45af99cc76ff411022b61f1b Merged-In: I92acad938d79e21b45af99cc76ff411022b61f1b (cherry picked from commit ae871ba823659e81b0839f5ea2618d172bf4d846) --- .../settings/users/UserDetailsSettings.java | 2 +- .../android/settings/users/UserSettings.java | 25 +++++-------------- .../settings/users/UserSettingsTest.java | 4 +-- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java index c3657be1343..a3c8e696e26 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -256,7 +256,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment mSwitchUserPref.setTitle( context.getString(com.android.settingslib.R.string.user_switch_to_user, - UserSettings.getUserName(context, mUserInfo))); + mUserInfo.name)); if (mUserCaps.mDisallowSwitchUser) { mSwitchUserPref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context)); diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index 9878b4470dc..64a65a4b405 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -16,7 +16,6 @@ package com.android.settings.users; -import android.annotation.NonNull; import android.app.Activity; import android.app.ActivityManager; import android.app.Dialog; @@ -562,11 +561,10 @@ public class UserSettings extends SettingsPreferenceFragment extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userInfo.id); extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser); - final Context context = getContext(); - SubSettingLauncher launcher = new SubSettingLauncher(context) + SubSettingLauncher launcher = new SubSettingLauncher(getContext()) .setDestination(UserDetailsSettings.class.getName()) .setArguments(extras) - .setTitleText(getUserName(context, userInfo)) + .setTitleText(userInfo.name) .setSourceMetricsCategory(getMetricsCategory()); if (mGuestUserAutoCreated && userInfo.isGuest()) { launcher.setResultListener(this, REQUEST_EDIT_GUEST); @@ -956,8 +954,7 @@ public class UserSettings extends SettingsPreferenceFragment // "Resetting guest..." mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST); mExecutor.execute(() -> { - UserInfo guest = mUserManager.createGuest( - getContext(), getString(com.android.settingslib.R.string.user_guest)); + UserInfo guest = mUserManager.createGuest(getContext()); mGuestCreationScheduled.set(false); if (guest == null) { Log.e(TAG, "Unable to automatically recreate guest user"); @@ -996,9 +993,8 @@ public class UserSettings extends SettingsPreferenceFragment if (user.id == UserHandle.myUserId()) { pref = mMePreference; } else { - final Context prefContext = getPrefContext(); - pref = new UserPreference(prefContext, null, user.id); - pref.setTitle(getUserName(prefContext, user)); + pref = new UserPreference(getPrefContext(), null, user.id); + pref.setTitle(user.name); userPreferences.add(pref); pref.setOnPreferenceClickListener(this); pref.setEnabled(canOpenUserDetails); @@ -1228,14 +1224,6 @@ public class UserSettings extends SettingsPreferenceFragment } } - /** Returns the user's name, or the appropriate string in the case of a Guest. */ - public static String getUserName(Context context, @NonNull UserInfo userInfo) { - if (userInfo.isGuest()) { - return context.getString(R.string.user_guest); - } - return userInfo.name; - } - @Override public boolean onPreferenceClick(Preference pref) { if (pref == mMePreference) { @@ -1272,8 +1260,7 @@ public class UserSettings extends SettingsPreferenceFragment mAddGuest.setEnabled(false); // prevent multiple tap issue mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD); Trace.beginSection("UserSettings.addGuest"); - UserInfo guest = mUserManager.createGuest( - getContext(), getString(com.android.settingslib.R.string.user_guest)); + UserInfo guest = mUserManager.createGuest(getContext()); Trace.endSection(); if (guest == null) { Toast.makeText(getContext(), diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java index 0fa3d5c671a..1376712d75f 100644 --- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java +++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java @@ -662,12 +662,12 @@ public class UserSettingsTest { public void onPreferenceClick_addGuestClicked_createGuestAndOpenDetails() { UserInfo createdGuest = getGuest(false); removeFlag(createdGuest, UserInfo.FLAG_INITIALIZED); - doReturn(createdGuest).when(mUserManager).createGuest(mActivity, "Guest"); + doReturn(createdGuest).when(mUserManager).createGuest(mActivity); doReturn(mActivity).when(mFragment).getContext(); mFragment.onPreferenceClick(mAddGuestPreference); - verify(mUserManager).createGuest(mActivity, "Guest"); + verify(mUserManager).createGuest(mActivity); Intent startedIntent = shadowOf(mActivity).getNextStartedActivity(); ShadowIntent shadowIntent = shadowOf(startedIntent); assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class); From ea34e9ab42d0654310c07f26fe324f922493a60e Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Wed, 23 Feb 2022 19:05:53 +0000 Subject: [PATCH 08/13] Home Controls: Update subtitle for setting. Change subtitle for device controls setting to be less generic. Need to address merge conflicts here. Bug: 216110204 Test: Manual Change-Id: I848d052461f412c51109c39b811252c64b19440a (cherry picked from commit d0b77425a39676036a232c7b58294717062074f0) --- res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 87272b5d569..d8a55f384b7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13360,7 +13360,7 @@ Show device controls - Access controls when locked + Show controls for external devices from the lock screen Control from locked device From cd517a654aa7d34bf0570092381b313930f0264b Mon Sep 17 00:00:00 2001 From: Edgar Wang Date: Wed, 2 Mar 2022 12:55:34 +0000 Subject: [PATCH 09/13] Use android.app.AlertDialog in SetupChooseLockGeneric androidx.appcompat.app.AlertDialog will cause postiveButton and negativeButton become too close when the texts are longer. Bug: 216442969 Change-Id: I39e84c1007c817399902034e853b2aeee1343adc Test: visual verify --- src/com/android/settings/password/SetupSkipDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/password/SetupSkipDialog.java b/src/com/android/settings/password/SetupSkipDialog.java index a0fe9617f3c..2dac3d655dd 100644 --- a/src/com/android/settings/password/SetupSkipDialog.java +++ b/src/com/android/settings/password/SetupSkipDialog.java @@ -17,6 +17,7 @@ package com.android.settings.password; import android.app.Activity; +import android.app.AlertDialog; import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.DialogInterface; @@ -26,7 +27,6 @@ import android.view.inputmethod.InputMethodManager; import androidx.annotation.NonNull; import androidx.annotation.StringRes; -import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentManager; import com.android.settings.R; From 372bbdcf9ccfd8e75a2b7d7f6f89d6d0114baef7 Mon Sep 17 00:00:00 2001 From: Amy Hsu Date: Fri, 18 Feb 2022 21:06:12 +0800 Subject: [PATCH 10/13] Add summary and footer message for the ScreenResolutionFragment. Bug: b/199559703 Test: Check resolution switch UI in Settings app atest SettingsUnitTests:ScreenResolutionControllerTest atest SettingsUnitTests:ScreenResolutionFragmentTest Change-Id: Iee1e74d3d4de81500b2abe62bc7e9bd69f55452c (cherry picked from commit d633cd6b32915a36d66d6f85abb0656cd3015f8f) Merged-In: Iee1e74d3d4de81500b2abe62bc7e9bd69f55452c --- res/values/strings.xml | 2 + .../display/ScreenResolutionFragment.java | 43 ++++++++++++++++--- .../display/ScreenResolutionFragmentTest.java | 18 ++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 02bc5dd917d..1d69657ce36 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2919,6 +2919,8 @@ 1080p FHD+ 1440p QHD+ + + Switching your resolution might cause some apps currently running to close. Colors diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java index 31957723752..3b08ae7f00b 100644 --- a/src/com/android/settings/display/ScreenResolutionFragment.java +++ b/src/com/android/settings/display/ScreenResolutionFragment.java @@ -36,7 +36,9 @@ import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.widget.CandidateInfo; +import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.IllustrationPreference; +import com.android.settingslib.widget.SelectorWithWidgetPreference; import java.util.ArrayList; import java.util.HashSet; @@ -55,6 +57,7 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { private Display mDefaultDisplay; private String[] mScreenResolutionOptions; private Set mResolutions; + private String[] mScreenResolutionSummaries; private IllustrationPreference mImagePreference; @@ -67,6 +70,8 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { mResources = context.getResources(); mScreenResolutionOptions = mResources.getStringArray(R.array.config_screen_resolution_options_strings); + mScreenResolutionSummaries = + mResources.getStringArray(R.array.config_screen_resolution_summaries_strings); mResolutions = getAllSupportedResolution(); mImagePreference = new IllustrationPreference(context); } @@ -80,6 +85,24 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { protected void addStaticPreferences(PreferenceScreen screen) { updateIllustrationImage(mImagePreference); screen.addPreference(mImagePreference); + + final FooterPreference footerPreference = new FooterPreference(screen.getContext()); + footerPreference.setTitle(R.string.screen_resolution_footer); + footerPreference.setSelectable(false); + footerPreference.setLayoutResource(R.layout.preference_footer); + screen.addPreference(footerPreference); + } + + @Override + public void bindPreferenceExtra( + SelectorWithWidgetPreference pref, + String key, + CandidateInfo info, + String defaultKey, + String systemDefaultKey) { + final ScreenResolutionCandidateInfo candidateInfo = (ScreenResolutionCandidateInfo) info; + final CharSequence summary = candidateInfo.loadSummary(); + if (summary != null) pref.setSummary(summary); } @Override @@ -90,6 +113,7 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { candidates.add( new ScreenResolutionCandidateInfo( mScreenResolutionOptions[i], + mScreenResolutionSummaries[i], mScreenResolutionOptions[i], true /* enabled */)); } @@ -134,9 +158,9 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { /** Get the key corresponding to the resolution. */ @VisibleForTesting String getKeyForResolution(int width) { - return width == FHD_WIDTH - ? mScreenResolutionOptions[FHD_INDEX] - : width == QHD_WIDTH ? mScreenResolutionOptions[QHD_INDEX] : null; + return width == FHD_WIDTH ? mScreenResolutionOptions[FHD_INDEX] + : width == QHD_WIDTH ? mScreenResolutionOptions[QHD_INDEX] + : null; } @Override @@ -175,13 +199,17 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { return SettingsEnums.SCREEN_RESOLUTION; } - static class ScreenResolutionCandidateInfo extends CandidateInfo { + /** This is an extension of the CandidateInfo class, which adds summary information. */ + public static class ScreenResolutionCandidateInfo extends CandidateInfo { private final CharSequence mLabel; + private final CharSequence mSummary; private final String mKey; - ScreenResolutionCandidateInfo(CharSequence label, String key, boolean enabled) { + ScreenResolutionCandidateInfo( + CharSequence label, CharSequence summary, String key, boolean enabled) { super(enabled); mLabel = label; + mSummary = summary; mKey = key; } @@ -190,6 +218,11 @@ public class ScreenResolutionFragment extends RadioButtonPickerFragment { return mLabel; } + /** It is the summary for radio options. */ + public CharSequence loadSummary() { + return mSummary; + } + @Override public Drawable loadIcon() { return null; diff --git a/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java b/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java index 225a1d9a216..b7d37df0d19 100644 --- a/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java +++ b/tests/unit/src/com/android/settings/display/ScreenResolutionFragmentTest.java @@ -18,6 +18,7 @@ package com.android.settings.display; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -28,6 +29,8 @@ import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.android.settingslib.widget.SelectorWithWidgetPreference; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -87,4 +90,19 @@ public class ScreenResolutionFragmentTest { verify(mFragment).setDisplayMode(QHD_WIDTH); } + + @Test + @UiThreadTest + public void bindPreferenceExtra_setSummary() { + mFragment.onAttach(mContext); + SelectorWithWidgetPreference preference = new SelectorWithWidgetPreference(mContext); + ScreenResolutionFragment.ScreenResolutionCandidateInfo candidates = + mock(ScreenResolutionFragment.ScreenResolutionCandidateInfo.class); + CharSequence summary = "test summary"; + doReturn(summary).when(candidates).loadSummary(); + + mFragment.bindPreferenceExtra(preference, "com.example.test", candidates, null, null); + + assertThat(preference.getSummary().toString().contentEquals(summary)).isTrue(); + } } From 705276771a3e623a4e59a69329af74f1182698e9 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Fri, 4 Mar 2022 10:39:30 +0800 Subject: [PATCH 11/13] Remove Flashlight from search results while the hardware is unavailable Test: manual Fix: 222599976 Change-Id: I353b872f9e56f5e00026e95933125c345636bbd2 --- .../flashlight/FlashlightHandleActivity.java | 18 ++++++++++++++++-- .../settings/flashlight/FlashlightSlice.java | 2 -- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/flashlight/FlashlightHandleActivity.java b/src/com/android/settings/flashlight/FlashlightHandleActivity.java index 589496540bc..0847d49d70e 100644 --- a/src/com/android/settings/flashlight/FlashlightHandleActivity.java +++ b/src/com/android/settings/flashlight/FlashlightHandleActivity.java @@ -21,12 +21,13 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.provider.Settings; +import android.util.Log; import com.android.settings.R; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.Indexable; -import com.android.settingslib.search.SearchIndexableRaw; import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.search.SearchIndexableRaw; import java.util.ArrayList; import java.util.List; @@ -39,6 +40,9 @@ public class FlashlightHandleActivity extends Activity implements Indexable { public static final String EXTRA_FALLBACK_TO_HOMEPAGE = "fallback_to_homepage"; + private static final String TAG = "FlashlightActivity"; + private static final String DATA_KEY = "flashlight"; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -69,10 +73,20 @@ public class FlashlightHandleActivity extends Activity implements Indexable { data.intentTargetPackage = context.getPackageName(); data.intentTargetClass = FlashlightHandleActivity.class.getName(); data.intentAction = Intent.ACTION_MAIN; - data.key = "flashlight"; + data.key = DATA_KEY; result.add(data); return result; } + + @Override + public List getNonIndexableKeys(Context context) { + List keys = super.getNonIndexableKeys(context); + if (!FlashlightSlice.isFlashlightAvailable(context)) { + Log.i(TAG, "Flashlight is unavailable"); + keys.add(DATA_KEY); + } + return keys; + } }; } diff --git a/src/com/android/settings/flashlight/FlashlightSlice.java b/src/com/android/settings/flashlight/FlashlightSlice.java index eaf059aa673..5feaf4f7f42 100644 --- a/src/com/android/settings/flashlight/FlashlightSlice.java +++ b/src/com/android/settings/flashlight/FlashlightSlice.java @@ -39,7 +39,6 @@ import androidx.slice.builders.ListBuilder; import androidx.slice.builders.ListBuilder.RowBuilder; import androidx.slice.builders.SliceAction; -import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.slices.CustomSliceRegistry; @@ -138,7 +137,6 @@ public class FlashlightSlice implements CustomSliceable { return null; } - @VisibleForTesting static boolean isFlashlightAvailable(Context context) { int defaultAvailability = 0; try { From 3aff4b1513f1d1e89d96ef27a25783dc5b81be03 Mon Sep 17 00:00:00 2001 From: cnchen Date: Fri, 4 Mar 2022 11:58:26 +0800 Subject: [PATCH 12/13] Add dynamic color support (before)https://hsv.googleplex.com/6220707954425856 (after)https://hsv.googleplex.com/6270261408038912 Bug: 209889556 Test: see the hsv above Change-Id: Ifee0392c189dbe7210ba2561355e2c275e7cb7fe --- .../wifi/dpp/WifiDppBaseActivity.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java b/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java index f55960be5e0..938d224c5a1 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java @@ -26,6 +26,8 @@ import com.android.settings.R; import com.android.settings.SetupWizardUtils; import com.android.settings.core.InstrumentedActivity; +import com.google.android.setupdesign.util.ThemeHelper; + public abstract class WifiDppBaseActivity extends InstrumentedActivity { protected FragmentManager mFragmentManager; @@ -35,6 +37,8 @@ public abstract class WifiDppBaseActivity extends InstrumentedActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + applyTheme(); + setContentView(R.layout.wifi_dpp_activity); mFragmentManager = getSupportFragmentManager(); @@ -45,8 +49,18 @@ public abstract class WifiDppBaseActivity extends InstrumentedActivity { @Override protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) { - final int new_resid = SetupWizardUtils.getTheme(this, getIntent()); - theme.applyStyle(R.style.SetupWizardPartnerResource, /* force */ true); - super.onApplyThemeResource(theme, new_resid, first); + theme.applyStyle(R.style.SetupWizardPartnerResource, true); + super.onApplyThemeResource(theme, resid, first); + } + + private void applyTheme() { + if (ThemeHelper.trySetDynamicColor(this)) { + final int appliedTheme = ThemeHelper.isSetupWizardDayNightEnabled(this) + ? R.style.SudDynamicColorThemeSettings_SetupWizard_DayNight + : R.style.SudDynamicColorThemeSettings_SetupWizard; + setTheme(appliedTheme); + } else { + setTheme(SetupWizardUtils.getTheme(this, getIntent())); + } } } From bb0a8f2523ce760b1461825b0681a3ba125225f8 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Fri, 4 Mar 2022 06:09:33 +0000 Subject: [PATCH 13/13] Remove InterfaceState and Role @IntDef from TetheredSettings. @InterfaceState and @Role won't be exposed as module-lib APIs from EthernetManager after migration, which are not visible for Settings code, remove them as well. Bug: 210586283 Test: m Settings Change-Id: I49f0e8401681e66d6f5853c8eb3205fcef803c25 --- src/com/android/settings/TetherSettings.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index ae2416824bd..da21729d72e 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -34,8 +34,6 @@ import android.content.IntentFilter; import android.hardware.usb.UsbManager; import android.net.ConnectivityManager; import android.net.EthernetManager; -import android.net.EthernetManager.InterfaceState; -import android.net.EthernetManager.Role; import android.net.IpConfiguration; import android.net.TetheringManager; import android.net.wifi.WifiManager; @@ -650,8 +648,8 @@ public class TetherSettings extends RestrictedSettingsFragment } private final class EthernetListener implements EthernetManager.InterfaceStateListener { - public void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state, - @Role int role, @NonNull IpConfiguration configuration) { + public void onInterfaceStateChanged(@NonNull String iface, int state, int role, + @NonNull IpConfiguration configuration) { if (state == EthernetManager.STATE_LINK_UP) { mAvailableInterfaces.add(iface); } else {