Loading src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java +50 −19 Original line number Diff line number Diff line Loading @@ -57,7 +57,10 @@ import com.android.internal.widget.LockscreenCredential; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.InstrumentedFragment; import com.android.settingslib.widget.SettingsThemeHelper; import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; /** Loading Loading @@ -108,6 +111,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr protected boolean mRemoteValidation; protected boolean mRequestWriteRepairModePassword; protected boolean mRepairMode; protected boolean mExpressiveTheme; protected CharSequence mAlternateButtonText; protected BiometricManager mBiometricManager; @Nullable protected RemoteLockscreenValidationSession mRemoteLockscreenValidationSession; Loading @@ -115,6 +119,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr @Nullable protected RemoteLockscreenValidationClient mRemoteLockscreenValidationClient; protected RemoteLockscreenValidationFragment mRemoteLockscreenValidationFragment; @Nullable protected SaveAndFinishWorker mSaveAndFinishWorker; @Nullable protected FooterBarMixin mFooterBarMixin; private boolean isInternalActivity() { return (getActivity() instanceof ConfirmLockPassword.InternalActivity) Loading Loading @@ -194,29 +199,49 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr mDevicePolicyManager = (DevicePolicyManager) getActivity().getSystemService( Context.DEVICE_POLICY_SERVICE); mBiometricManager = getActivity().getSystemService(BiometricManager.class); mExpressiveTheme = SettingsThemeHelper.isExpressiveTheme(getActivity()); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mCancelButton = view.findViewById(R.id.cancelButton); boolean showCancelButton = mRemoteValidation || getActivity().getIntent().getBooleanExtra( SHOW_CANCEL_BUTTON, false); boolean hasAlternateButton = (mFrp || mRemoteValidation || mRepairMode) boolean hasAlternateButton = (mFrp || mRemoteValidation || mRepairMode) && !TextUtils.isEmpty(mAlternateButtonText); mCancelButton.setVisibility(showCancelButton || hasAlternateButton ? View.VISIBLE : View.GONE); boolean showCancelButton = mRemoteValidation || getActivity().getIntent().getBooleanExtra(SHOW_CANCEL_BUTTON, false) || hasAlternateButton; mFooterBarMixin = mGlifLayout.getMixin(FooterBarMixin.class); if (mExpressiveTheme && showCancelButton && mFooterBarMixin != null && mRemoteValidation) { mFooterBarMixin.setSecondaryButton( new FooterButton.Builder(getActivity()) .setButtonType(FooterButton.ButtonType.CANCEL) .setText(hasAlternateButton ? mAlternateButtonText.toString() : getString(R.string.cancel)) .setListener(v -> onRemoteLockscreenValidationFailure( "Forgot lockscreen credential button pressed.")) .build()); // Remove the cancel button since the footer bar button is used instead mCancelButton.setVisibility(View.GONE); } else { mCancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE); if (hasAlternateButton) { mCancelButton.setText(mAlternateButtonText); } mCancelButton.setOnClickListener(v -> { mCancelButton.setOnClickListener( v -> { if (hasAlternateButton) { getActivity().setResult(KeyguardManager.RESULT_ALTERNATE); getActivity().finish(); } else if (mRemoteValidation) { onRemoteLockscreenValidationFailure("Forgot lockscreen credential button pressed."); onRemoteLockscreenValidationFailure( "Forgot lockscreen credential button pressed."); } }); } setupForgotButtonIfManagedProfile(view); mCheckBox = view.findViewById(R.id.checkbox); Loading Loading @@ -441,10 +466,16 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr return; } boolean enable = mRemoteLockscreenValidationFragment.isRemoteValidationInProgress(); mGlifLayout.setProgressBarShown(enable); mCheckBox.setEnabled(!enable); mCancelButton.setEnabled(!enable); boolean inProgress = mRemoteLockscreenValidationFragment.isRemoteValidationInProgress(); mGlifLayout.setProgressBarShown(inProgress); if (mExpressiveTheme && mFooterBarMixin != null && mFooterBarMixin.getSecondaryButton() != null) { mFooterBarMixin.getSecondaryButton().setEnabled(!inProgress); } else { mCancelButton.setEnabled(!inProgress); } mCheckBox.setEnabled(!inProgress); } /** Loading src/com/android/settings/password/ConfirmLockPassword.java +15 −4 Original line number Diff line number Diff line Loading @@ -251,10 +251,21 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { ? getDefaultCheckboxLabel() : mCheckBoxLabel); } if (mCancelButton != null && TextUtils.isEmpty(mAlternateButtonText)) { mCancelButton.setText(mIsAlpha if (TextUtils.isEmpty(mAlternateButtonText)) { int forgotLockPasswordResId = mIsAlpha ? R.string.lockpassword_forgot_password : R.string.lockpassword_forgot_pin); : R.string.lockpassword_forgot_pin; if (mExpressiveTheme && mFooterBarMixin != null && mFooterBarMixin.getSecondaryButton() != null) { mFooterBarMixin .getSecondaryButton() .setText(getActivity(), forgotLockPasswordResId); } else if (mCancelButton != null) { mCancelButton.setText(forgotLockPasswordResId); } } updateRemoteLockscreenValidationViews(); } Loading src/com/android/settings/password/ConfirmLockPattern.java +11 −2 Original line number Diff line number Diff line Loading @@ -236,8 +236,17 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { ? getDefaultCheckboxLabel() : mCheckBoxLabel); } if (mCancelButton != null && TextUtils.isEmpty(mAlternateButtonText)) { mCancelButton.setText(R.string.lockpassword_forgot_pattern); if (TextUtils.isEmpty(mAlternateButtonText)) { int forgotLockPasswordResId = R.string.lockpassword_forgot_pattern; if (mExpressiveTheme && mFooterBarMixin != null && mFooterBarMixin.getSecondaryButton() != null) { mFooterBarMixin .getSecondaryButton() .setText(getActivity(), forgotLockPasswordResId); } else if (mCancelButton != null) { mCancelButton.setText(forgotLockPasswordResId); } } updateRemoteLockscreenValidationViews(); } Loading tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java +44 −0 Original line number Diff line number Diff line Loading @@ -34,7 +34,10 @@ import android.app.admin.ManagedSubscriptionsPolicy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.FeatureFlagUtils; import android.view.View; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; Loading @@ -45,9 +48,11 @@ import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowLockPatternUtils; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.testutils.shadow.ShadowUtils; import com.android.settingslib.widget.theme.flags.Flags; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; Loading @@ -67,6 +72,9 @@ import org.robolectric.shadows.ShadowApplicationPackageManager; }) public class ConfirmCredentialTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private Context mContext; private ShadowApplicationPackageManager mShadowApplicationPackageManager; Loading Loading @@ -175,6 +183,42 @@ public class ConfirmCredentialTest { assertThat(activity.isFinishing()).isTrue(); } @Test public void normalCredentialConfirmation_noCancelButton() { ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(ConfirmLockPassword.class, new Intent()); ConfirmDeviceCredentialBaseFragment fragment = getConfirmDeviceCredentialBaseFragment(activity); assertThat(fragment.mFooterBarMixin.getButtonContainer()).isNull(); assertThat(fragment.mCancelButton.getVisibility()).isEqualTo(View.GONE); } @Test public void remoteValidation_usesCancelButton() throws Exception { ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity( ConfirmLockPassword.class, createRemoteLockscreenValidationIntent( KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS)); ConfirmDeviceCredentialBaseFragment fragment = getConfirmDeviceCredentialBaseFragment(activity); assertThat(fragment.mFooterBarMixin.getButtonContainer()).isNull(); assertThat(fragment.mCancelButton.getVisibility()).isEqualTo(View.VISIBLE); } @Test @EnableFlags(Flags.FLAG_IS_EXPRESSIVE_DESIGN_ENABLED) public void remoteValidation_expressiveTheme_usesFooterBarButton() throws Exception { ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity( ConfirmLockPassword.class, createRemoteLockscreenValidationIntent( KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS)); ConfirmDeviceCredentialBaseFragment fragment = getConfirmDeviceCredentialBaseFragment(activity); assertThat(fragment.mFooterBarMixin.getSecondaryButton()).isNotNull(); assertThat(fragment.mCancelButton.getVisibility()).isEqualTo(View.GONE); } @Test public void testLastTryDialogShownExactlyOnce() { FragmentManager fm = Robolectric.buildActivity(FragmentActivity.class). Loading Loading
src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java +50 −19 Original line number Diff line number Diff line Loading @@ -57,7 +57,10 @@ import com.android.internal.widget.LockscreenCredential; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.InstrumentedFragment; import com.android.settingslib.widget.SettingsThemeHelper; import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; /** Loading Loading @@ -108,6 +111,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr protected boolean mRemoteValidation; protected boolean mRequestWriteRepairModePassword; protected boolean mRepairMode; protected boolean mExpressiveTheme; protected CharSequence mAlternateButtonText; protected BiometricManager mBiometricManager; @Nullable protected RemoteLockscreenValidationSession mRemoteLockscreenValidationSession; Loading @@ -115,6 +119,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr @Nullable protected RemoteLockscreenValidationClient mRemoteLockscreenValidationClient; protected RemoteLockscreenValidationFragment mRemoteLockscreenValidationFragment; @Nullable protected SaveAndFinishWorker mSaveAndFinishWorker; @Nullable protected FooterBarMixin mFooterBarMixin; private boolean isInternalActivity() { return (getActivity() instanceof ConfirmLockPassword.InternalActivity) Loading Loading @@ -194,29 +199,49 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr mDevicePolicyManager = (DevicePolicyManager) getActivity().getSystemService( Context.DEVICE_POLICY_SERVICE); mBiometricManager = getActivity().getSystemService(BiometricManager.class); mExpressiveTheme = SettingsThemeHelper.isExpressiveTheme(getActivity()); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mCancelButton = view.findViewById(R.id.cancelButton); boolean showCancelButton = mRemoteValidation || getActivity().getIntent().getBooleanExtra( SHOW_CANCEL_BUTTON, false); boolean hasAlternateButton = (mFrp || mRemoteValidation || mRepairMode) boolean hasAlternateButton = (mFrp || mRemoteValidation || mRepairMode) && !TextUtils.isEmpty(mAlternateButtonText); mCancelButton.setVisibility(showCancelButton || hasAlternateButton ? View.VISIBLE : View.GONE); boolean showCancelButton = mRemoteValidation || getActivity().getIntent().getBooleanExtra(SHOW_CANCEL_BUTTON, false) || hasAlternateButton; mFooterBarMixin = mGlifLayout.getMixin(FooterBarMixin.class); if (mExpressiveTheme && showCancelButton && mFooterBarMixin != null && mRemoteValidation) { mFooterBarMixin.setSecondaryButton( new FooterButton.Builder(getActivity()) .setButtonType(FooterButton.ButtonType.CANCEL) .setText(hasAlternateButton ? mAlternateButtonText.toString() : getString(R.string.cancel)) .setListener(v -> onRemoteLockscreenValidationFailure( "Forgot lockscreen credential button pressed.")) .build()); // Remove the cancel button since the footer bar button is used instead mCancelButton.setVisibility(View.GONE); } else { mCancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE); if (hasAlternateButton) { mCancelButton.setText(mAlternateButtonText); } mCancelButton.setOnClickListener(v -> { mCancelButton.setOnClickListener( v -> { if (hasAlternateButton) { getActivity().setResult(KeyguardManager.RESULT_ALTERNATE); getActivity().finish(); } else if (mRemoteValidation) { onRemoteLockscreenValidationFailure("Forgot lockscreen credential button pressed."); onRemoteLockscreenValidationFailure( "Forgot lockscreen credential button pressed."); } }); } setupForgotButtonIfManagedProfile(view); mCheckBox = view.findViewById(R.id.checkbox); Loading Loading @@ -441,10 +466,16 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr return; } boolean enable = mRemoteLockscreenValidationFragment.isRemoteValidationInProgress(); mGlifLayout.setProgressBarShown(enable); mCheckBox.setEnabled(!enable); mCancelButton.setEnabled(!enable); boolean inProgress = mRemoteLockscreenValidationFragment.isRemoteValidationInProgress(); mGlifLayout.setProgressBarShown(inProgress); if (mExpressiveTheme && mFooterBarMixin != null && mFooterBarMixin.getSecondaryButton() != null) { mFooterBarMixin.getSecondaryButton().setEnabled(!inProgress); } else { mCancelButton.setEnabled(!inProgress); } mCheckBox.setEnabled(!inProgress); } /** Loading
src/com/android/settings/password/ConfirmLockPassword.java +15 −4 Original line number Diff line number Diff line Loading @@ -251,10 +251,21 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { ? getDefaultCheckboxLabel() : mCheckBoxLabel); } if (mCancelButton != null && TextUtils.isEmpty(mAlternateButtonText)) { mCancelButton.setText(mIsAlpha if (TextUtils.isEmpty(mAlternateButtonText)) { int forgotLockPasswordResId = mIsAlpha ? R.string.lockpassword_forgot_password : R.string.lockpassword_forgot_pin); : R.string.lockpassword_forgot_pin; if (mExpressiveTheme && mFooterBarMixin != null && mFooterBarMixin.getSecondaryButton() != null) { mFooterBarMixin .getSecondaryButton() .setText(getActivity(), forgotLockPasswordResId); } else if (mCancelButton != null) { mCancelButton.setText(forgotLockPasswordResId); } } updateRemoteLockscreenValidationViews(); } Loading
src/com/android/settings/password/ConfirmLockPattern.java +11 −2 Original line number Diff line number Diff line Loading @@ -236,8 +236,17 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { ? getDefaultCheckboxLabel() : mCheckBoxLabel); } if (mCancelButton != null && TextUtils.isEmpty(mAlternateButtonText)) { mCancelButton.setText(R.string.lockpassword_forgot_pattern); if (TextUtils.isEmpty(mAlternateButtonText)) { int forgotLockPasswordResId = R.string.lockpassword_forgot_pattern; if (mExpressiveTheme && mFooterBarMixin != null && mFooterBarMixin.getSecondaryButton() != null) { mFooterBarMixin .getSecondaryButton() .setText(getActivity(), forgotLockPasswordResId); } else if (mCancelButton != null) { mCancelButton.setText(forgotLockPasswordResId); } } updateRemoteLockscreenValidationViews(); } Loading
tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java +44 −0 Original line number Diff line number Diff line Loading @@ -34,7 +34,10 @@ import android.app.admin.ManagedSubscriptionsPolicy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.FeatureFlagUtils; import android.view.View; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; Loading @@ -45,9 +48,11 @@ import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowLockPatternUtils; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.testutils.shadow.ShadowUtils; import com.android.settingslib.widget.theme.flags.Flags; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; Loading @@ -67,6 +72,9 @@ import org.robolectric.shadows.ShadowApplicationPackageManager; }) public class ConfirmCredentialTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private Context mContext; private ShadowApplicationPackageManager mShadowApplicationPackageManager; Loading Loading @@ -175,6 +183,42 @@ public class ConfirmCredentialTest { assertThat(activity.isFinishing()).isTrue(); } @Test public void normalCredentialConfirmation_noCancelButton() { ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(ConfirmLockPassword.class, new Intent()); ConfirmDeviceCredentialBaseFragment fragment = getConfirmDeviceCredentialBaseFragment(activity); assertThat(fragment.mFooterBarMixin.getButtonContainer()).isNull(); assertThat(fragment.mCancelButton.getVisibility()).isEqualTo(View.GONE); } @Test public void remoteValidation_usesCancelButton() throws Exception { ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity( ConfirmLockPassword.class, createRemoteLockscreenValidationIntent( KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS)); ConfirmDeviceCredentialBaseFragment fragment = getConfirmDeviceCredentialBaseFragment(activity); assertThat(fragment.mFooterBarMixin.getButtonContainer()).isNull(); assertThat(fragment.mCancelButton.getVisibility()).isEqualTo(View.VISIBLE); } @Test @EnableFlags(Flags.FLAG_IS_EXPRESSIVE_DESIGN_ENABLED) public void remoteValidation_expressiveTheme_usesFooterBarButton() throws Exception { ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity( ConfirmLockPassword.class, createRemoteLockscreenValidationIntent( KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS)); ConfirmDeviceCredentialBaseFragment fragment = getConfirmDeviceCredentialBaseFragment(activity); assertThat(fragment.mFooterBarMixin.getSecondaryButton()).isNotNull(); assertThat(fragment.mCancelButton.getVisibility()).isEqualTo(View.GONE); } @Test public void testLastTryDialogShownExactlyOnce() { FragmentManager fm = Robolectric.buildActivity(FragmentActivity.class). Loading