中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android4.0開發之Keyguard解鎖屏機制的示例分析

發布時間:2021-08-21 14:02:31 來源:億速云 閱讀:168 作者:小新 欄目:移動開發

這篇文章主要介紹了Android4.0開發之Keyguard解鎖屏機制的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

具體如下:

Keyguard解鎖屏是Android系統中必不可少的模塊,用戶在開機后或者在點擊Power按鈕屏幕變亮后首先看到的畫面即為解鎖屏模塊對應的界面。Keyguard模塊功能相對簡單:

第一:直觀地顯示手機當前的關鍵信息:比如電池信息、運營商信息、日期信息以及通話短信信息等。

第二:增強手機的安全性能:為了安全,用戶可以在Setting里的Secure選項中設置password、pattern、account等不同的安全策略,防止非法用戶訪問手機系統。

但從代碼實現的角度該模塊邏輯還是比較復雜,不但需要監聽系統中的多種event,比如sim、電話、電池以及Carrier等狀態,還要正確反映、顯示屏幕的不同狀態。為了對Keyguard模塊的處理邏輯有更清晰的理解,下面首先從系統構成的角度概括介紹Keyguard解鎖屏模塊的框架,然后對解鎖屏模塊中重要的處理邏輯進行詳細介紹。

一、系統介紹

Keyguard解鎖屏模塊的框架類圖如下:

Android4.0開發之Keyguard解鎖屏機制的示例分析

圖中僅列出了Keyguard解鎖屏模塊涉及的重要類,這些類實現了Keyguard模塊的主要功能,它們的作用如下:

PhoneWindowManager是解鎖屏模塊對外交互的接口,窗口管理Service、電源管理Service等外部模塊都是通過PhoneWindowManager訪問Keyguard內部功能。
KeyguardViewMediator類為解鎖屏模塊的中介者,以中介的身份處理keyguard狀態變化,處理event、power管理、PhoneWindowManager通知等請求,并作為回調對象供解鎖屏模塊的其它類回調。
KeyguardUpdateMonitor類為解鎖屏模塊的監聽者,它負責監聽時間、sim卡、運營商信息、電池信息、電話信息等狀態的變化,并通知keyguard View模塊更新顯示。
KeyguardViewManager類為解鎖屏view模塊的管理者,管理解鎖屏界面的創建、顯示、隱藏以及重置等。
LockPatternKeyguardView類為解鎖屏模塊的View界面,為所有解鎖屏界面的host view。根據設置的安全策略,顯示不同的解鎖屏界面。Google原生代碼中實現了6種解鎖屏界面:

1) LockScreen:用于顯示屏幕加鎖狀態
2) PatternUnlockScreen:實現圖案解鎖模式
3) SimPukUnlockScreen:屏幕實現SIM PUK碼解鎖模式
4) SimUnlockScreen:實現Sim PIN碼解鎖模式
5) AccountUnlockScreen:實現 GOOGLE 帳戶解鎖
6) PasswordUnlockScreen:實現自定義密碼解鎖模式

二、主要邏輯

1、Keyguard模塊啟動、顯示邏輯

即手機開機進入系統到鎖屏界面顯示的過程。手機系統啟動過程中會自動啟動Keyguard解鎖屏模塊,該模塊的創建始于WindowManagerService類,時序圖如下:

Android4.0開發之Keyguard解鎖屏機制的示例分析

1)WindowManagerService在啟動時會實例化PhoneWindowManager對象mPolicy,并在窗口管理Policy線程PolicyThread中初始化,代碼如下:

public void run() {
 Looper.prepare();
 WindowManagerPolicyThread.set(this, Looper.myLooper());
 ......
 mPolicy.init(mContext, mService, mService, mPM);
 ......
 Looper.loop();
}

從代碼中可以看到PhoneWindowManager在獨立的線程和Looper消息隊列中處理Message事件,該Looper對象也為解鎖屏模塊使用以處理所有handler消息。
2)mPolicy函數init中創建解鎖屏模塊的中介者——KeyguardViewMediator對象。
3)在KeyguardViewMediator的構造函數中創建LockPatternKeyguardViewProperties、KeyguardUpdateMonitor、KeyguardViewManager等重要對象:

public KeyguardViewMediator(Context context, PhoneWindowManager callback,
   LocalPowerManager powerManager) {
  ……
  mUpdateMonitor = new KeyguardUpdateMonitor(context);
  mUpdateMonitor.registerInfoCallback(this);
  mUpdateMonitor.registerSimStateCallback(this);
  mLockPatternUtils = new LockPatternUtils(mContext);
  mKeyguardViewProperties
= new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
  mKeyguardViewManager = new KeyguardViewManager(
    context, WindowManagerImpl.getDefault(), this,
    mKeyguardViewProperties, mUpdateMonitor);
  ……
 }

KeyguardViewMediator中記錄了PhoneWindowManager、PowerManager等對象,同時也保存了LockPatternKeyguardViewProperties、KeyguardUpdateMonitor、KeyguardViewManager等模塊內的重要對象,這樣該類以中介者身份在Keyguard模塊對外交互以及內部各對象間的交互中發揮了重要作用。

4)KeyguardUpdateMonitor構造函數中創建mHandler,用以響應處理該類監聽的各事件狀態的改變,并在handle處理函數中通知mInfoCallbacks和mSimStateCallbacks保存的監聽對象,監聽事件有ACTION_TIME_TICK、ACTION_TIME_CHANGED、ACTION_BATTERY_CHANGED、ACTION_TIMEZONE_CHANGED、ACTION_SIM_STATE_CHANGED、        ACTION_PHONE_STATE_CHANGED、RINGER_MODE_CHANGED_ACTION

至此Keyguard解鎖屏模塊中重要的類對象已經實例化,但是還未涉及解鎖屏View界面的創建和顯示。

5)系統啟動后解鎖屏界面的首次顯示始于WindowManagerService的systemReady函數,通知PhoneWindowManager系統就緒,代碼如下:

public void systemReady() {
 mPolicy.systemReady();
}

6)PhoneWindowManager的systemReady函數中通知解鎖屏模塊的中介者KeyguardViewMediator對象系統就緒

7)中介者KeyguardViewMediator類中處理系統就緒情形:調用doKeyguardLocked函數顯示解鎖屏界面:

public void onSystemReady() {
 synchronized (this) {
   mSystemReady = true;
   doKeyguardLocked();
 }
}
private void doKeyguardLocked() {
  ......
  // if the keyguard is already showing, don't bother
  if (mKeyguardViewManager.isShowing()) {
   if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
   return;
  }
  .....
  if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
  showLocked();
}

showLocked函數中發送SHOW消息異步處理解鎖屏界面顯示的請求。

8)handleShow中處理界面顯示的消息請求,函數中調用KeyguardViewManager的函數show實現解鎖屏界面的真正顯示:

public synchronized void show() {
  ......
  if (mKeyguardHost == null) {
   if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
   mKeyguardHost = new KeyguardViewHost(mContext, mCallback);
   ......
   mViewManager.addView(mKeyguardHost, lp);
  }
  ......
  mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
  if (mKeyguardView == null) {
   mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
   ......
   mKeyguardHost.addView(mKeyguardView, lp);
   ......
  }
  ......
}

該函數中主要創建了Keyguard顯示View中的兩個重要的對象:mKeyguardHost和mKeyguardView,它們都是繼承于FrameLayout,為解鎖屏視圖的根view。

9)在創建對象mKeyguardView時根據解鎖屏mode創建解鎖屏界面:

protected void updateScreen(Mode mode, boolean force) {
   ......
  // Re-create the lock screen if necessary
  if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
   if (force || mLockScreen == null) {
    recreateLockScreen();
   }
  }
  // Re-create the unlock screen if necessary. This is primarily required to properly handle
  // SIM state changes. This typically happens when this method is called by reset()
  if (mode == Mode.UnlockScreen) {
   final UnlockMode unlockMode = getUnlockMode();
   if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
    recreateUnlockScreen(unlockMode);
   }
  }
  ......
}

10)在函數createLockScreen或者createUnlockScreenFor中創建具體的Lock或者Unlock View界面,并調用show函數進行顯示

至此,Keyguard解鎖屏模塊從系統開機啟動到界面顯示的處理邏輯已介紹完成。

2、兩次按下Power按鈕屏幕亮->暗->亮過程中鎖屏模塊處理邏輯

連續兩次按下Power按鈕屏幕亮->暗->亮過程中解鎖屏模塊處理邏輯的時序圖如下:

Android4.0開發之Keyguard解鎖屏機制的示例分析

1)在函數PowerManagerService:setPowerState中響應Power按鈕的按下,代碼如下:

private void setPowerState(int newState, boolean noChangeLights, int reason)
{
  synchronized (mLocks) {
   ……
   if (oldScreenOn != newScreenOn) {
    if (newScreenOn) {
     // When the user presses the power button, we need to always send out the
     // notification that it's going to sleep so the keyguard goes on. But
     // we can't do that until the screen fades out, so we don't show the keyguard
     // too early.
     if (mStillNeedSleepNotification) {
      sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
     }
     ……
     if (err == 0) {
      sendNotificationLocked(true, -1);
      // Update the lights *after* taking care of turning the
      // screen on, so we do this after our notifications are
      // enqueued and thus will delay turning on the screen light
      // until the windows are correctly displayed.
      if (stateChanged) {
       updateLightsLocked(newState, 0);
      }
      mPowerState |= SCREEN_ON_BIT;
     }
    } else {
     ……
     if (!mScreenBrightness.animating) {
      err = screenOffFinishedAnimatingLocked(reason);
     }
     ……
    }
   }
   ……
  }
}

根據上面的代碼邏輯,屏幕即將變暗時調用函數screenOffFinishedAnimatingLocked,屏幕即將變亮時調用函數sendNotificationLocked。

2)函數sendNotificationLocked發送Notification Task線程到handler,并異步執行通知解鎖屏模塊進行狀態更新:

private Runnable mNotificationTask = new Runnable()
{
  public void run()
  {
   while (true) {
    ......
    if (value == 1) {
     policy.screenTurningOn(mScreenOnListener);
     ......
    }
    else if (value == 0) {
     policy.screenTurnedOff(why);
     ......
    }
    else {
     // If we're in this case, then this handler is running for a previous
     // paired transaction. mBroadcastWakeLock will already have been released.
     break;
    }
   }
  }
};

上面的線程函數run中分別處理了屏幕變暗和變亮的情形。按下Power按鈕屏幕變暗時調用了函數screenTurnedOff,why為變暗的原因,此處值為OFF_BECAUSE_OF_USER。

3)KeyguardViewMediator中根據屏幕變暗的原因分別處理屏幕變暗事件:

/**
* Called to let us know the screen was turned off.
* @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
* {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
* {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
*/
public void onScreenTurnedOff(int why) {
 synchronized (this) {
 ……
 else if (mShowing) { //若是(mShowing)則重置顯示界面,否則重新顯示鎖屏界面
    notifyScreenOffLocked();
    resetStateLocked();
   } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) {
    // if the screen turned off because of timeout, set an alarm
    // to enable it a little bit later (i.e, give the user a chance
    // to turn the screen back on within a certain window without
    // having to unlock the screen)
    ……
    if (timeout <= 0) {
     // Lock now
     mSuppressNextLockSound = true;
     doKeyguardLocked();
    } else {
     // Lock in the future
     long when = SystemClock.elapsedRealtime() + timeout;
     Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
     intent.putExtra("seq", mDelayedShowingSequence);
     PendingIntent sender = PendingIntent.getBroadcast(mContext,
       0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
     mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when,
       sender);
    }
   } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
    // Do not enable the keyguard if the prox sensor forced the screen off.
   } else { //顯示鎖屏屏幕
    doKeyguardLocked();
   }
  }
}

4)調用doKeyguardLocked重新顯示鎖屏界面,隨后的鎖屏界面顯示邏輯與Keyguard模塊啟動顯示中的8~10步相同,不再贅述。

5)按下Power按鈕屏幕即將由暗->亮時代碼處理邏輯重新執行1~2步,第二步中屏幕變亮時調用的函數是PhoneWindowManager:screenTurningOn。

6)函數screenTurningOn中調用中介者KeyguardViewMediator的函數onScreenTurnedOn,該函數直接調用屏幕變亮異步通知函數KeyguardViewMediator:notifyScreenOnLocked,告知解鎖屏模塊屏幕即將變亮。

7)函數handleNotifyScreenOn響應屏幕變亮的通知

8)程序執行到LockPatternKeyguardView:onScreenTurnedOn函數,并調用show函數進行解鎖屏界面的顯示,代碼如下:

public void show() {
  if (mMode == Mode.LockScreen) {
   ((KeyguardScreen) mLockScreen).onResume();
  } else {
   ((KeyguardScreen) mUnlockScreen).onResume();
  }
  ......
 }

至此,邏輯處理完成。

3、自定義口令解鎖邏輯

自定義口令解鎖始于PasswordUnlockScreen,時序圖如下:

Android4.0開發之Keyguard解鎖屏機制的示例分析

1)解鎖屏界面輸入密碼點擊確定按鈕后,在函數onEditorAction中進行響應:

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
  // Check if this was the result of hitting the enter key
  if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
    || actionId == EditorInfo.IME_ACTION_NEXT) {
   verifyPasswordAndUnlock();
   return true;
  }
  return false;
}

2)在函數verifyPasswordAndUnlock中對輸入的密碼進行判斷,如果輸入正確,測調用keyguardDone響應解鎖完成的操作。mCallback.keyguardDone(true)調用是所有解鎖屏mode情形在解鎖成功后必須調用的函數,隨后的處理邏輯對于不同的解鎖屏界面也是相同的。

3)回調KeyguardScreenCallback和KeyguardViewMediator的函數keyguardDone,在后者的keyguardDone函數中,異步發送keyDone事件:

public void keyguardDone(boolean authenticated, boolean wakeup) {
 synchronized (this) {
  ……
  Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
  msg.arg1 = wakeup ? 1 : 0;
  mHandler.sendMessage(msg);
  ……
 }
}

4)函數KeyguardViewMediator:handleKeyguardDone異步處理keyguardDone事件,調用handleHide隱藏鎖屏界面。

5)KeyguardViewManager.hide函數中調用鎖屏界面的銷毀函LockPatternKeyguardView:cleanUp數隱藏銷毀界面,如下:

public void cleanUp() {
 if (mLockScreen != null) {
  ((KeyguardScreen) mLockScreen).onPause();
  ((KeyguardScreen) mLockScreen).cleanUp();
  this.removeView(mLockScreen);
  mLockScreen = null;
 }
 if (mUnlockScreen != null) {
  ((KeyguardScreen) mUnlockScreen).onPause();
  ((KeyguardScreen) mUnlockScreen).cleanUp();
  this.removeView(mUnlockScreen);
  mUnlockScreen = null;
 }
 ......
}

至此,解鎖完成。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Android4.0開發之Keyguard解鎖屏機制的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

达州市| 大田县| 台湾省| 泰来县| 涿州市| 瓦房店市| 玉屏| 龙州县| 辛集市| 宜昌市| 修武县| 南和县| 齐河县| 大新县| 嘉峪关市| 安阳县| 澄迈县| 鄂托克前旗| 永嘉县| 武定县| 观塘区| 积石山| 梧州市| 揭东县| 高青县| 苏尼特右旗| 胶南市| 丰县| 石景山区| 金溪县| 弋阳县| 元江| 铜鼓县| 七台河市| 和林格尔县| 宿州市| 长宁区| 新丰县| 泗阳县| 新化县| 贡山|