1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.settings.biometrics.face; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.content.res.ResourceId; 23 import android.hardware.biometrics.SensorProperties; 24 import android.hardware.face.FaceManager; 25 import android.hardware.face.FaceSensorPropertiesInternal; 26 import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; 27 import android.util.Log; 28 import android.view.View; 29 30 import androidx.annotation.NonNull; 31 import androidx.preference.Preference; 32 import androidx.preference.PreferenceScreen; 33 34 import com.android.settings.R; 35 import com.android.settings.Utils; 36 import com.android.settings.core.BasePreferenceController; 37 import com.android.settings.overlay.FeatureFactory; 38 import com.android.settings.utils.AnnotationSpan; 39 import com.android.settingslib.HelpUtils; 40 import com.android.settingslib.widget.FooterPreference; 41 42 import java.util.List; 43 44 /** 45 * Footer for face settings showing the help text and help link. 46 */ 47 public class FaceSettingsFooterPreferenceController extends BasePreferenceController { 48 private static final String KEY = "security_face_footer"; 49 private static final String TAG = "FaceSettingsFooterPreferenceController"; 50 private static final String ANNOTATION_URL = "url"; 51 private final FaceFeatureProvider mProvider; 52 private Preference mPreference; 53 private boolean mIsFaceStrong; 54 private int mUserId; 55 FaceSettingsFooterPreferenceController(@onNull Context context)56 public FaceSettingsFooterPreferenceController(@NonNull Context context) { 57 this(context, KEY); 58 } FaceSettingsFooterPreferenceController(Context context, String preferenceKey)59 public FaceSettingsFooterPreferenceController(Context context, String preferenceKey) { 60 super(context, preferenceKey); 61 mProvider = FeatureFactory.getFeatureFactory().getFaceFeatureProvider(); 62 } 63 64 @Override displayPreference(PreferenceScreen screen)65 public void displayPreference(PreferenceScreen screen) { 66 super.displayPreference(screen); 67 mPreference = screen.findPreference(mPreferenceKey); 68 if (screen.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) { 69 addAuthenticatorsRegisteredCallback(screen.getContext()); 70 } else { 71 Log.w(TAG, "Not support FEATURE_FACE"); 72 } 73 } 74 75 @Override getAvailabilityStatus()76 public int getAvailabilityStatus() { 77 return AVAILABLE_UNSEARCHABLE; 78 } 79 80 @Override updateState(Preference preference)81 public void updateState(Preference preference) { 82 super.updateState(preference); 83 84 final Intent helpIntent = HelpUtils.getHelpIntent( 85 mContext, mContext.getString(R.string.help_url_face), getClass().getName()); 86 final AnnotationSpan.LinkInfo linkInfo = 87 new AnnotationSpan.LinkInfo(mContext, ANNOTATION_URL, helpIntent); 88 final FaceSettingsFeatureProvider featureProvider = FeatureFactory.getFeatureFactory() 89 .getFaceFeatureProvider().getFaceSettingsFeatureProvider(); 90 final int footerRes; 91 boolean isAttentionSupported = mProvider.isAttentionSupported(mContext); 92 if (Utils.isPrivateProfile(mUserId, mContext)) { 93 footerRes = R.string.private_space_face_settings_footer; 94 } else if (mIsFaceStrong) { 95 footerRes = isAttentionSupported 96 ? featureProvider.getSettingPageFooterDescriptionClass3() 97 : R.string.security_settings_face_settings_footer_attention_not_supported; 98 } else { 99 footerRes = isAttentionSupported 100 ? R.string.security_settings_face_settings_footer 101 : R.string.security_settings_face_settings_footer_class3_attention_not_supported; 102 } 103 preference.setTitle(AnnotationSpan.linkify( 104 mContext.getText(footerRes), linkInfo)); 105 106 final int learnMoreRes = featureProvider.getSettingPageFooterLearnMoreDescription(); 107 final int learnMoreUrlRes = featureProvider.getSettingPageFooterLearnMoreUrl(); 108 if (ResourceId.isValid(learnMoreRes) 109 && ResourceId.isValid(learnMoreUrlRes) 110 && preference instanceof FooterPreference) { 111 final Intent learnMoreIntent = HelpUtils.getHelpIntent( 112 mContext, mContext.getString(learnMoreUrlRes), getClass().getName()); 113 final View.OnClickListener learnMoreClickListener = (v) -> { 114 mContext.startActivityForResult(KEY, learnMoreIntent, 0, null); 115 }; 116 ((FooterPreference) preference).setLearnMoreAction(learnMoreClickListener); 117 ((FooterPreference) preference).setLearnMoreText(mContext.getString(learnMoreRes)); 118 } 119 } 120 setUserId(int userId)121 public void setUserId(int userId) { 122 mUserId = userId; 123 } 124 addAuthenticatorsRegisteredCallback(Context context)125 private void addAuthenticatorsRegisteredCallback(Context context) { 126 final FaceManager faceManager = context.getSystemService(FaceManager.class); 127 faceManager.addAuthenticatorsRegisteredCallback( 128 new IFaceAuthenticatorsRegisteredCallback.Stub() { 129 @Override 130 public void onAllAuthenticatorsRegistered( 131 @NonNull List<FaceSensorPropertiesInternal> sensors) { 132 if (sensors.isEmpty()) { 133 Log.e(TAG, "No sensors"); 134 return; 135 } 136 137 boolean isFaceStrong = sensors.get(0).sensorStrength 138 == SensorProperties.STRENGTH_STRONG; 139 if (mIsFaceStrong == isFaceStrong) { 140 return; 141 } 142 mIsFaceStrong = isFaceStrong; 143 updateState(mPreference); 144 } 145 }); 146 } 147 } 148