[BiometricsV2] Refactor Fingerprint intro fragment
Refactor FingerprintEnrollIntroFragment to kotlin and add bindView() method for it. Bug: 286197823 Test: atest FingerprintEnrollmentActivityTest Change-Id: I44157bf2c2bea6f49382335438b16aae3e3e5b4c
This commit is contained in:
@@ -81,6 +81,7 @@
|
||||
android:id="@+id/footer_message_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_2"
|
||||
style="@style/BiometricEnrollIntroMessage" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -102,6 +103,7 @@
|
||||
android:id="@+id/footer_message_3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_3"
|
||||
style="@style/BiometricEnrollIntroMessage" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -110,6 +112,7 @@
|
||||
android:id="@+id/footer_title_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_enroll_introduction_footer_title_1"
|
||||
style="@style/BiometricEnrollIntroTitle" />
|
||||
|
||||
<LinearLayout
|
||||
@@ -130,6 +133,7 @@
|
||||
android:id="@+id/footer_message_4"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_4"
|
||||
style="@style/BiometricEnrollIntroMessage" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -139,7 +143,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/BiometricEnrollIntroTitle"
|
||||
android:text="@string/security_settings_face_enroll_introduction_info_title"/>
|
||||
android:text="@string/security_settings_fingerprint_enroll_introduction_footer_title_2"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -159,6 +163,7 @@
|
||||
android:id="@+id/footer_message_5"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_5"
|
||||
style="@style/BiometricEnrollIntroMessage" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -180,6 +185,7 @@
|
||||
android:id="@+id/footer_message_6"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_6"
|
||||
style="@style/BiometricEnrollIntroMessage" />
|
||||
</LinearLayout>
|
||||
|
||||
|
@@ -1,310 +0,0 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.view;
|
||||
|
||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED;
|
||||
|
||||
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX;
|
||||
|
||||
import static com.google.android.setupdesign.util.DynamicColorPalette.ColorType.ACCENT;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus;
|
||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel;
|
||||
|
||||
import com.google.android.setupcompat.template.FooterBarMixin;
|
||||
import com.google.android.setupcompat.template.FooterButton;
|
||||
import com.google.android.setupdesign.GlifLayout;
|
||||
import com.google.android.setupdesign.template.RequireScrollMixin;
|
||||
import com.google.android.setupdesign.util.DeviceHelper;
|
||||
import com.google.android.setupdesign.util.DynamicColorPalette;
|
||||
|
||||
/**
|
||||
* Fingerprint intro onboarding page fragment implementation
|
||||
*/
|
||||
public class FingerprintEnrollIntroFragment extends Fragment {
|
||||
|
||||
private static final String TAG = "FingerprintEnrollIntroFragment";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private FingerprintEnrollIntroViewModel mViewModel = null;
|
||||
|
||||
private View mView = null;
|
||||
private FooterButton mPrimaryFooterButton = null;
|
||||
private FooterButton mSecondaryFooterButton = null;
|
||||
private final OnClickListener mOnNextClickListener = (v) -> mViewModel.onNextButtonClick();
|
||||
private final OnClickListener mOnSkipOrCancelClickListener =
|
||||
(v) -> mViewModel.onSkipOrCancelButtonClick();
|
||||
private ImageView mIconShield = null;
|
||||
private TextView mFooterMessage6 = null;
|
||||
@Nullable private PorterDuffColorFilter mIconColorFilter;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
final Context context = inflater.getContext();
|
||||
mView = inflater.inflate(R.layout.fingerprint_enroll_introduction, container, false);
|
||||
|
||||
final ImageView iconFingerprint = mView.findViewById(R.id.icon_fingerprint);
|
||||
final ImageView iconDeviceLocked = mView.findViewById(R.id.icon_device_locked);
|
||||
final ImageView iconTrashCan = mView.findViewById(R.id.icon_trash_can);
|
||||
final ImageView iconInfo = mView.findViewById(R.id.icon_info);
|
||||
mIconShield = mView.findViewById(R.id.icon_shield);
|
||||
final ImageView iconLink = mView.findViewById(R.id.icon_link);
|
||||
iconFingerprint.getDrawable().setColorFilter(getIconColorFilter(context));
|
||||
iconDeviceLocked.getDrawable().setColorFilter(getIconColorFilter(context));
|
||||
iconTrashCan.getDrawable().setColorFilter(getIconColorFilter(context));
|
||||
iconInfo.getDrawable().setColorFilter(getIconColorFilter(context));
|
||||
mIconShield.getDrawable().setColorFilter(getIconColorFilter(context));
|
||||
iconLink.getDrawable().setColorFilter(getIconColorFilter(context));
|
||||
|
||||
final TextView footerMessage2 = mView.findViewById(R.id.footer_message_2);
|
||||
final TextView footerMessage3 = mView.findViewById(R.id.footer_message_3);
|
||||
final TextView footerMessage4 = mView.findViewById(R.id.footer_message_4);
|
||||
final TextView footerMessage5 = mView.findViewById(R.id.footer_message_5);
|
||||
mFooterMessage6 = mView.findViewById(R.id.footer_message_6);
|
||||
footerMessage2.setText(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_2);
|
||||
footerMessage3.setText(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_3);
|
||||
footerMessage4.setText(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_4);
|
||||
footerMessage5.setText(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_5);
|
||||
mFooterMessage6.setText(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_6);
|
||||
|
||||
final TextView footerTitle1 = mView.findViewById(R.id.footer_title_1);
|
||||
final TextView footerTitle2 = mView.findViewById(R.id.footer_title_2);
|
||||
footerTitle1.setText(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_footer_title_1);
|
||||
footerTitle2.setText(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_footer_title_2);
|
||||
|
||||
final TextView footerLink = mView.findViewById(R.id.footer_learn_more);
|
||||
footerLink.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
final String footerLinkStr = getContext().getString(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_message_learn_more,
|
||||
Html.FROM_HTML_MODE_LEGACY);
|
||||
footerLink.setText(Html.fromHtml(footerLinkStr));
|
||||
|
||||
// footer buttons
|
||||
|
||||
return mView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
final Context context = view.getContext();
|
||||
|
||||
if (mViewModel.canAssumeUdfps()) {
|
||||
mFooterMessage6.setVisibility(View.VISIBLE);
|
||||
mIconShield.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mFooterMessage6.setVisibility(View.GONE);
|
||||
mIconShield.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final GlifLayoutHelper glifLayoutHelper = new GlifLayoutHelper(getActivity(), getLayout());
|
||||
if (mViewModel.isBiometricUnlockDisabledByAdmin()
|
||||
&& !mViewModel.isParentalConsentRequired()) {
|
||||
glifLayoutHelper.setHeaderText(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_title_unlock_disabled
|
||||
);
|
||||
glifLayoutHelper.setDescriptionText(getDescriptionDisabledByAdmin(context));
|
||||
} else {
|
||||
glifLayoutHelper.setHeaderText(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_title);
|
||||
glifLayoutHelper.setDescriptionText(getString(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_v3_message,
|
||||
DeviceHelper.getDeviceName(context)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
final Context context = requireContext();
|
||||
final FooterBarMixin footerBarMixin = getFooterBarMixin();
|
||||
initPrimaryFooterButton(context, footerBarMixin);
|
||||
initSecondaryFooterButton(context, footerBarMixin);
|
||||
observePageStatusLiveDataIfNeed();
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
private void initPrimaryFooterButton(@NonNull Context context,
|
||||
@NonNull FooterBarMixin footerBarMixin) {
|
||||
if (footerBarMixin.getPrimaryButton() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPrimaryFooterButton = new FooterButton.Builder(context)
|
||||
.setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
|
||||
.setButtonType(FooterButton.ButtonType.OPT_IN)
|
||||
.setTheme(R.style.SudGlifButton_Primary)
|
||||
.build();
|
||||
mPrimaryFooterButton.setOnClickListener(mOnNextClickListener);
|
||||
footerBarMixin.setPrimaryButton(mPrimaryFooterButton);
|
||||
}
|
||||
|
||||
private void initSecondaryFooterButton(@NonNull Context context,
|
||||
@NonNull FooterBarMixin footerBarMixin) {
|
||||
if (footerBarMixin.getSecondaryButton() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSecondaryFooterButton = new FooterButton.Builder(context)
|
||||
.setText(mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction()
|
||||
? R.string.security_settings_fingerprint_enroll_introduction_cancel
|
||||
: R.string.security_settings_fingerprint_enroll_introduction_no_thanks)
|
||||
.setButtonType(FooterButton.ButtonType.NEXT)
|
||||
.setTheme(R.style.SudGlifButton_Primary)
|
||||
.build();
|
||||
mSecondaryFooterButton.setOnClickListener(mOnSkipOrCancelClickListener);
|
||||
footerBarMixin.setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */);
|
||||
}
|
||||
|
||||
private void observePageStatusLiveDataIfNeed() {
|
||||
final LiveData<FingerprintEnrollIntroStatus> statusLiveData =
|
||||
mViewModel.getPageStatusLiveData();
|
||||
final FingerprintEnrollIntroStatus status = statusLiveData.getValue();
|
||||
if (DEBUG) {
|
||||
Log.e(TAG, "observePageStatusLiveDataIfNeed() requireScrollWithButton, status:"
|
||||
+ status);
|
||||
}
|
||||
if (status != null && (status.hasScrollToBottom()
|
||||
|| status.getEnrollableStatus() == FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)) {
|
||||
// Update once and do not requireScrollWithButton() again when page has scrolled to
|
||||
// bottom or User has enrolled at least a fingerprint, because if we
|
||||
// requireScrollWithButton() again, primary button will become "More" after scrolling.
|
||||
updateFooterButtons(status);
|
||||
return;
|
||||
}
|
||||
|
||||
final RequireScrollMixin requireScrollMixin = getLayout()
|
||||
.getMixin(RequireScrollMixin.class);
|
||||
requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton,
|
||||
getMoreButtonTextRes(), mOnNextClickListener);
|
||||
|
||||
requireScrollMixin.setOnRequireScrollStateChangedListener(
|
||||
scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded));
|
||||
statusLiveData.observe(this, this::updateFooterButtons);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
mViewModel = new ViewModelProvider(getActivity())
|
||||
.get(FingerprintEnrollIntroViewModel.class);
|
||||
super.onAttach(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private PorterDuffColorFilter getIconColorFilter(@NonNull Context context) {
|
||||
if (mIconColorFilter == null) {
|
||||
mIconColorFilter = new PorterDuffColorFilter(
|
||||
DynamicColorPalette.getColor(context, ACCENT),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
return mIconColorFilter;
|
||||
}
|
||||
|
||||
private GlifLayout getLayout() {
|
||||
return mView.findViewById(R.id.setup_wizard_layout);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private FooterBarMixin getFooterBarMixin() {
|
||||
final GlifLayout layout = getLayout();
|
||||
return layout.getMixin(FooterBarMixin.class);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getDescriptionDisabledByAdmin(@NonNull Context context) {
|
||||
final int defaultStrId =
|
||||
R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled;
|
||||
|
||||
final DevicePolicyManager devicePolicyManager = getActivity()
|
||||
.getSystemService(DevicePolicyManager.class);
|
||||
if (devicePolicyManager != null) {
|
||||
return devicePolicyManager.getResources().getString(FINGERPRINT_UNLOCK_DISABLED,
|
||||
() -> context.getString(defaultStrId));
|
||||
} else {
|
||||
Log.w(TAG, "getDescriptionDisabledByAdmin, null device policy manager res");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void updateFooterButtons(@NonNull FingerprintEnrollIntroStatus status) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "updateFooterButtons(" + status + ")");
|
||||
}
|
||||
mPrimaryFooterButton.setText(getContext(),
|
||||
status.getEnrollableStatus() == FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||
? R.string.done
|
||||
: status.hasScrollToBottom()
|
||||
? R.string.security_settings_fingerprint_enroll_introduction_agree
|
||||
: getMoreButtonTextRes());
|
||||
mSecondaryFooterButton.setVisibility(status.hasScrollToBottom()
|
||||
&& status.getEnrollableStatus() != FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||
? View.VISIBLE
|
||||
: View.INVISIBLE);
|
||||
|
||||
final TextView errorTextView = mView.findViewById(R.id.error_text);
|
||||
switch (status.getEnrollableStatus()) {
|
||||
case FINGERPRINT_ENROLLABLE_OK:
|
||||
errorTextView.setText(null);
|
||||
errorTextView.setVisibility(View.GONE);
|
||||
break;
|
||||
case FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX:
|
||||
errorTextView.setText(R.string.fingerprint_intro_error_max);
|
||||
errorTextView.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case FINGERPRINT_ENROLLABLE_UNKNOWN:
|
||||
// default case, do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
@StringRes
|
||||
private int getMoreButtonTextRes() {
|
||||
return R.string.security_settings_face_enroll_introduction_more;
|
||||
}
|
||||
}
|
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* 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.biometrics2.ui.view
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED
|
||||
import android.content.Context
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffColorFilter
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK
|
||||
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_UNKNOWN
|
||||
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel
|
||||
import com.google.android.setupcompat.template.FooterBarMixin
|
||||
import com.google.android.setupcompat.template.FooterButton
|
||||
import com.google.android.setupdesign.GlifLayout
|
||||
import com.google.android.setupdesign.template.RequireScrollMixin
|
||||
import com.google.android.setupdesign.util.DeviceHelper
|
||||
import com.google.android.setupdesign.util.DynamicColorPalette
|
||||
import com.google.android.setupdesign.util.DynamicColorPalette.ColorType.ACCENT
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
* Fingerprint intro onboarding page fragment implementation
|
||||
*/
|
||||
class FingerprintEnrollIntroFragment : Fragment() {
|
||||
|
||||
private val viewModelProvider: ViewModelProvider
|
||||
get() = ViewModelProvider(requireActivity())
|
||||
|
||||
private var _viewModel: FingerprintEnrollIntroViewModel? = null
|
||||
private val viewModel: FingerprintEnrollIntroViewModel
|
||||
get() {
|
||||
if (_viewModel == null) {
|
||||
_viewModel = viewModelProvider[FingerprintEnrollIntroViewModel::class.java]
|
||||
}
|
||||
return _viewModel!!
|
||||
}
|
||||
|
||||
private var introView: GlifLayout? = null
|
||||
|
||||
private var primaryFooterButton: FooterButton? = null
|
||||
|
||||
private var secondaryFooterButton: FooterButton? = null
|
||||
|
||||
private val onNextClickListener =
|
||||
View.OnClickListener { _: View? -> viewModel.onNextButtonClick() }
|
||||
|
||||
private val onSkipOrCancelClickListener =
|
||||
View.OnClickListener { _: View? -> viewModel.onSkipOrCancelButtonClick() }
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
introView = inflater.inflate(
|
||||
R.layout.fingerprint_enroll_introduction,
|
||||
container,
|
||||
false
|
||||
) as GlifLayout
|
||||
return introView!!
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
requireActivity().bindFingerprintEnrollIntroView(
|
||||
view = introView!!,
|
||||
canAssumeUdfps = viewModel.canAssumeUdfps(),
|
||||
isBiometricUnlockDisabledByAdmin = viewModel.isBiometricUnlockDisabledByAdmin,
|
||||
isParentalConsentRequired = viewModel.isParentalConsentRequired,
|
||||
descriptionDisabledByAdminSupplier = { getDescriptionDisabledByAdmin(view.context) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
val context: Context = requireContext()
|
||||
val footerBarMixin: FooterBarMixin = footerBarMixin
|
||||
initPrimaryFooterButton(context, footerBarMixin)
|
||||
initSecondaryFooterButton(context, footerBarMixin)
|
||||
observePageStatusLiveDataIfNeed()
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
private fun initPrimaryFooterButton(
|
||||
context: Context,
|
||||
footerBarMixin: FooterBarMixin
|
||||
) {
|
||||
if (footerBarMixin.primaryButton != null) {
|
||||
return
|
||||
}
|
||||
primaryFooterButton = FooterButton.Builder(context)
|
||||
.setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
|
||||
.setButtonType(FooterButton.ButtonType.OPT_IN)
|
||||
.setTheme(R.style.SudGlifButton_Primary)
|
||||
.build()
|
||||
.also {
|
||||
it.setOnClickListener(onNextClickListener)
|
||||
footerBarMixin.primaryButton = it
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSecondaryFooterButton(
|
||||
context: Context,
|
||||
footerBarMixin: FooterBarMixin
|
||||
) {
|
||||
if (footerBarMixin.secondaryButton != null) {
|
||||
return
|
||||
}
|
||||
secondaryFooterButton = FooterButton.Builder(context)
|
||||
.setText(
|
||||
if (viewModel.request.isAfterSuwOrSuwSuggestedAction)
|
||||
R.string.security_settings_fingerprint_enroll_introduction_cancel
|
||||
else
|
||||
R.string.security_settings_fingerprint_enroll_introduction_no_thanks
|
||||
)
|
||||
.setButtonType(FooterButton.ButtonType.NEXT)
|
||||
.setTheme(R.style.SudGlifButton_Primary)
|
||||
.build()
|
||||
.also {
|
||||
it.setOnClickListener(onSkipOrCancelClickListener)
|
||||
footerBarMixin.setSecondaryButton(it, true /* usePrimaryStyle */)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observePageStatusLiveDataIfNeed() {
|
||||
val statusLiveData: LiveData<FingerprintEnrollIntroStatus> =
|
||||
viewModel.pageStatusLiveData
|
||||
val status: FingerprintEnrollIntroStatus? = statusLiveData.value
|
||||
|
||||
if (DEBUG) {
|
||||
Log.e(
|
||||
TAG, "observePageStatusLiveDataIfNeed() requireScrollWithButton, status:"
|
||||
+ status
|
||||
)
|
||||
}
|
||||
|
||||
if (status != null && (status.hasScrollToBottom()
|
||||
|| status.enrollableStatus === FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
|
||||
) {
|
||||
// Update once and do not requireScrollWithButton() again when page has scrolled to
|
||||
// bottom or User has enrolled at least a fingerprint, because if we
|
||||
// requireScrollWithButton() again, primary button will become "More" after scrolling.
|
||||
updateFooterButtons(status)
|
||||
return
|
||||
}
|
||||
|
||||
introView!!.getMixin(RequireScrollMixin::class.java).let {
|
||||
it.requireScrollWithButton(
|
||||
requireActivity(),
|
||||
primaryFooterButton!!,
|
||||
moreButtonTextRes,
|
||||
onNextClickListener
|
||||
)
|
||||
it.setOnRequireScrollStateChangedListener { scrollNeeded: Boolean ->
|
||||
viewModel.setHasScrolledToBottom(!scrollNeeded)
|
||||
}
|
||||
}
|
||||
statusLiveData.observe(this) { newStatus: FingerprintEnrollIntroStatus ->
|
||||
updateFooterButtons(newStatus)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
_viewModel = null
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
private val footerBarMixin: FooterBarMixin
|
||||
get() = introView!!.getMixin(FooterBarMixin::class.java)
|
||||
|
||||
private fun getDescriptionDisabledByAdmin(context: Context): String? {
|
||||
val defaultStrId: Int =
|
||||
R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled
|
||||
val devicePolicyManager: DevicePolicyManager = requireActivity()
|
||||
.getSystemService(DevicePolicyManager::class.java)
|
||||
|
||||
return devicePolicyManager.resources.getString(FINGERPRINT_UNLOCK_DISABLED) {
|
||||
context.getString(defaultStrId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFooterButtons(status: FingerprintEnrollIntroStatus) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "updateFooterButtons($status)")
|
||||
}
|
||||
primaryFooterButton!!.setText(
|
||||
context,
|
||||
if (status.enrollableStatus === FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
|
||||
R.string.done
|
||||
else if (status.hasScrollToBottom())
|
||||
R.string.security_settings_fingerprint_enroll_introduction_agree
|
||||
else
|
||||
moreButtonTextRes
|
||||
)
|
||||
secondaryFooterButton!!.visibility =
|
||||
if (status.hasScrollToBottom()
|
||||
&& status.enrollableStatus !== FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
|
||||
)
|
||||
View.VISIBLE
|
||||
else
|
||||
View.INVISIBLE
|
||||
|
||||
view!!.findViewById<TextView>(R.id.error_text).let {
|
||||
when (status.enrollableStatus) {
|
||||
FINGERPRINT_ENROLLABLE_OK -> {
|
||||
it.text = null
|
||||
it.visibility = View.GONE
|
||||
}
|
||||
|
||||
FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX -> {
|
||||
it.setText(R.string.fingerprint_intro_error_max)
|
||||
it.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
FINGERPRINT_ENROLLABLE_UNKNOWN -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@get:StringRes
|
||||
private val moreButtonTextRes: Int
|
||||
get() = R.string.security_settings_face_enroll_introduction_more
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FingerprintEnrollIntroFragment"
|
||||
private const val DEBUG = false
|
||||
}
|
||||
}
|
||||
|
||||
fun FragmentActivity.bindFingerprintEnrollIntroView(
|
||||
view: GlifLayout,
|
||||
canAssumeUdfps: Boolean,
|
||||
isBiometricUnlockDisabledByAdmin: Boolean,
|
||||
isParentalConsentRequired: Boolean,
|
||||
descriptionDisabledByAdminSupplier: Supplier<String?>
|
||||
) {
|
||||
val context = view.context
|
||||
|
||||
val iconFingerprint = view.findViewById<ImageView>(R.id.icon_fingerprint)!!
|
||||
val iconDeviceLocked = view.findViewById<ImageView>(R.id.icon_device_locked)!!
|
||||
val iconTrashCan = view.findViewById<ImageView>(R.id.icon_trash_can)!!
|
||||
val iconInfo = view.findViewById<ImageView>(R.id.icon_info)!!
|
||||
val iconShield = view.findViewById<ImageView>(R.id.icon_shield)!!
|
||||
val iconLink = view.findViewById<ImageView>(R.id.icon_link)!!
|
||||
val footerMessage6 = view.findViewById<TextView>(R.id.footer_message_6)!!
|
||||
|
||||
PorterDuffColorFilter(
|
||||
DynamicColorPalette.getColor(context, ACCENT),
|
||||
PorterDuff.Mode.SRC_IN
|
||||
).let { colorFilter ->
|
||||
iconFingerprint.drawable.colorFilter = colorFilter
|
||||
iconDeviceLocked.drawable.colorFilter = colorFilter
|
||||
iconTrashCan.drawable.colorFilter = colorFilter
|
||||
iconInfo.drawable.colorFilter = colorFilter
|
||||
iconShield.drawable.colorFilter = colorFilter
|
||||
iconLink.drawable.colorFilter = colorFilter
|
||||
}
|
||||
|
||||
view.findViewById<TextView>(R.id.footer_learn_more)!!.let { learnMore ->
|
||||
learnMore.movementMethod = LinkMovementMethod.getInstance()
|
||||
val footerLinkStr: String = context.getString(
|
||||
R.string.security_settings_fingerprint_v2_enroll_introduction_message_learn_more,
|
||||
Html.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
learnMore.text = Html.fromHtml(footerLinkStr)
|
||||
}
|
||||
|
||||
if (canAssumeUdfps) {
|
||||
footerMessage6.visibility = View.VISIBLE
|
||||
iconShield.visibility = View.VISIBLE
|
||||
} else {
|
||||
footerMessage6.visibility = View.GONE
|
||||
iconShield.visibility = View.GONE
|
||||
}
|
||||
val glifLayoutHelper = GlifLayoutHelper(this, view)
|
||||
if (isBiometricUnlockDisabledByAdmin && !isParentalConsentRequired) {
|
||||
glifLayoutHelper.setHeaderText(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_title_unlock_disabled
|
||||
)
|
||||
glifLayoutHelper.setDescriptionText(descriptionDisabledByAdminSupplier.get())
|
||||
} else {
|
||||
glifLayoutHelper.setHeaderText(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_title
|
||||
)
|
||||
glifLayoutHelper.setDescriptionText(
|
||||
getString(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_v3_message,
|
||||
DeviceHelper.getDeviceName(context)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user