From 55b7b0613d31dd632ba7d3dec68d958d4b77c0f2 Mon Sep 17 00:00:00 2001 From: Yuri Ufimtsev Date: Tue, 4 Feb 2025 14:57:33 +0000 Subject: [PATCH] Allow the LockPatterUtils to be null In some tests it could inconsistently become a null, crashing with NPE, for the reason I can't understand (maybe there is a race condition somewhere between mocking and accessing the LockPatterUtils in such tests) Let's accept it gracefully Test: atest SettingsUnitTests Bug: 382637173 Flag: EXEMPT bugfix Change-Id: I35d5faa1a29307fc780207a816680a32b2796bc0 --- .../safetycenter/LockScreenSafetySource.java | 9 ++++- .../ScreenLockPreferenceDetailsUtils.java | 9 ++++- .../ScreenLockPreferenceDetailsUtilsTest.java | 37 ++++++++++++++++++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/safetycenter/LockScreenSafetySource.java b/src/com/android/settings/safetycenter/LockScreenSafetySource.java index 14ad268c3cf..00a4c676a80 100644 --- a/src/com/android/settings/safetycenter/LockScreenSafetySource.java +++ b/src/com/android/settings/safetycenter/LockScreenSafetySource.java @@ -95,8 +95,7 @@ public final class LockScreenSafetySource { new SafetySourceStatus.Builder( context.getString(R.string.unlock_set_unlock_launch_picker_title), lockScreenAllowedByAdmin - ? screenLockPreferenceDetailsUtils.getSummary( - UserHandle.myUserId()) + ? getScreenLockSummary(screenLockPreferenceDetailsUtils) : context.getString(R.string.disabled_by_policy_title), severityLevel) .setPendingIntent(lockScreenAllowedByAdmin ? pendingIntent : null) @@ -114,6 +113,12 @@ public final class LockScreenSafetySource { .setSafetySourceData(context, SAFETY_SOURCE_ID, safetySourceData, safetyEvent); } + private static String getScreenLockSummary( + ScreenLockPreferenceDetailsUtils screenLockPreferenceDetailsUtils) { + String summary = screenLockPreferenceDetailsUtils.getSummary(UserHandle.myUserId()); + return summary != null ? summary : ""; + } + /** Notifies Safety Center of a change in lock screen settings. */ public static void onLockScreenChange(Context context) { setSafetySourceData( diff --git a/src/com/android/settings/security/ScreenLockPreferenceDetailsUtils.java b/src/com/android/settings/security/ScreenLockPreferenceDetailsUtils.java index bc38feb20dc..b1685685bb4 100644 --- a/src/com/android/settings/security/ScreenLockPreferenceDetailsUtils.java +++ b/src/com/android/settings/security/ScreenLockPreferenceDetailsUtils.java @@ -23,6 +23,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; +import androidx.annotation.Nullable; import androidx.annotation.StringRes; import com.android.internal.app.UnlaunchableAppActivity; @@ -43,6 +44,7 @@ public class ScreenLockPreferenceDetailsUtils { private final int mUserId = UserHandle.myUserId(); private final Context mContext; + @Nullable private final LockPatternUtils mLockPatternUtils; private final int mProfileChallengeUserId; private final UserManager mUm; @@ -85,7 +87,7 @@ public class ScreenLockPreferenceDetailsUtils { * Returns whether the lock pattern is secure. */ public boolean isLockPatternSecure() { - return mLockPatternUtils.isSecure(mUserId); + return mLockPatternUtils != null && mLockPatternUtils.isSecure(mUserId); } /** @@ -148,6 +150,7 @@ public class ScreenLockPreferenceDetailsUtils { // profile with unified challenge on FBE-enabled devices. Otherwise, vold would not be // able to complete the operation due to the lack of (old) encryption key. if (mProfileChallengeUserId != UserHandle.USER_NULL + && mLockPatternUtils != null && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId) && StorageManager.isFileEncrypted()) { if (mUm.isQuietModeEnabled(UserHandle.of(mProfileChallengeUserId))) { @@ -166,8 +169,12 @@ public class ScreenLockPreferenceDetailsUtils { .toIntent(); } + @Nullable @StringRes private Integer getSummaryResId(int userId) { + if (mLockPatternUtils == null) { + return null; + } if (!mLockPatternUtils.isSecure(userId)) { if (userId == mProfileChallengeUserId || mLockPatternUtils.isLockScreenDisabled(userId)) { diff --git a/tests/unit/src/com/android/settings/security/ScreenLockPreferenceDetailsUtilsTest.java b/tests/unit/src/com/android/settings/security/ScreenLockPreferenceDetailsUtilsTest.java index abc982db33c..25358708043 100644 --- a/tests/unit/src/com/android/settings/security/ScreenLockPreferenceDetailsUtilsTest.java +++ b/tests/unit/src/com/android/settings/security/ScreenLockPreferenceDetailsUtilsTest.java @@ -78,6 +78,7 @@ public class ScreenLockPreferenceDetailsUtilsTest { private StorageManager mStorageManager; private Context mContext; + private FakeFeatureFactory mFeatureFactory; private ScreenLockPreferenceDetailsUtils mScreenLockPreferenceDetailsUtils; @@ -95,8 +96,8 @@ public class ScreenLockPreferenceDetailsUtilsTest { doNothing().when(mContext).startActivity(any()); when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{}); - final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest(); - when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) + mFeatureFactory = FakeFeatureFactory.setupForTest(); + when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) .thenReturn(mLockPatternUtils); mScreenLockPreferenceDetailsUtils = new ScreenLockPreferenceDetailsUtils(mContext); @@ -230,6 +231,15 @@ public class ScreenLockPreferenceDetailsUtilsTest { assertNull(mScreenLockPreferenceDetailsUtils.getSummary(USER_ID)); } + @Test + public void getSummary_noLockPatternUtils_shouldReturnNull() { + when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) + .thenReturn(null); + mScreenLockPreferenceDetailsUtils = new ScreenLockPreferenceDetailsUtils(mContext); + + assertNull(mScreenLockPreferenceDetailsUtils.getSummary(USER_ID)); + } + @Test public void isPasswordQualityManaged_withoutAdmin_shouldReturnFalse() { final RestrictedLockUtils.EnforcedAdmin admin = null; @@ -274,6 +284,15 @@ public class ScreenLockPreferenceDetailsUtilsTest { assertThat(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).isFalse(); } + @Test + public void isLockPatternSecure_noLockPatterUtils_shouldReturnFalse() { + when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) + .thenReturn(null); + mScreenLockPreferenceDetailsUtils = new ScreenLockPreferenceDetailsUtils(mContext); + + assertThat(mScreenLockPreferenceDetailsUtils.isLockPatternSecure()).isFalse(); + } + @Test @RequiresFlagsEnabled(Flags.FLAG_BIOMETRIC_ONBOARDING_EDUCATION) public void shouldShowGearMenu_patternIsSecure_flagOn_shouldReturnFalse() { @@ -341,6 +360,20 @@ public class ScreenLockPreferenceDetailsUtilsTest { ChooseLockGeneric.ChooseLockGenericFragment.class.getName()); } + @Test + public void getLaunchChooseLockGenericFragmentIntent_noLockPatternUtils_returnsIntent() { + when(mFeatureFactory.securityFeatureProvider.getLockPatternUtils(mContext)) + .thenReturn(null); + mScreenLockPreferenceDetailsUtils = new ScreenLockPreferenceDetailsUtils(mContext); + when(mUserManager.isQuietModeEnabled(any())).thenReturn(false); + + final Intent intent = mScreenLockPreferenceDetailsUtils + .getLaunchChooseLockGenericFragmentIntent(SOURCE_METRICS_CATEGORY); + + assertFragmentLaunchIntent(intent, + ChooseLockGeneric.ChooseLockGenericFragment.class.getName()); + } + private void whenConfigShowUnlockSetOrChangeIsEnabled(boolean enabled) { final int resId = ResourcesUtils.getResourcesId( ApplicationProvider.getApplicationContext(), "bool",