1.简介
- 主要学习下screen lock 页面的逻辑,lock方式的切换,验证逻辑
- 看下密码相关的数据获取以及存储逻辑
<com.android.settings.widget.HomepagePreference
android:fragment="com.android.settings.security.SecuritySettings"
android:icon="@drawable/ic_settings_security_white"
android:key="top_level_security"
android:order="-50"
android:title="@string/security_settings_title"
android:summary="@string/security_dashboard_summary"
settings:highlightableMenuKey="@string/menu_key_security"
settings:controller="com.android.settings.security.TopLevelSecurityEntryPreferenceController"/>
1.1.图片
2.SecuritySettings
2.1.security_dashboard_settings.xml
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="security_dashboard_page"
android:title="@string/security_settings_title">
<!-- security_settings_status.xml -->
<PreferenceCategory
android:order="-10"
android:key="security_status"
android:title="@string/security_status_title" />
<PreferenceCategory
android:order="1"
android:key="dashboard_tile_placeholder" />
<!-- security section 里边有4种,后3种根据设备是否支持来决定显示与否-->
<PreferenceCategory
android:order="10"
android:key="security_category"
android:title="@string/lock_settings_title">
<!--常见的上划,密码,PIN码,图案等-->
<com.android.settings.widget.GearPreference
android:key="unlock_set_or_change"
android:title="@string/unlock_set_unlock_launch_picker_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_lockscreen" />
<!--指纹识别-->
<com.android.settingslib.RestrictedPreference
android:key="fingerprint_settings"
android:title="@string/security_settings_fingerprint_preference_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_fingerprint_settings" />
<!--人脸识别-->
<com.android.settingslib.RestrictedPreference
android:key="face_settings"
android:title="@string/security_settings_face_preference_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_face_settings" />
<!--生物识别,包括指纹和人脸-->
<com.android.settingslib.RestrictedPreference
android:key="biometric_settings"
android:title="@string/security_settings_biometric_preference_title"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_biometric_settings" />
</PreferenceCategory>
<!--更多安全设置-->
<Preference
android:order="100"
android:key="security_advanced_settings"
android:title="@string/security_advanced_settings"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.security.SecurityAdvancedSettings"
settings:controller="com.android.settings.security.SecurityAdvancedSettingsController"
settings:keywords="@string/security_advanced_settings_keywords" />
</PreferenceScreen>
2.2.buildPreferenceControllers
控制器都在这里了,我们只研究下默认的
private static List<AbstractPreferenceController> buildPreferenceControllers
(Context context,
Lifecycle lifecycle, SecuritySettings host) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
//这是4种安全锁对应的controller
final List<AbstractPreferenceController> securityPreferenceControllers = new ArrayList<>();
//人脸识别的
securityPreferenceControllers.add(new FaceStatusPreferenceController(context, lifecycle));
//指纹识别的
securityPreferenceControllers.add(new FingerprintStatusPreferenceController(
context, lifecycle));
//生物识别的
securityPreferenceControllers.add(new CombinedBiometricStatusPreferenceController(
context, lifecycle));
//默认的,具体见小节3
securityPreferenceControllers.add(new ChangeScreenLockPreferenceController(context, host));
//这是4种锁外边的容器security_category的控制器
controllers.add(new PreferenceCategoryController(context, SECURITY_CATEGORY)
.setChildren(securityPreferenceControllers));
controllers.addAll(securityPreferenceControllers);
return controllers;
}
3.ChangeScreenLockPreferenceController
这个控制器控制的就是下图这个选项的内容,完整的页面图见小节2
- none或者swipe的时候显示如下,没有齿轮
- password,pin, pattern的时候显示如下,带齿轮:
3.1.isAvailable
控制选项是否可用,默认是true
public boolean isAvailable() {
return mScreenLockPreferenceDetailUtils.isAvailable();//见 4.1
}
3.2.updateState
是否显示齿轮菜单,就是下图这个,非swipe或者none的时候会显示
public void updateState(Preference preference) {
if (mPreference != null && mPreference instanceof GearPreference) {
//见4.2,根据lock类型决定是否需要显示齿轮按钮
if (mScreenLockPreferenceDetailUtils.shouldShowGearMenu()) {
//需要显示齿轮菜单,给齿轮设置点击事件跳转,listener不为空,齿轮显示
((GearPreference) mPreference).setOnGearClickListener(this);//点击事件见补充1
} else {
//listener为null,齿轮隐藏
((GearPreference) mPreference).setOnGearClickListener(null);
}
}
//见补充2,获取摘要
updateSummary(preference, mUserId);
disableIfPasswordQualityManaged(mUserId);
if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) {
disableIfPasswordQualityManaged(mProfileChallengeUserId);
}
}
>1.onGearClick
齿轮点击跳转的逻辑,工具类处理的,见4.3
public void onGearClick(GearPreference p) {
if (TextUtils.equals(p.getKey(), getPreferenceKey())) {
//见4.3
mScreenLockPreferenceDetailUtils.openScreenLockSettings(mHost.getMetricsCategory());
}
}
>2.updateSummary
protected void updateSummary(Preference preference, int userId) {
preference.setSummary(mScreenLockPreferenceDetailUtils.getSummary(userId));//见4.4
mPreference.setEnabled(true);
}
3.3.handlePreferenceTreeClick
这个是整个选项点击后的跳转逻辑
public boolean handlePreferenceTreeClick(Preference preference) {
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return super.handlePreferenceTreeClick(preference);
}
//见4.5,最终跳转的页面是小节8
return mScreenLockPreferenceDetailUtils.openChooseLockGenericFragment(
mHost.getMetricsCategory());
}
4.ScreenLockPreferenceDetailsUtils
4.1.isAvailable
默认是true
public boolean isAvailable() {
return mContext.getResources().getBoolean(R.bool.config_show_unlock_set_or_change);
}
4.2.shouldShowGearMenu
是否应该显示齿轮按钮,none或者swipe不显示,其他的比如password,pin,pattern需要显示
public boolean shouldShowGearMenu() {
return isLockPatternSecure();
}
public boolean isLockPatternSecure() {
//见小节5.1
return mLockPatternUtils.isSecure(mUserId);
}
4.3.openScreenLockSettings
齿轮按钮点击跳转到如下的页面
public void openScreenLockSettings(int sourceMetricsCategory) {
mContext.startActivity(getLaunchScreenLockSettingsIntent(sourceMetricsCategory));
}
>1.getLaunchScreenLockSettingsIntent
public Intent getLaunchScreenLockSettingsIntent(int sourceMetricsCategory) {
return new SubSettingLauncher(mContext)
.setDestination(ScreenLockSettings.class.getName())
.setSourceMetricsCategory(sourceMetricsCategory)
.toIntent();
}
4.4.getSummary
public String getSummary(int userId) {
//见补充1
final Integer summaryResId = getSummaryResId(userId);
return summaryResId != null ? mContext.getResources().getString(summaryResId) : null;
}
>1.getSummaryResId
根据当前的锁屏类型,返回对应的摘要字符串id
private Integer getSummaryResId(int userId) {
//非安全模式,也就是none或者swipe
if (!mLockPatternUtils.isSecure(userId)) {
if (userId == mProfileChallengeUserId
//见5.7
|| mLockPatternUtils.isLockScreenDisabled(userId)) {
return R.string.unlock_set_unlock_mode_off; //none
} else {
return R.string.unlock_set_unlock_mode_none;//swipe
}
} else {
//见5.10
int keyguardStoredPasswordQuality =
mLockPatternUtils.getKeyguardStoredPasswordQuality(userId);
switch (keyguardStoredPasswordQuality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
return R.string.unlock_set_unlock_mode_pattern;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
return R.string.unlock_set_unlock_mode_pin;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
return R.string.unlock_set_unlock_mode_password;
default:
return null;
}
}
}
4.5.openChooseLockGenericFragment
选项点击跳转如下页面
public boolean openChooseLockGenericFragment(int sourceMetricsCategory) {
final Intent quietModeDialogIntent = getQuietModeDialogIntent();
if (quietModeDialogIntent != null) {
mContext.startActivity(quietModeDialogIntent);
return false;
}
//正常走这里,intent见补充2
mContext.startActivity(getChooseLockGenericFragmentIntent(sourceMetricsCategory));
return true;
}
>1.getQuietModeDialogIntent
正常返回空
private Intent getQuietModeDialogIntent() {
if (mProfileChallengeUserId != UserHandle.USER_NULL
&& !mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)
&& StorageManager.isFileEncryptedNativeOnly()) {
if (mUm.isQuietModeEnabled(UserHandle.of(mProfileChallengeUserId))) {
return UnlaunchableAppActivity.createInQuietModeDialogIntent(
mProfileChallengeUserId);
}
}
return null;
}
>2.getChooseLockGenericFragmentIntent
跳转页面ChooseLockGenericFragment,见小节8
private Intent getChooseLockGenericFragmentIntent(int sourceMetricsCategory) {
return new SubSettingLauncher(mContext)
.setDestination(ChooseLockGenericFragment.class.getName())
.setSourceMetricsCategory(sourceMetricsCategory)
.setTransitionType(SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE)
.toIntent();
}
5.LockPatternUtils.java
5.1.isSecure
凭据类型不是none(也就是设置了Pattern,PIN或者password),那么就说明设置了凭据
public boolean isSecure(int userId) {
int type = getCredentialTypeForUser(userId);
return type != CREDENTIAL_TYPE_NONE;
}
5.2.getCredentialTypeForUser
获取凭据的类型
public @CredentialType int getCredentialTypeForUser(int userHandle) {
//见5.3
return mCredentialTypeCache.query(userHandle);
}
>1.CredentialType
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = {
CREDENTIAL_TYPE_NONE, //-1
CREDENTIAL_TYPE_PATTERN, //1
CREDENTIAL_TYPE_PASSWORD, //4
CREDENTIAL_TYPE_PIN, //3
// CREDENTIAL_TYPE_PASSWORD_OR_PIN is missing on purpose.
})
public @interface CredentialType {}
5.3.mCredentialTypeCache
private final static String CREDENTIAL_TYPE_API = "getCredentialType";
/**
* Special user id for triggering the FRP verification flow.
*/
public static final int USER_FRP = UserHandle.USER_NULL + 1;//-10000+1
private final PropertyInvalidatedCache<Integer, Integer> mCredentialTypeCache =
new PropertyInvalidatedCache<>(4, PropertyInvalidatedCache.MODULE_SYSTEM,
CREDENTIAL_TYPE_API, CREDENTIAL_TYPE_API, mCredentialTypeQuery);
//查询方法就是这个
private final PropertyInvalidatedCache.QueryHandler<Integer, Integer> mCredentialTypeQuery =
new PropertyInvalidatedCache.QueryHandler<>() {
@Override
public Integer apply(Integer userHandle) {
try {
//见5.4
return getLockSettings().getCredentialType(userHandle);
} catch (RemoteException re) {
return CREDENTIAL_TYPE_NONE;
}
}
@Override
public boolean shouldBypassCache(Integer userHandle) {
//返回ture表示绕过缓存
return userHandle == USER_FRP;
}
};
//
public ILockSettings getLockSettings() {
if (mLockSettingsService == null) {
//见5.4
ILockSettings service = ILockSettings.Stub.asInterface(
ServiceManager.getService("lock_settings"));
mLockSettingsService = service;
}
return mLockSettingsService;
}
5.4.LockSettingsService.java
public int getCredentialType(int userId) {
checkPasswordHavePermission(userId);
return getCredentialTypeInternal(userId);
}
public int getCredentialTypeInternal(int userId) {
if (userId == USER_FRP) {
return getFrpCredentialType();
}
synchronized (mSpManager) {
//见补充1,读取数据库,看有没有对应的handle
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
//获取handle,数据库里的值
final long handle = getSyntheticPasswordHandleLocked(userId);
//见小节7.1,根据handle读取对应的文件,解析内容返回type
int rawType = mSpManager.getCredentialType(handle, userId);
if (rawType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
return rawType;
}
//CREDENTIAL_TYPE_PASSWORD_OR_PIN 这种是遗留的,所以特殊处理下
//见补充2和3
return pinOrPasswordQualityToCredentialType(getKeyguardStoredQuality(userId));
}
}
// Intentional duplication of the getKeyguardStoredQuality() call above since this is a
// unlikely code path (device with pre-synthetic password credential). We want to skip
// calling getKeyguardStoredQuality whenever possible.
//补充2
final int savedQuality = getKeyguardStoredQuality(userId);
if (savedQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING //0x10000;
//见6.3
&& mStorage.hasPattern(userId)) {
return CREDENTIAL_TYPE_PATTERN;
}
if (savedQuality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC //0x20000;
&& mStorage.hasPassword(userId)) {
//见补充3
return pinOrPasswordQualityToCredentialType(savedQuality);
}
return CREDENTIAL_TYPE_NONE;
}
>1.isSyntheticPasswordBasedCredentialLocked
private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
if (userId == USER_FRP) {
final int type = mStorage.readPersistentDataBlock().type;
return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER;
}
long handle = getSyntheticPasswordHandleLocked(userId);
return handle != SyntheticPasswordManager.DEFAULT_HANDLE;
}
//具体就是6.2里的数据库
long getSyntheticPasswordHandleLocked(int userId) {
return getLong(SYNTHETIC_PASSWORD_HANDLE_KEY,
SyntheticPasswordManager.DEFAULT_HANDLE, userId);
}
>2.getKeyguardStoredQuality
最终读取的是6.2里的数据库里的值
private int getKeyguardStoredQuality(int userId) {
return (int) mStorage.getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
}
>3.pinOrPasswordQualityToCredentialType
private static int pinOrPasswordQualityToCredentialType(int quality) {
//见5.5
if (LockPatternUtils.isQualityAlphabeticPassword(quality)) {
return CREDENTIAL_TYPE_PASSWORD;
}
//见5.6
if (LockPatternUtils.isQualityNumericPin(quality)) {
return CREDENTIAL_TYPE_PIN;
}
throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality);
}
5.5.isQualityAlphabeticPassword
public static boolean isQualityAlphabeticPassword(int quality) {
return quality >= PASSWORD_QUALITY_ALPHABETIC;//0x40000;
}
5.6.isQualityNumericPin
public static boolean isQualityNumericPin(int quality) {
//0x20000; 0x30000;
return quality == PASSWORD_QUALITY_NUMERIC || quality == PASSWORD_QUALITY_NUMERIC_COMPLEX;
}
5.7.isLockScreenDisabled
public boolean isLockScreenDisabled(int userId) {
if (isSecure(userId)) {
//安全模式下肯定是false了
return false;
}
boolean disabledByDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_disableLockscreenByDefault);
boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
UserInfo userInfo = getUserManager().getUserInfo(userId);
boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null
&& userInfo.isDemo();
//1.读取 DISABLE_LOCKSCREEN_KEY 的值,这个是数据库里的
//2.配置里默认disable为true并且非系统用户
//3.测试用户
return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
|| (disabledByDefault && !isSystemUser)
|| isDemoUser;
}
>1.disabledByDefault
新用户是否默认禁止掉锁屏,默认值false
<!-- Is the lock-screen disabled for new users by default -->
<bool name="config_disableLockscreenByDefault">false</bool>
5.8.hasSecureLockScreen
public boolean hasSecureLockScreen() {
if (mHasSecureLockScreen == null) {
try {
mHasSecureLockScreen = Boolean.valueOf(getLockSettings().hasSecureLockScreen());
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
return mHasSecureLockScreen.booleanValue();
}
其实最终读取的是LockSettingsService里的值,看是否有对应的feature
mHasSecureLockScreen = mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN);
5.9.setLockScreenDisabled
这个最终是写到数据库里的,就是5.7里用的
public void setLockScreenDisabled(boolean disable, int userId) {
setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);
}
5.10.getKeyguardStoredPasswordQuality
public int getKeyguardStoredPasswordQuality(int userHandle) {
//type获取见5.2
return credentialTypeToPasswordQuality(getCredentialTypeForUser(userHandle));
}
>1.credentialTypeToPasswordQuality
凭据类型转化为quality值
public static int credentialTypeToPasswordQuality(int credentialType) {
switch (credentialType) {
case CREDENTIAL_TYPE_NONE:
return PASSWORD_QUALITY_UNSPECIFIED;
case CREDENTIAL_TYPE_PATTERN:
return PASSWORD_QUALITY_SOMETHING;
case CREDENTIAL_TYPE_PIN:
return PASSWORD_QUALITY_NUMERIC;
case CREDENTIAL_TYPE_PASSWORD:
return PASSWORD_QUALITY_ALPHABETIC;
default:
throw new IllegalStateException("Unknown type: " + credentialType);
}
}
5.11.isCredentialsDisabledForUser
是否允许用户通过PASSWORD_QUALITY_MANAGED设置任何凭据
public boolean isCredentialsDisabledForUser(int userId) {
return getDevicePolicyManager().getPasswordQuality(/* admin= */ null, userId)
== PASSWORD_QUALITY_MANAGED;
}
6.LockSettingsStorage.java
6.1.readSyntheticPasswordState
public byte[] readSyntheticPasswordState(int userId, long handle, String name) {
return readFile(getSynthenticPasswordStateFilePathForUser(userId, handle, name));
}
>1.getSynthenticPasswordStateFilePathForUser
protected String getSynthenticPasswordStateFilePathForUser(int userId, long handle,
String name) {
//目录见补充2
final File baseDir = getSyntheticPasswordDirectoryForUser(userId);
//文件名字就是handle的十六进制加上点name
final String baseName = formatSimple("%016x.%s", handle, name);
return new File(baseDir, baseName).getAbsolutePath();
}
>2.getSyntheticPasswordDirectoryForUser
返回目录 /data/system_de/0/spblob/
private static final String SYNTHETIC_PASSWORD_DIRECTORY = "spblob/";
protected File getSyntheticPasswordDirectoryForUser(int userId) {
return new File(Environment.getDataSystemDeDirectory(userId) ,SYNTHETIC_PASSWORD_DIRECTORY);
}
存储目录/data/system_de/0/
public static File getDataSystemDeDirectory(int userId) {
return buildPath(getDataDirectory(), "system_de", String.valueOf(userId));
}
6.2.数据库
数据是从数据库里读出来的
private static final String DATABASE_NAME = "locksettings.db";
private static final String TABLE = "locksettings";
private static final String COLUMN_KEY = "name";
private static final String COLUMN_USERID = "user";
private static final String COLUMN_VALUE = "value";
//存储表信息如下
private void createTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE + " (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
COLUMN_KEY + " TEXT," +
COLUMN_USERID + " INTEGER," +
COLUMN_VALUE + " TEXT" +
");");
}
//这是读取数据的代码,根据user以及key查询value
Object result = DEFAULT;
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
new String[] { Integer.toString(userId), key },
null, null, null)) != null) {
if (cursor.moveToFirst()) {
result = cursor.getString(0);
}
cursor.close();
}
6.3.hasPassword
获取补充2里的路径下的gatekeeper.password.key文件内容是否为空
public boolean hasPassword(int userId) {
return hasFile(getLockPasswordFilename(userId));
}
>1.getLockPasswordFilename
private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key文件内容是否为空";
String getLockPasswordFilename(int userId) {
return getLockCredentialFilePathForUser(userId, LOCK_PASSWORD_FILE);
}
>2.getLockCredentialFilePathForUser
- userid是0 路径是: /data/system/0
- userid不是0,路径是: /data/system/users/xxx
private static final String SYSTEM_DIRECTORY = "/system/";
private String getLockCredentialFilePathForUser(int userId, String basename) {
String dataSystemDirectory = Environment.getDataDirectory().getAbsolutePath() +
SYSTEM_DIRECTORY;
if (userId == 0) {
// Leave it in the same place for user 0
return dataSystemDirectory + basename;
} else {
return new File(Environment.getUserSystemDirectory(userId), basename).getAbsolutePath();
}
}
7.SyntheticPasswordManager.java
7.1.getCredentialType
private static final String PASSWORD_DATA_NAME = "pwd";
int getCredentialType(long handle, int userId) {
//见7.2,从文件读取数据,handle决定了文件的名字
byte[] passwordData = loadState(PASSWORD_DATA_NAME, handle, userId);
if (passwordData == null) {
return LockPatternUtils.CREDENTIAL_TYPE_NONE;
}
//解析读取的byte数组,封装成对象,获取type返回
return PasswordData.fromBytes(passwordData).credentialType;
}
7.2.loadState
private byte[] loadState(String stateName, long handle, int userId) {
//见6.1
return mStorage.readSyntheticPasswordState(userId, handle, stateName);
}
8.ChooseLockGenericFragment
public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
8.1.security_settings_picker.xml
根据条件显示不同的选项
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="lock_settings_picker">
<!--正常进来显示下边5个选项-->
<com.android.settingslib.RestrictedPreference
android:key="unlock_set_off"
android:title="@string/unlock_set_unlock_off_title"
android:icon="@drawable/ic_lock_none"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_set_none"
android:title="@string/unlock_set_unlock_none_title"
android:icon="@drawable/ic_lock_swipe"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_set_pattern"
android:title="@string/unlock_set_unlock_pattern_title"
android:icon="@drawable/ic_pattern"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_set_pin"
android:title="@string/unlock_set_unlock_pin_title"
android:icon="@drawable/ic_lock_pin"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_set_password"
android:title="@string/unlock_set_unlock_password_title"
android:icon="@drawable/ic_password"
android:persistent="false"/>
<!--下边是其他情况显示-->
<com.android.settingslib.RestrictedPreference
android:key="unlock_set_managed"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_skip_fingerprint"
android:title="@string/fingerprint_unlock_skip_fingerprint"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_skip_face"
android:title="@string/face_unlock_skip_face"
android:persistent="false"/>
<com.android.settingslib.RestrictedPreference
android:key="unlock_skip_biometrics"
android:title="@string/biometrics_unlock_skip_biometrics"
android:persistent="false"/>
<com.android.settingslib.widget.FooterPreference
android:key="lock_settings_footer"
android:selectable="false"
settings:searchable="false"/>
</PreferenceScreen>
8.2.onCreate
public void onCreate(Bundle savedInstanceState) {
//省略中间读值的逻辑
//controller后边用
mController = new ChooseLockGenericController.Builder(
getContext(), mUserId, mLockPatternUtils)
.setAppRequestedMinComplexity(mRequestedMinComplexity)
.setEnforceDevicePasswordRequirementOnly(mOnlyEnforceDevicePasswordRequirement)
.setProfileToUnify(mUnificationProfileId)
.setHideInsecureScreenLockTypes(alwaysHideInsecureScreenLockTypes()
|| intent.getBooleanExtra(HIDE_INSECURE_OPTIONS, false))
.build();
//...
if (mPasswordConfirmed) {
//强制要求密码的走这里
updatePreferencesOrFinish(savedInstanceState != null);
if (mForChangeCredRequiredForBoot) {
maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
mUserId), false);
}
} else if (!mWaitingForConfirmation) {
//正常走这里
final ChooseLockSettingsHelper.Builder builder =
new ChooseLockSettingsHelper.Builder(activity, this);
//questCode
builder.setRequestCode(CONFIRM_EXISTING_REQUEST)
.setTitle(getString(R.string.unlock_set_unlock_launch_picker_title))
.setReturnCredentials(true)
.setUserId(mUserId);
boolean managedProfileWithUnifiedLock =
mIsManagedProfile
&& !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
//不管这个,这个是管理类的程序控制的
boolean skipConfirmation = managedProfileWithUnifiedLock && !mIsSetNewPassword;
//比如设置了图案或者密码,那么正常会跳转到解锁密码或者图案页面,也就是下边的builder.show方法
//show方法返回true表示进入了密码输入页面,返回false表示未进入密码页面,见9.1
if (skipConfirmation || !builder.show()) {
//走到这里说明没有密码或者不需要输入密码,显示正常的页面
mPasswordConfirmed = true; // no password set, so no need to confirm
//见8.4
updatePreferencesOrFinish(savedInstanceState != null);
} else {
mWaitingForConfirmation = true;
}
}
addHeaderView();
}
8.3.onActivityResult
见9.3最后调用的这个fragment的startActivityForResult,这里就是回调
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mWaitingForConfirmation = false;
//requestCode见8.2 builder.setRequestCode方法
if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
//这里对应9.2从密码确认页面回来,
mPasswordConfirmed = true;
mUserPassword = data != null
? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
: null;
//见8.4
updatePreferencesOrFinish(false /* isRecreatingActivity */);
if (mForChangeCredRequiredForBoot) {
if (mUserPassword != null && !mUserPassword.isNone()) {
maybeEnableEncryption(
mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
} else {
finish();
}
}
8.4.updatePreferencesOrFinish
更新选项或者关闭页面
void updatePreferencesOrFinish(boolean isRecreatingActivity) {
Intent intent = getActivity().getIntent();
int quality = -1;
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
}
if (quality == -1) {
// If caller didn't specify password quality, show UI and allow the user to choose.
final PreferenceScreen prefScreen = getPreferenceScreen();
if (prefScreen != null) {
prefScreen.removeAll();
}
addPreferences();//见补充1
disableUnusablePreferences();//补充2
updatePreferenceText();//补充4
updateCurrentPreference();//补充5
} else if (!isRecreatingActivity) {
// Don't start the activity again if we are recreated for configuration change
updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
}
}
>1.addPreferences
添加要显示的选项
protected void addPreferences() {
//从xml里获取
addPreferencesFromResource(R.xml.security_settings_picker);
int profileUserId = Utils.getManagedProfileId(mUserManager, mUserId);
final FooterPreference footer = findPreference(KEY_LOCK_SETTINGS_FOOTER);
if (!TextUtils.isEmpty(mCallerAppName) && !mIsCallingAppAdmin) {
footer.setVisible(true);
footer.setTitle(getFooterString());
} else if (!mForFace && !mForBiometrics && !mForFingerprint && !mIsManagedProfile
&& mController.isScreenLockRestrictedByAdmin()
&& profileUserId != UserHandle.USER_NULL) {
final StringBuilder description = new StringBuilder(
mDpm.getResources().getString(
WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK,
() -> getString(
R.string.lock_settings_picker_admin_restricted_personal_message)));
footer.setVisible(true);
footer.setTitle(description);
final StringBuilder setLockText = new StringBuilder(
mDpm.getResources().getString(
WORK_PROFILE_IT_ADMIN_CANT_RESET_SCREEN_LOCK_ACTION,
() -> getString(
R.string.lock_settings_picker_admin_restricted_personal_message_action)));
View.OnClickListener setLockClickListener = (v) -> {
final Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_USER_ID, profileUserId);
if (mUserPassword != null) {
extras.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
mUserPassword);
}
new SubSettingLauncher(getActivity())
.setDestination(ChooseLockGenericFragment.class.getName())
.setSourceMetricsCategory(getMetricsCategory())
.setArguments(extras)
.launch();
finish();
};
footer.setLearnMoreText(setLockText);
footer.setLearnMoreAction(setLockClickListener);
} else {
footer.setVisible(false);
}
// Used for testing purposes
findPreference(ScreenLockType.NONE.preferenceKey).setViewId(R.id.lock_none);
findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
findPreference(KEY_SKIP_FACE).setViewId(R.id.lock_none);
findPreference(KEY_SKIP_BIOMETRICS).setViewId(R.id.lock_none);
findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
}
>2.disableUnusablePreferences
处理下锁屏类型那几个是否可以显示,是否可用
private ChooseLockGenericController mController;
private void disableUnusablePreferences () {
final PreferenceScreen entries = getPreferenceScreen();
//循环所有支持的锁屏类型,更新其可见性以及可用性
for (ScreenLockType lock : ScreenLockType.values()) {
String key = lock.preferenceKey;
Preference pref = findPreference(key);
if (pref instanceof RestrictedPreference) {
//见10.1
boolean visible = mController.isScreenLockVisible(lock);
//见10.2
boolean enabled = mController.isScreenLockEnabled(lock);
if (!visible) {
entries.removePreference(pref);
} else if (!enabled) {
pref.setEnabled(false);
}
}
}
}
>3.ScreenLockType
所有的锁屏类型
public enum ScreenLockType {
NONE(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
"unlock_set_off"),
SWIPE(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
"unlock_set_none"),
PATTERN(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
"unlock_set_pattern"),
PIN(
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
"unlock_set_pin"),
PASSWORD(
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
"unlock_set_password"),
MANAGED(
DevicePolicyManager.PASSWORD_QUALITY_MANAGED,
"unlock_set_managed");
>4.updatePreferenceText
如下图,我们点击的face unlock,那么下边的forFace的值就是真的 进去的值如下,就是下边if修改的,不同的来源显示不同的文字
private void updatePreferenceText() {
//下边这几个if,是从对应的锁屏方式点进来的
if (mForFingerprint) {
setPreferenceTitle(ScreenLockType.PATTERN,
R.string.fingerprint_unlock_set_unlock_pattern);
setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
setPreferenceTitle(ScreenLockType.PASSWORD,
R.string.fingerprint_unlock_set_unlock_password);
} else if (mForFace) {
setPreferenceTitle(ScreenLockType.PATTERN,
R.string.face_unlock_set_unlock_pattern);
setPreferenceTitle(ScreenLockType.PIN, R.string.face_unlock_set_unlock_pin);
setPreferenceTitle(ScreenLockType.PASSWORD,
R.string.face_unlock_set_unlock_password);
} else if (mForBiometrics) {
setPreferenceTitle(ScreenLockType.PATTERN,
R.string.biometrics_unlock_set_unlock_pattern);
setPreferenceTitle(ScreenLockType.PIN, R.string.biometrics_unlock_set_unlock_pin);
setPreferenceTitle(ScreenLockType.PASSWORD,
R.string.biometrics_unlock_set_unlock_password);
}
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
setPreferenceTitle(ScreenLockType.MANAGED,
mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
} else {
removePreference(ScreenLockType.MANAGED.preferenceKey);
}
if (!(mForFingerprint && mIsSetNewPassword)) {
removePreference(KEY_SKIP_FINGERPRINT);
}
if (!(mForFace && mIsSetNewPassword)) {
removePreference(KEY_SKIP_FACE);
}
if (!(mForBiometrics && mIsSetNewPassword)) {
removePreference(KEY_SKIP_BIOMETRICS);
}
}
>5.updateCurrentPreference
查下当先设置的是哪种lock,显示summary,如下图
private void updateCurrentPreference() {
String currentKey = getKeyForCurrent();
Preference preference = findPreference(currentKey);
if (preference != null) {
preference.setSummary(R.string.current_screen_lock);
}
}
private String getKeyForCurrent() {
final int credentialOwner = UserManager.get(getContext())
.getCredentialOwnerProfile(mUserId);
if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
return ScreenLockType.NONE.preferenceKey;
}
ScreenLockType lock =
ScreenLockType.fromQuality(
mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
return lock != null ? lock.preferenceKey : null;
}
8.5.onPreferenceTreeClick
看下选项的点击事件
public boolean onPreferenceTreeClick (Preference preference) {
writePreferenceClickMetric(preference);
final String key = preference.getKey();
//点击的是none或者swipe,见补充1,
//当前是secure类型(密码,pin,pattern),见5.1
if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) {
// 这里需要提示删除旧的数据,见补充2
showFactoryResetProtectionWarningDialog(key);
return true;
} else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)
|| KEY_SKIP_BIOMETRICS.equals(key)) {
//点击的是跳过指纹,人脸识别,生物识别,见补充4,其实加载的还是这个fragment
Intent chooseLockGenericIntent = new Intent(getActivity(),
getInternalActivityClass());
chooseLockGenericIntent.setAction(getIntent().getAction());
// Forward the target user id to ChooseLockGeneric.
chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed);
chooseLockGenericIntent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY,
mRequestedMinComplexity);
chooseLockGenericIntent.putExtra(EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY,
mOnlyEnforceDevicePasswordRequirement);
chooseLockGenericIntent.putExtra(EXTRA_KEY_CALLER_APP_NAME, mCallerAppName);
if (mUserPassword != null) {
chooseLockGenericIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
mUserPassword);
}
startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
return true;
} else {
//点击的是 pattern,pin,或者password选项
return setUnlockMethod(key);//补充3,
}
}
>1.isUnlockMethodSecure
如果key不是none或者swipe,返回true,否则返回false
private boolean isUnlockMethodSecure(String unlockMethod) {
return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
}
>2.showFactoryResetProtectionWarningDialog
清除密码确认框,这里的参数是NONE或者SWIPE
private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
int title = getResIdForFactoryResetProtectionWarningTitle();
int message = getResIdForFactoryResetProtectionWarningMessage();
FactoryResetProtectionWarningDialog dialog =
FactoryResetProtectionWarningDialog.newInstance(
title, message, unlockMethodToSet);
dialog.show(getChildFragmentManager(), TAG_FRP_WARNING_DIALOG);
}
dialog的确认按钮事件如下
.setPositiveButton(R.string.unlock_disable_frp_warning_ok,
(dialog, whichButton) -> {
String unlockMethod = args.getString(ARG_UNLOCK_METHOD_TO_SET);
((ChooseLockGenericFragment) getParentFragment())
.setUnlockMethod(unlockMethod);//见补充3
})
>3.setUnlockMethod
private boolean setUnlockMethod(String unlockMethod) {
ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
if (lock != null) {
switch (lock) {
case NONE:
case SWIPE:
//前两种,直接修改关闭页面,见8.6
updateUnlockMethodAndFinish(
lock.defaultQuality,
lock == ScreenLockType.NONE,
false /* chooseLockSkipped */);
return true;
case PATTERN:
case PIN:
case PASSWORD:
case MANAGED:
//跳转到对应的设置页面,见8.7
maybeEnableEncryption(lock.defaultQuality, false);
return true;
}
}
return false;
}
>4.getInternalActivityClass
protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() {
return ChooseLockGeneric.InternalActivity.class;
}
8.6.updateUnlockMethodAndFinish
void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
quality = mController.upgradeQuality(quality);
//见补充1
Intent intent = getIntentForUnlockMethod(quality);
if (intent != null) {
//非none或swipe的走这里
if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
}
intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
// If the caller requested Gatekeeper Password Handle to be returned, we assume it
// came from biometric enrollment. onActivityResult will put the LockSettingsService
// into the extras and launch biometric enrollment. This should be cleaned up,
// since requesting a Gatekeeper Password Handle should not imply it came from
// biometric setup/settings.
startActivityForResult(intent,
mIsSetNewPassword && mRequestGatekeeperPasswordHandle
? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
: CHOOSE_LOCK_REQUEST);
return;
}
//8.5.3里的none或者swipe走这里
if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
//有旧密码的清除旧密码数据
//密码来源见8.3,有密码的情况进入此页会先要求输入密码,8.3回调里会记录获取的密码
if (mUserPassword != null) {
mLockPatternUtils.setLockCredential(
LockscreenCredential.createNone(), mUserPassword, mUserId);
}
//none的话disable为true,swipe的话disable为false
mLockPatternUtils.setLockScreenDisabled(disabled, mUserId);
getActivity().setResult(Activity.RESULT_OK);
LockScreenSafetySource.onLockScreenChange(getContext());
finish();
}
}
>1.getIntentForUnlockMethod
根据给定的quality获取对应的intent或者空,比如none或者swipe类型的就是空
private Intent getIntentForUnlockMethod(int quality) {
Intent intent = null;
if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
intent = getLockManagedPasswordIntent(mUserPassword);
} else if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
intent = getLockPasswordIntent(quality);//见补充2
} else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
intent = getLockPatternIntent();//见补充3
}
return intent;
}
>2.getLockPasswordIntent
password或者pin设置页面,ChooseLockPassword
protected Intent getLockPasswordIntent(int quality) {
ChooseLockPassword.IntentBuilder builder =
new ChooseLockPassword.IntentBuilder(getContext())
.setPasswordType(quality)
.setPasswordRequirement(
mController.getAggregatedPasswordComplexity(),
mController.getAggregatedPasswordMetrics())
.setForFingerprint(mForFingerprint)
.setForFace(mForFace)
.setForBiometrics(mForBiometrics)
.setUserId(mUserId)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPasswordHandle);
if (mUserPassword != null) {
builder.setPassword(mUserPassword);
}
if (mUnificationProfileId != UserHandle.USER_NULL) {
builder.setProfileToUnify(mUnificationProfileId, mUnificationProfileCredential);
}
return builder.build();
}
>3.getLockPatternIntent
九宫格设置页面,ChooseLockPattern
protected Intent getLockPatternIntent() {
ChooseLockPattern.IntentBuilder builder =
new ChooseLockPattern.IntentBuilder(getContext())
.setForFingerprint(mForFingerprint)
.setForFace(mForFace)
.setForBiometrics(mForBiometrics)
.setUserId(mUserId)
.setRequestGatekeeperPasswordHandle(mRequestGatekeeperPasswordHandle);
if (mUserPassword != null) {
builder.setPattern(mUserPassword);
}
if (mUnificationProfileId != UserHandle.USER_NULL) {
builder.setProfileToUnify(mUnificationProfileId, mUnificationProfileCredential);
}
return builder.build();
}
8.7.maybeEnableEncryption
private void maybeEnableEncryption(int quality, boolean disabled) {
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
if (UserManager.get(getActivity()).isAdminUser()
&& mUserId == UserHandle.myUserId()
&& LockPatternUtils.isDeviceEncryptionEnabled()
&& !LockPatternUtils.isFileEncryptionEnabled()
&& !dpm.getDoNotAskCredentialsOnBoot()) {
// 见8.6.1根据不同的密码类型获取不同的intent
Intent unlockMethodIntent = getIntentForUnlockMethod(quality);
//...设置要传递的参数
//补充1,封装新的跳转intent
Intent intent = getEncryptionInterstitialIntent(context, quality, required,
unlockMethodIntent);
//...我们不走这里
startActivityForResult(
intent,
mIsSetNewPassword && mRequestGatekeeperPasswordHandle
? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
: ENABLE_ENCRYPTION_REQUEST);
} else {
if (mForChangeCredRequiredForBoot) {
// Welp, couldn't change it. Oh well.
finish();
return;
}
//正常走这里,又回到8.6了
updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
}
}
9.ChooseLockSettingsHelper.java
9.1.show
最终执行的就是9.2的方法,决定是否跳转到密码确认页面
public boolean show() {
return build().launch();
}
>1.build
@NonNull public ChooseLockSettingsHelper build() {
//..
return new ChooseLockSettingsHelper(this, mActivity, mFragment,
mActivityResultLauncher);
}
>2.launch
public boolean launch() {
//见9.2
return launchConfirmationActivity(mBuilder.mRequestCode, mBuilder.mTitle, mBuilder.mHeader,
mBuilder.mDescription, mBuilder.mReturnCredentials, mBuilder.mExternal,
mBuilder.mForceVerifyPath, mBuilder.mUserId, mBuilder.mAlternateButton,
mBuilder.mAllowAnyUserId, mBuilder.mForegroundOnly,
mBuilder.mRequestGatekeeperPasswordHandle);
}
9.2.launchConfirmationActivity
- 根据userId从数据库里读取到对应的quality值,看是否在case里,在的话说明是Pattern,pin,password里的一种,需要弹密码确认框
- case里的区别就是跳转到9宫格图案还是密码输入页面
- 页面跳转逻辑见9.3
- returnCredentials 是true,参数见8.2
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@Nullable CharSequence header, @Nullable CharSequence description,
boolean returnCredentials, boolean external, boolean forceVerifyPath,
int userId, @Nullable CharSequence alternateButton, boolean allowAnyUser,
boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
//默认值是false
boolean launched = false;
//见5.10,获取当前的密码类型对应的quality值
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId)) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
//9宫格是一种样式
launched = launchConfirmationActivity(request, title, header, description,
returnCredentials || forceVerifyPath
? ConfirmLockPattern.InternalActivity.class//跳转的类
: ConfirmLockPattern.class, returnCredentials, external,
forceVerifyPath, userId, alternateButton, allowAnyUser,
foregroundOnly, requestGatekeeperPasswordHandle);
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
//密码,pin是一种样式
launched = launchConfirmationActivity(request, title, header, description,
returnCredentials || forceVerifyPath
? ConfirmLockPassword.InternalActivity.class//跳转的类
: ConfirmLockPassword.class, returnCredentials, external,
forceVerifyPath, userId, alternateButton, allowAnyUser,
foregroundOnly, requestGatekeeperPasswordHandle);
break;
}
//没有设置密码的话返回的就是默认值false,有密码的话就跳转到密码页并返回true,见9.3
return launched;
}
9.3.launchConfirmationActivity
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
CharSequence message, Class<?> activityClass, boolean returnCredentials,
boolean external, boolean forceVerifyPath, int userId,
@Nullable CharSequence alternateButton, boolean allowAnyUser,
boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
final Intent intent = new Intent();
//设置要传递的参数..省略
//设置要跳转的类
intent.setClassName(SETTINGS_PACKAGE_NAME, activityClass.getName());
intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE);
Intent inIntent = mFragment != null ? mFragment.getActivity().getIntent() :
mActivity.getIntent();
copyInternalExtras(inIntent, intent);
if (external) {
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
copyOptionalExtras(inIntent, intent);
if (mActivityResultLauncher != null) {
mActivityResultLauncher.launch(intent);
} else if (mFragment != null) {
mFragment.startActivity(intent);
} else {
mActivity.startActivity(intent);
}
} else {
if (mActivityResultLauncher != null) {
mActivityResultLauncher.launch(intent);
} else if (mFragment != null) {
//我们走这里
mFragment.startActivityForResult(intent, request);
} else {
mActivity.startActivityForResult(intent, request);
}
}
return true;
}
9.4.密码验证页面
每次进入小节8的页面,如果已经设置了密码,那么会先跳转到输入密码页才能操作,对应的两种密码页面如下
- 九宫格 ConfirmLockPattern.InternalActivity.class
- 密码或者pin码 ConfirmLockPassword.InternalActivity.class
10.ChooseLockGenericController.java
10.1.isScreenLockVisible
public boolean isScreenLockVisible(ScreenLockType type) {
final boolean managedProfile = mContext.getSystemService(UserManager.class)
.isManagedProfile(mUserId);
switch (type) {
case NONE:
return !mHideInsecureScreenLockTypes
&& !mContext.getResources().getBoolean(R.bool.config_hide_none_security_option)
&& !managedProfile; // Profiles should use unified challenge instead.
case SWIPE:
return !mHideInsecureScreenLockTypes
&& !mContext.getResources().getBoolean(R.bool.config_hide_swipe_security_option)
&& !managedProfile; // Swipe doesn't make sense for profiles.
case MANAGED:
return mManagedPasswordProvider.isManagedPasswordChoosable();
case PIN:
case PATTERN:
case PASSWORD:
//见5.8
return mLockPatternUtils.hasSecureLockScreen();
}
return true;
}
10.2.isScreenLockEnabled
public boolean isScreenLockEnabled(ScreenLockType type) {
//见5.11,
return !mLockPatternUtils.isCredentialsDisabledForUser(mUserId)
&& type.maxQuality >= upgradeQuality(PASSWORD_QUALITY_UNSPECIFIED);
}
10.3.upgradeQuality
public int upgradeQuality(int quality) {
return Math.max(quality,
Math.max(
LockPatternUtils.credentialTypeToPasswordQuality(
getAggregatedPasswordMetrics().credType),
PasswordMetrics.complexityLevelToMinQuality(
getAggregatedPasswordComplexity())
)
);
}
11.总结
- screen lock 的判定逻辑,先判断是否是secure模式,也就是(pin,password,pattern)里的一种
- 如果是非secure模式,再根据util判断是否是disable状态(数据存储在数据库里的),none的话disable为true,其他都是false
- lock方式选择页面,见小节8,(如果设置过密码,那么会先跳转到密码页,见9.4,输入密码以后才会)展示可用lock方式选项
- 密码修改或者说设置页,见8.6.2以及8.6.3两种
11.1.KeyguardManager
获取系统锁的状态
KeyguardManager keyguardManager=getSystemService(KeyguardManager.class);
>1.isKeyguardSecure
设置了pin,pasword,pattern或者SIM卡锁定 为true,不设置或者是swipe为false
keyguardManager.isKeyguardSecure()
>2.isKeyguardLocked
这个当前是否是锁屏状态,只要不是None,息屏后能看到锁屏页面的都是true,
keyguardManager.isKeyguardLocked()
>3.isDeviceSecure
和补充1的区别,这里只判断pin,pasword,pattern,不包括sim卡锁定
keyguardManager.isDeviceSecure()
>4.isDeviceLocked
是否屏幕已解锁,就是需要pin,password,pattern解锁,和补充2的区别,如果是swipe的话这里也是false
keyguardManager.isDeviceLocked()