Setting 確認密碼解析

什麼是確認密碼

人臉apk點擊開始錄入時,apk會通過Internt會調用ChooseLockGeneric.java,我們知道如果之前設置過密碼,再次進入時,則會依次跳轉到如下界面:
image.pngimage.pngimage.png

流程圖分析

首先看下整體的流程圖,有個大概瞭解:


確認密碼頁面前傳

整體結構

接着看下ChooseLockGeneric.java的整體結構如下:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/password/ChooseLockGeneric.java
public class ChooseLockGeneric extends SettingsActivity {
    public static final String CONFIRM_CREDENTIALS = "confirm_credentials";
    public static class ChooseLockGenericFragment extends SettingsPreferenceFragment{}
}

可以看到,ChooseLockGeneric繼承自SettingsActivity,所以我們從SettingsActivity 的onCreat()方法入手,log打印如下:

image.png

頁面流程分析

首先看chooseLockGenericFragment的onCreat流程,如下所示

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ChooseLockGeneric.java/ChooseLockGenericFragment
@Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            final Activity activity = getActivity();
  			......
            //FACE_UNLOCK_SUPPORT start
            if (isFaceUnlockSupport()) {
                mVerifyUnlock = getActivity().getIntent().getBooleanExtra("verify_unlock", false);
                Log.d(TAG, "onCreate mVerifyUnlock = " + mVerifyUnlock);
            }
            //FACE_UNLOCK_SUPPORT end

           .........

			//第一次進入時mPasswordConfirmed、mWaitingForConfirmation都被初始化爲false
            if (mPasswordConfirmed) {
                updatePreferencesOrFinish(savedInstanceState != null);
                if (mForChangeCredRequiredForBoot) {
                    maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
                            mUserId), false);
                }
            } else if (!mWaitingForConfirmation) {//會走着個流程
                //初始化ChooseLockSettingsHelper,this指的是Fragment即ChooseLockGenericFragment
                ChooseLockSettingsHelper helper =
                        new ChooseLockSettingsHelper(this.getActivity(), this);
                boolean managedProfileWithUnifiedLock =
                        UserManager.get(getActivity()).isManagedProfile(mUserId)
                        && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId);
                boolean skipConfirmation = managedProfileWithUnifiedLock && !mIsSetNewPassword;
                //log打印managedProfileWithUnifiedLock和skipConfirmation 都爲false
                if (skipConfirmation
                        || !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
                        getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) {
                    //發現並沒有進入這個流程說明helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
                    //getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)返回true
                   
                    mPasswordConfirmed = true; // no password set, so no need to confirm
                    //此時savedInstanceState爲null
                    updatePreferencesOrFinish(savedInstanceState != null);
                } else {
                    mWaitingForConfirmation = true;
                }
            }
            addHeaderView();
        }

我們來看下helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)方法幹了些什麼,跟蹤發現最後調用到如下方法:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ChooseLockSettingsHelper.java
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
            @Nullable CharSequence header, @Nullable CharSequence description,
            boolean returnCredentials, boolean external, boolean hasChallenge,
            long challenge, int userId, @Nullable CharSequence alternateButton, Bundle extras) {
        final int effectiveUserId = UserManager.get(mActivity).getCredentialOwnerProfile(userId);
        boolean launched = false;
        Log.d(TAG,"ChooseLockSettingsHelper launchConfirmationActivity request"+ ":title: "+title+" :header: "+header
                +" :description: "+description+" :returnCredentials: "+returnCredentials+" :external: "+external
                +" :hasChallenge: "+hasChallenge);
    //Log打印如下:ChooseLockSettingsHelper launchConfirmationActivity request:title: 屏幕鎖定 :header: null 
    //:description: null :returnCredentials: true :external: false :hasChallenge: false
        switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(effectiveUserId)) {
            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING://圖案
                //log打印爲65536,爲圖案,由上面的log可以看出returnCredentials爲true,所以爲ConfirmLockPattern.InternalActivity.class
                //所以會執行如下方法
                launched = launchConfirmationActivity(request, title, header, description,
                        returnCredentials || hasChallenge
                                ? ConfirmLockPattern.InternalActivity.class
                                : ConfirmLockPattern.class, returnCredentials, external,
                                hasChallenge, challenge, userId, alternateButton, extras);
                break;
            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX://PIN碼
            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX://密碼
            case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
                ......
                break;
        }
        return launched;
    }

其中幾種鎖屏方式如下:

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"),//PIN
    PASSWORD(
            DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,//默認,低優先級
            DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,//高優先級
            "unlock_set_password"),//密碼
    MANAGED(
            DevicePolicyManager.PASSWORD_QUALITY_MANAGED,
            "unlock_set_managed");
}

接着我們來看case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:裏面執行的launchConfirmationActivity,方法如下:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ChooseLockSettingsHelper.java
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
            CharSequence message, Class<?> activityClass, boolean returnCredentials,
            boolean external, boolean hasChallenge, long challenge,
            int userId, @Nullable CharSequence alternateButton, Bundle extras) {
        final Intent intent = new Intent();
    	//爲intent設置一些參數
        ......
    	//由上面log分析可知,此時的activityClass.getName()爲ConfirmLockPattern.java
    	//裏的一個空的靜態內部類InternalActivity
        intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
    	//由上面打印的log可以看出external爲false
        if (external) {
           ......
        } else {
            //此mFragment爲ChooseLockGenericFragment的onCreate方法中初始化的ChooseLockSettingsHelper裏的Fragment
            //此時不爲null
            if (mFragment != null) {
                //爲intent設置theme
                copyInternalExtras(mFragment.getActivity().getIntent(), intent);
                //啓動intent,即跳轉到ConfirmLockPattern.java
                mFragment.startActivityForResult(intent, request);
            } else {
                ......
            }
        }
        return true;
    }

此時通過調用mFragment.startActivityForResult(intent, request);方法跳轉到ConfirmLockPattern.java,即如下界面:
image.png

確認密碼頁面分析

整體結構

接下來我們來看下ConfirmLockPattern.java的結構

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ConfirmLockPattern.java
public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
	public static class InternalActivity extends ConfirmLockPattern {}
   
    public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment
            implements AppearAnimationCreator<Object>, CredentialCheckResultTracker.Listener{}

}

ConfirmDeviceCredentialBaseActivity.java結構如下:

public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {}

所以啓動跳轉到ConfirmLockPattern.java的SettingsActivity打印log如下:

image.png

頁面流程分析

接着來看ConfirmLockPatternFragment的onCreateView方法,如下所示:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ConfirmLockPattern.java/ConfirmLockPatternFragment
@Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            
			//加載佈局、設置view id、處理點擊事件
            ......
            //獲取intent,由上面log可知mHeaderText、mDetailsText都爲null  
            Intent intent = getActivity().getIntent();
            if (intent != null) {
                mHeaderText = intent.getCharSequenceExtra(
                        ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
                mDetailsText = intent.getCharSequenceExtra(
                        ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
            }
			//設置一些監聽事件
            ......
            //更新狀態
            updateStage(Stage.NeedToUnlock);
			......
            return view;
        }

接着我們來看下updateStage(Stage.NeedToUnlock);方法如下:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ConfirmLockPattern.java/ConfirmLockPatternFragment
private void updateStage(Stage stage) {
            switch (stage) {
                case NeedToUnlock:
                    if (mHeaderText != null) {
                        mHeaderTextView.setText(mHeaderText);
                    } else {
                        //mHeaderText爲null,會執行這裏
                        //getDefaultHeader()返回字符串:"確認您的圖案"
                        mHeaderTextView.setText(getDefaultHeader());
                    }
                    if (mDetailsText != null) {
                        mDetailsTextView.setText(mDetailsText);
                    } else {
                        //mDetailsText爲null,會執行這裏
                        //getDefaultDetails()返回字符串:"請繪製您的設備解鎖圖案以繼續"
                        mDetailsTextView.setText(getDefaultDetails());
                    }
                    mErrorTextView.setText("");
                    updateErrorMessage(
                            mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId));
                    mLockPatternView.setEnabled(true);
                    mLockPatternView.enableInput();
                    mLockPatternView.clearPattern();
                    break;
                ......
            }
        }

接着會執行onResume(),設置監聽事件mCredentialCheckResultTracker.setListener(this);來監聽判斷圖案繪製。

我們可以從ChooseLockSettingsHelper.java中的launchConfirmationActivity方法中可以看出最後結果是 return true,所以回到ChooseLockGeneric.java,發現最後會執行到如下:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ChooseLockGeneric.java/ChooseLockGenericFragment
@Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ......
			//打印log發現第一次時mPasswordConfirmed、mWaitingForConfirmation都爲false
            if (mPasswordConfirmed) {
                ......
            } else if (!mWaitingForConfirmation) {//會走着個流程
                ......
                //log打印managedProfileWithUnifiedLock和skipConfirmation 都爲false
                if (skipConfirmation
                        || !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
                        getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) {
                   ......
                } else {
                    //此時會執行到這裏
                    mWaitingForConfirmation = true;
                }
            }
            addHeaderView();
        }

繪製完成,結束頁面

當繪製完密碼後,會執行onActivityResult方法,如下所示:

// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/settings
// /password/ChooseLockGeneric.java/ChooseLockGenericFragment 
@Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            Log.d(TAG,"onActivityResult");
            super.onActivityResult(requestCode, resultCode, data);
            Log.d(TAG,"onActivityResult1 requestCode:resultCode "+requestCode+" : "+resultCode +" :data: "+ data);
            mWaitingForConfirmation = false;
            if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
                Log.d(TAG,"onActivityResult2");
                //FACE_UNLOCK_SUPPORT start
                      if (isFaceUnlockSupport() && mVerifyUnlock) {
                          data.putExtra("mVerify", true);
                          getActivity().setResult(resultCode, data);
                          finish();
                      } else {
                      //FACE_UNLOCK_SUPPORT end
                        ......
                      //FACE_UNLOCK_SUPPORT start
                      }
                      //FACE_UNLOCK_SUPPORT end
            } 
            ......
        }

打印log如下:
image.png

其中requestCode 100即爲CONFIRM_EXISTING_REQUEST,此時如果含有人臉的話會結束掉此密碼驗證頁面,進入到開始錄入界面,即下圖所示:

image.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章