Android11.0(R) 预留清空锁屏密码接口

前言

出厂的设备有些客户喜欢设置锁屏密码,无奈记性不好,忘记密码后就只能恢复出厂或者重新刷机了,啊这客户肯定不接受的。

为了防止客户逼逼赖赖,我们就未雨绸缪,给它加个清除接口。

先说结论,系统锁屏密码数据库存储位于 /data/system/locksettings.db

经过测试 O 版本直接删除 locksettings.db 就已经达到要求

测试 Q、R 版本直接删除 locksettings.db 后,系统锁屏界面确实没了,但一直卡在安卓正在启动界面了,

无法进入桌面,进入设置中查看 Launcher3 应用丢了,目测此路不通。

那就曲线救国去研究 Settings 中是如何验证密码并取消密码的。

Settings 中各版本存储密码传递对象,已图案密码为例 ConfirmLockPattern.java

O、P 版本 密码 String intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, LockPatternUtils.patternToString(pattern));

Q 版本 密码 Byte[] intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, LockPatternUtils.patternToByteArray(pattern));

R 版本 密码 LockscreenCredential intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pattern);

framework 往下加解密流程可参考这篇 AndroidQ 锁屏密码验证流程之GateKeeper解析

解决思路

一:找到 Settings 中与用户交互设置锁屏密码核心代码,将绘制图案或者密码字符保存起来(数据库、prop、ContentProvider等)

二:增加清除接口(AIDL、广播、ContentResolver监听等)

三:取出用户设置密码转换为 framework 所需要 LockscreenCredential 对象

四:移除密码

上代码

4.1、找到锁屏图案保存核心代码

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\password\ChooseLockPattern.java

        protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
                new LockPatternView.OnPatternListener() {
				....
                public void onPatternDetected(List<LockPatternView.Cell> pattern) {
                    if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
                        if (mChosenPattern == null) throw new IllegalStateException(
                                "null chosen pattern in stage 'need to confirm");
                        try (LockscreenCredential confirmPattern =
                                LockscreenCredential.createPattern(pattern)) {
                            if (mChosenPattern.equals(confirmPattern)) {
                                //20200903 cczheng add save lockdata start
                                mScreenLockHelper.saveCurrentLockData(pattern);
                                //20200903 cczheng add save lockdata end
                                updateStage(Stage.ChoiceConfirmed);
                            } else {
                                updateStage(Stage.ConfirmWrong);
                            }
                        }
                    } else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
                        if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
                            updateStage(Stage.ChoiceTooShort);
                        } else {
                            mChosenPattern = LockscreenCredential.createPattern(pattern);
                            updateStage(Stage.FirstChoiceValid);
                        }
                    } else {
                        throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
                                + "entering the pattern.");
                    }
                }

mChosenPattern 第一次绘制图案密码,confirmPattern 第二次绘制图案密码,两次一致设置成功,

就地保存图案密码。图案密码九宫格每个点 Cell 对应一个 Row, 一个 Column,实际规则如下

(0,0) (0,1) (0,2)

(1,0) (1,1) (1,2)

(2,0) (2,1) (2,2)

最终画线将每一个 cell 添加到集合中。

实际图案密码对象 LockscreenCredential.createPattern(pattern);

4.2、找到PIN码和密码保存核心代码

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\password\ChooseLockPassword.java

		public void handleNext() {
            if (mSaveAndFinishWorker != null) return;
            // TODO(b/120484642): This is a point of entry for passwords from the UI
            final Editable passwordText = mPasswordEntry.getText();
            if (TextUtils.isEmpty(passwordText)) {
                return;
            }
            mChosenPassword = mIsAlphaMode ? LockscreenCredential.createPassword(passwordText)
                    : LockscreenCredential.createPin(passwordText);
            if (mUiStage == Stage.Introduction) {
                if (validatePassword(mChosenPassword)) {
                    mFirstPassword = mChosenPassword;
                    mPasswordEntry.setText("");
                    updateStage(Stage.NeedToConfirm);
                } else {
                    mChosenPassword.zeroize();
                }
            } else if (mUiStage == Stage.NeedToConfirm) {
                if (mChosenPassword.equals(mFirstPassword)) {
                    //20200903 cczheng add save lockdata start
                    mScreenLockHelper.saveCurrentLockData(mIsAlphaMode, passwordText.toString());
                    //20200903 cczheng add save lockdata end
                    startSaveAndFinish();
                } else {
                    CharSequence tmp = mPasswordEntry.getText();
                    if (tmp != null) {
                        Selection.setSelection((Spannable) tmp, 0, tmp.length());
                    }
                    updateStage(Stage.ConfirmWrong);
                    mChosenPassword.zeroize();
                }
            }
        }

mIsAlphaMode 用来区分是 PIN 码还是密码

实际密码对象 LockscreenCredential.createPassword(passwordText)

实际PIN码对象 LockscreenCredential.createPin(passwordText)

4.3、找到移除密码核心代码

设置完锁屏密码后再次进入锁屏选择页面,此时需要验证刚刚设置密码,验证成功后才能进入锁屏选择界面。

验证成功就获取到了 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pattern);

这个很关键,一会需要用它来移除锁屏密码

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\password\ChooseLockGeneric.java

 void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
			.....
            if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                // Clearing of user biometrics when screen lock is cleared is done at
                // LockSettingsService.removeBiometricsForUser().
                if (mUserPassword != null) {
                    // No need to call setLockCredential if the user currently doesn't
                    // have a password
                    mChooseLockSettingsHelper.utils().setLockCredential(
                            LockscreenCredential.createNone(), mUserPassword, mUserId);
                }
                mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
                getActivity().setResult(Activity.RESULT_OK);
                finish();
            }
        }

关键方法就两个

setLockCredential(新密码,旧密码,用户id)

setLockScreenDisabled(移除密码,用户id)

4.4、造数据移除密码

package com.android.settings.password;

import android.content.Context;
import android.util.Log;
import android.os.SystemProperties;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockscreenCredential;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class ScreenLockHelper{

	private static final String TAG = "ScreenLockHelper";
	//value startwith 
	//pt&xxxx  LockPattern
	//pn&xxxx  LockPin
	//ps&xxxx  LockPassword
	private final String KEY = "persist.android.screen.lock";
	private final String HEAD_PAT = "pt&";
	private final String HEAD_PIN = "pn&";
	private final String HEAD_PWD = "ps&";

	private Context mContext;
	private LockPatternUtils mLockPatternUtils;

	public ScreenLockHelper(Context context) {
        mContext = context;
        mLockPatternUtils = new LockPatternUtils(context);
    }

    public void saveCurrentLockData(boolean mIsPwd, String pwd) {
       pwd = (mIsPwd ? HEAD_PWD : HEAD_PIN) + pwd;
       SystemProperties.set(KEY, pwd);
    }

    public void saveCurrentLockData(List<LockPatternView.Cell> pattern) {
    	String pwd = HEAD_PAT;
		StringBuilder builder = new StringBuilder();
		builder.append(pwd);
    	for (int i=0; i<pattern.size(); i++) {
    		LockPatternView.Cell cell = pattern.get(i);
    		builder.append(cell.getRow());
    		builder.append("*");
    		builder.append(cell.getColumn());
            if (i != pattern.size() - 1) {
            	builder.append("+");
            }
            Log.i(TAG,"cell="+cell.toString());
        }
        pwd = builder.toString();
        SystemProperties.set(KEY, pwd);
    }

    public void  clearScreenLock() {
       LockscreenCredential emptyCredential = LockscreenCredential.createNone();
       LockscreenCredential savedCredential;
       String pwdValue = SystemProperties.get(KEY, "");
       if (pwdValue.startsWith(HEAD_PIN)) {
       	  savedCredential = LockscreenCredential.createPin(pwdValue.substring(3));
       }else if (pwdValue.startsWith(HEAD_PWD)) {
       	  savedCredential = LockscreenCredential.createPassword(pwdValue.substring(3));
       }else if (pwdValue.startsWith(HEAD_PAT)) {
       	  pwdValue = pwdValue.substring(3);
       	  List<LockPatternView.Cell> pattern = new ArrayList<LockPatternView.Cell>();
       	  String[] cellArray = pwdValue.split("\\+");
       	  for (String cellStr : cellArray) {
       	  	String[] cell = cellStr.split("\\*");
       	  	pattern.add(Cell.of(Integer.parseInt(cell[0]), Integer.parseInt(cell[1])));
       	  }
       	  savedCredential = LockscreenCredential.createPattern(pattern);
       }else{
       	  savedCredential = LockscreenCredential.createNone();
       }

       mLockPatternUtils.setLockCredential(emptyCredential, savedCredential, 0);
       mLockPatternUtils.setLockScreenDisabled(true, 0);
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cczhengv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值