Merge "Add home controls button to screensaver settings" into tm-qpr-dev
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index f154abc..fd8d55f 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -20,6 +20,7 @@
     android:id="@+id/panel_container"
     android:layout_width="@dimen/settings_panel_width"
     android:layout_height="wrap_content"
+    android:fitsSystemWindows="true"
     android:layout_gravity="center_horizontal"
     android:background="@drawable/settings_panel_rounded_top_corner_background" >
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1df5dad..35a4c9d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4805,6 +4805,9 @@
     <string name="lockpattern_settings_enable_summary">Must draw pattern to unlock screen</string>
     <!-- Security & location settings screen, setting check box title. This setting controls whether a visible green line is drawn as the users move their finger around while drawing the unlock pattern.  If checked, this line is drawn.  If unchecked, there is nothing drawn so the users do not reveal their pattern while they unlock the phone.-->
     <string name="lockpattern_settings_enable_visible_pattern_title">Make pattern visible</string>
+    <!-- Security & location settings screen, setting check box title. This setting disables animations when entering the PIN.-->
+    <string name="lockpattern_settings_enhanced_pin_privacy_title">Enhanced PIN privacy</string>
+    <string name="lockpattern_settings_enhanced_pin_privacy_summary">Disable animations while entering the PIN</string>
     <!-- Security & location settings screen, setting check box title. This setting controls whether a visible green line is drawn as the users move their finger around while drawing the profile unlock pattern.  If checked, this line is drawn.  If unchecked, there is nothing drawn so the users do not reveal their pattern while they unlock the profile.-->
     <string name="lockpattern_settings_enable_visible_pattern_title_profile">Make profile pattern visible</string>
     <!-- Security & location settings screen, setting check box title. This setting controls whether tactile feedback will be produced when the user draws the pattern.-->
diff --git a/res/values/themes.xml b/res/values/themes.xml
index ff56e7e..e6c0510 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -229,6 +229,7 @@
     <!-- Note that Dialog themes do not set list dividers -->
     <style name="Theme.Panel" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
         <item name="android:windowBackground">@null</item>
+        <item name="android:windowTranslucentNavigation">true</item>
         <item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:listDivider">@*android:drawable/list_divider_material</item>
diff --git a/res/xml/screen_lock_settings.xml b/res/xml/screen_lock_settings.xml
index dd4ac34..930120e 100644
--- a/res/xml/screen_lock_settings.xml
+++ b/res/xml/screen_lock_settings.xml
@@ -27,6 +27,12 @@
         android:key="visiblepattern"
         android:title="@string/lockpattern_settings_enable_visible_pattern_title" />
 
+    <!-- available in pin -->
+    <SwitchPreference
+        android:key="enhancedPinPrivacy"
+        android:title="@string/lockpattern_settings_enhanced_pin_privacy_title"
+        android:summary="@string/lockpattern_settings_enhanced_pin_privacy_summary" />
+
     <!-- available in pin/pattern/password -->
     <com.android.settings.display.TimeoutListPreference
         android:key="lock_after_timeout"
diff --git a/src/com/android/settings/accessibility/FontSizeData.java b/src/com/android/settings/accessibility/FontSizeData.java
index 56980a4..1de0a5f 100644
--- a/src/com/android/settings/accessibility/FontSizeData.java
+++ b/src/com/android/settings/accessibility/FontSizeData.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
 import static com.android.settings.display.ToggleFontSizePreferenceFragment.fontSizeValueToIndex;
 
 import android.content.ContentResolver;
@@ -52,6 +54,12 @@
     @Override
     void commit(int currentProgress) {
         final ContentResolver resolver = getContext().getContentResolver();
+        if (Settings.Secure.getInt(resolver,
+                Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
+                /* def= */ OFF) != ON) {
+            Settings.Secure.putInt(resolver,
+                    Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, ON);
+        }
         Settings.System.putFloat(resolver, Settings.System.FONT_SCALE,
                 getValues().get(currentProgress));
     }
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 9ed284c..368564a 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -676,7 +676,10 @@
         }
     }
 
-    private void configureEnrollmentStage(@RawRes int lottie) {
+    @VisibleForTesting void configureEnrollmentStage(@RawRes int lottie) {
+        if (!mCanAssumeSfps) {
+            setDescriptionText("");
+        }
         LottieCompositionFactory.fromRawRes(this, lottie)
                 .addListener((c) -> {
                     mIllustrationLottie.setComposition(c);
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index 77949eb..60b8f88 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -29,12 +29,15 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsControllerCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
+import com.android.settings.Utils;
 import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
 
 /**
@@ -144,9 +147,33 @@
             window.setGravity(Gravity.BOTTOM);
             window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
                     WindowManager.LayoutParams.WRAP_CONTENT);
+            setupNavigationBar();
             mPanelFragment = new PanelFragment();
             mPanelFragment.setArguments(new Bundle(mBundle));
             fragmentManager.beginTransaction().add(R.id.main_content, mPanelFragment).commit();
         }
     }
+
+    /**
+     * Adjust bottom edge and color.
+     */
+    private void setupNavigationBar() {
+        // Extend the panel all the way to the bottom of the screen, as opposed to sitting on top of
+        // the navigation bar.
+        ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView(),
+                (v, windowInsets) -> {
+                    v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), v.getPaddingRight(), 0);
+                    return windowInsets; // propagate down to panel layout root element
+                });
+
+        // When using 3-button navigation in light mode, the system picks white navigation buttons
+        // which are not sufficiently contrasted from the panel background.
+        WindowInsetsControllerCompat windowInsetsController =
+                ViewCompat.getWindowInsetsController(getWindow().getDecorView());
+
+        if (windowInsetsController != null) {
+            boolean forceNavigationButtonsDark = !Utils.isNightMode(this);
+            windowInsetsController.setAppearanceLightNavigationBars(forceNavigationButtonsDark);
+        }
+    }
 }
diff --git a/src/com/android/settings/security/screenlock/LockScreenPreferenceController.java b/src/com/android/settings/security/screenlock/LockScreenPreferenceController.java
index 8585493..8a1cb2e 100644
--- a/src/com/android/settings/security/screenlock/LockScreenPreferenceController.java
+++ b/src/com/android/settings/security/screenlock/LockScreenPreferenceController.java
@@ -17,29 +17,22 @@
 package com.android.settings.security.screenlock;
 
 import android.content.Context;
-import android.os.UserHandle;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
-import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.notification.LockScreenNotificationPreferenceController;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnResume;
 
 public class LockScreenPreferenceController extends BasePreferenceController implements
         LifecycleObserver, OnResume {
 
-    private static final int MY_USER_ID = UserHandle.myUserId();
-    private final LockPatternUtils mLockPatternUtils;
     private Preference mPreference;
 
     public LockScreenPreferenceController(Context context, String key) {
         super(context, key);
-        mLockPatternUtils = FeatureFactory.getFactory(context)
-                .getSecurityFeatureProvider().getLockPatternUtils(context);
     }
 
     @Override
diff --git a/src/com/android/settings/security/screenlock/PatternVisiblePreferenceController.java b/src/com/android/settings/security/screenlock/PatternVisiblePreferenceController.java
index 133078c..ea3403b 100644
--- a/src/com/android/settings/security/screenlock/PatternVisiblePreferenceController.java
+++ b/src/com/android/settings/security/screenlock/PatternVisiblePreferenceController.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.security.screenlock;
 
-import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 
 import androidx.preference.Preference;
@@ -58,9 +57,8 @@
     }
 
     private boolean isPatternLock() {
-        return mLockPatternUtils.isSecure(mUserId)
-                && mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)
-                == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+        return mLockPatternUtils.getCredentialTypeForUser(mUserId)
+                == LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
     }
 
     @Override
diff --git a/src/com/android/settings/security/screenlock/PinPrivacyPreferenceController.kt b/src/com/android/settings/security/screenlock/PinPrivacyPreferenceController.kt
new file mode 100644
index 0000000..176183e
--- /dev/null
+++ b/src/com/android/settings/security/screenlock/PinPrivacyPreferenceController.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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.security.screenlock
+
+import android.content.Context
+import android.provider.Settings
+import androidx.preference.Preference
+import androidx.preference.TwoStatePreference
+import com.android.internal.widget.LockPatternUtils
+import com.android.internal.widget.LockPatternUtils.*
+import com.android.settings.core.PreferenceControllerMixin
+import com.android.settingslib.core.AbstractPreferenceController
+
+class PinPrivacyPreferenceController(
+    context: Context,
+    private val userId: Int,
+    private val lockPatternUtils: LockPatternUtils
+) : AbstractPreferenceController(context), PreferenceControllerMixin,
+    Preference.OnPreferenceChangeListener {
+
+    companion object {
+        private const val PREF_KEY = "enhancedPinPrivacy"
+    }
+
+    override fun isAvailable(): Boolean {
+        val credentialType = lockPatternUtils.getCredentialTypeForUser(userId)
+        return credentialType == CREDENTIAL_TYPE_PIN
+    }
+
+    override fun getPreferenceKey(): String {
+        return PREF_KEY
+    }
+
+    override fun onPreferenceChange(preference: Preference?, value: Any?): Boolean {
+        lockPatternUtils.setPinEnhancedPrivacyEnabled((value as Boolean), userId)
+        return true
+    }
+
+    override fun updateState(preference: Preference) {
+        (preference as TwoStatePreference).isChecked = getCurrentPreferenceState()
+    }
+
+    private fun getCurrentPreferenceState(): Boolean {
+        return lockPatternUtils.isPinEnhancedPrivacyEnabled(userId)
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/security/screenlock/ScreenLockSettings.java b/src/com/android/settings/security/screenlock/ScreenLockSettings.java
index 082e333..8c9dacb 100644
--- a/src/com/android/settings/security/screenlock/ScreenLockSettings.java
+++ b/src/com/android/settings/security/screenlock/ScreenLockSettings.java
@@ -68,9 +68,12 @@
 
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             DashboardFragment parent, LockPatternUtils lockPatternUtils) {
+
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new PatternVisiblePreferenceController(
                 context, MY_USER_ID, lockPatternUtils));
+        controllers.add(new PinPrivacyPreferenceController(
+                context, MY_USER_ID, lockPatternUtils));
         controllers.add(new PowerButtonInstantLockPreferenceController(
                 context, MY_USER_ID, lockPatternUtils));
         controllers.add(new LockAfterTimeoutPreferenceController(
diff --git a/tests/robotests/src/com/android/settings/accessibility/FontSizeDataTest.java b/tests/robotests/src/com/android/settings/accessibility/FontSizeDataTest.java
index 7e35714..adf7495 100644
--- a/tests/robotests/src/com/android/settings/accessibility/FontSizeDataTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/FontSizeDataTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -52,4 +55,19 @@
 
         assertThat(currentScale).isEqualTo(mFontSizeData.getValues().get(progress));
     }
+
+    @Test
+    public void commit_fontScalingHasBeenChangedIsOn() {
+        final int progress = 3;
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, OFF);
+
+        mFontSizeData.commit(progress);
+        final int currentSettings = Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
+                /* def= */ OFF);
+
+        assertThat(currentSettings).isEqualTo(ON);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index 439abc6..ea47924 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -283,6 +283,28 @@
         assertThat(getLayout().getDescriptionTextView().getVisibility()).isEqualTo(View.VISIBLE);
     }
 
+    @Test
+    public void testUdfpsConfigureEnrollmentStage_descriptionText() {
+        initializeActivityFor(TYPE_UDFPS_OPTICAL);
+
+        assertThat(getLayout().getDescriptionText()).isNotEqualTo("");
+
+        mActivity.configureEnrollmentStage(0 /* lottie */);
+
+        assertThat(getLayout().getDescriptionText()).isEqualTo("");
+    }
+
+    @Test
+    public void testSfpsConfigureEnrollmentStage_descriptionText() {
+        initializeActivityFor(TYPE_POWER_BUTTON);
+
+        assertThat(getLayout().getDescriptionTextView().getVisibility()).isEqualTo(View.GONE);
+
+        mActivity.configureEnrollmentStage(0 /* lottie */);
+
+        assertThat(getLayout().getDescriptionTextView().getVisibility()).isEqualTo(View.GONE);
+    }
+
     private GlifLayout getLayout() {
         return (GlifLayout) mActivity.findViewById(R.id.setup_wizard_layout);
     }
diff --git a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
index 5cdc12a..ea55b90 100644
--- a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
+++ b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
@@ -16,11 +16,13 @@
 
 package com.android.settings.panel;
 
+import static android.content.res.Configuration.UI_MODE_NIGHT_NO;
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -30,15 +32,20 @@
 
 import android.content.res.Configuration;
 import android.os.Build;
+import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsControllerCompat;
 import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
 
 import com.android.settings.R;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -61,6 +68,9 @@
     private PanelFragment mPanelFragment;
     @Mock
     private FragmentManager mFragmentManager;
+    @Mock
+    private FragmentTransaction mTransaction;
+    private int mOriginalUiMode;
 
     @Before
     public void setUp() {
@@ -76,6 +86,15 @@
         mSettingsPanelActivity.mPanelFragment = mPanelFragment;
         when(mFragmentManager.findFragmentById(R.id.main_content)).thenReturn(mPanelFragment);
         when(mSettingsPanelActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
+        mOriginalUiMode = mSettingsPanelActivity.getResources().getConfiguration().uiMode;
+        when(mFragmentManager.beginTransaction()).thenReturn(mTransaction);
+        when(mTransaction.add(anyInt(), any())).thenReturn(mTransaction);
+        when(mTransaction.commit()).thenReturn(0); // don't care about return value
+    }
+
+    @After
+    public void tearDown() {
+        mSettingsPanelActivity.getResources().getConfiguration().uiMode = mOriginalUiMode;
     }
 
     @Test
@@ -179,4 +198,24 @@
 
         verify(mPanelFragment, never()).updatePanelWithAnimation();
     }
+
+    @Test
+    public void onCreated_isWindowBottomPaddingZero() {
+        int paddingBottom = mSettingsPanelActivity.getWindow().getDecorView().getPaddingBottom();
+        assertThat(paddingBottom).isEqualTo(0);
+    }
+
+    @Test
+    public void notInNightMode_lightNavigationBarAppearance() {
+        Configuration config = mSettingsPanelActivity.getResources().getConfiguration();
+        config.uiMode = UI_MODE_NIGHT_NO;
+        mSettingsPanelActivity.onConfigurationChanged(config); // forces creation
+
+        mSettingsPanelActivity.onNewIntent(mSettingsPanelActivity.getIntent());
+        verify(mFragmentManager).beginTransaction();
+
+        View decorView = mSettingsPanelActivity.getWindow().getDecorView();
+        WindowInsetsControllerCompat controller = ViewCompat.getWindowInsetsController(decorView);
+        assertThat(controller.isAppearanceLightNavigationBars()).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/security/screenlock/PatternVisiblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/screenlock/PatternVisiblePreferenceControllerTest.java
index df6818b..10380ab 100644
--- a/tests/robotests/src/com/android/settings/security/screenlock/PatternVisiblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/screenlock/PatternVisiblePreferenceControllerTest.java
@@ -21,7 +21,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 
 import androidx.preference.SwitchPreference;
@@ -52,24 +51,22 @@
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mController =
-            new PatternVisiblePreferenceController(mContext, TEST_USER_ID, mLockPatternUtils);
+                new PatternVisiblePreferenceController(mContext, TEST_USER_ID, mLockPatternUtils);
         mPreference = new SwitchPreference(mContext);
     }
 
     @Test
     public void isAvailable_lockSetToPattern_shouldReturnTrue() {
-        when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true);
-        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(TEST_USER_ID))
-                .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+        when(mLockPatternUtils.getCredentialTypeForUser(TEST_USER_ID))
+                .thenReturn(LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
 
         assertThat(mController.isAvailable()).isTrue();
     }
 
     @Test
     public void isAvailable_lockSetToPin_shouldReturnFalse() {
-        when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true);
-        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(TEST_USER_ID))
-                .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.getCredentialTypeForUser(TEST_USER_ID)).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PIN);
 
         assertThat(mController.isAvailable()).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/security/screenlock/PinPrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/screenlock/PinPrivacyPreferenceControllerTest.java
new file mode 100644
index 0000000..171fb44
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/screenlock/PinPrivacyPreferenceControllerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 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.security.screenlock;
+
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class PinPrivacyPreferenceControllerTest {
+
+    private static final int TEST_USER_ID = 0;
+
+    @Mock
+    private LockPatternUtils mLockPatternUtils;
+    private Context mContext;
+    private PinPrivacyPreferenceController mController;
+    private SwitchPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController =
+                new PinPrivacyPreferenceController(mContext, TEST_USER_ID, mLockPatternUtils);
+        mPreference = new SwitchPreference(mContext);
+    }
+
+    @Test
+    public void isAvailable_lockSetToPin_shouldReturnTrue() {
+        when(mLockPatternUtils.getCredentialTypeForUser(TEST_USER_ID)).thenReturn(
+                CREDENTIAL_TYPE_PIN);
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_lockSetToPinOrPw_shouldReturnTrue() {
+        when(mLockPatternUtils.getCredentialTypeForUser(TEST_USER_ID)).thenReturn(
+                CREDENTIAL_TYPE_PASSWORD_OR_PIN);
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_lockSetToOther_shouldReturnFalse() {
+        when(mLockPatternUtils.getCredentialTypeForUser(TEST_USER_ID)).thenReturn(
+                CREDENTIAL_TYPE_PATTERN);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void updateState_shouldSetPref() {
+        when(mLockPatternUtils.isPinEnhancedPrivacyEnabled(TEST_USER_ID)).thenReturn(true);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_shouldSetPref_false() {
+        when(mLockPatternUtils.isPinEnhancedPrivacyEnabled(TEST_USER_ID)).thenReturn(false);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void onPreferenceChange_shouldUpdateLockPatternUtils() {
+        mController.onPreferenceChange(mPreference, true);
+        verify(mLockPatternUtils).setPinEnhancedPrivacyEnabled(true, TEST_USER_ID);
+    }
+
+    @Test
+    public void getPreferenceKey_returnsConst() {
+        assertThat(mController.getPreferenceKey().equals("enhancedPinPrivacy")).isTrue();
+    }
+}