日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 8.0 手机亮灭屏

發(fā)布時間:2024/1/8 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 8.0 手机亮灭屏 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文主要跟蹤分析通過按松power鍵來喚醒,熄滅屏幕的邏輯。下面是一些相關(guān)類的介紹

PowerManagerService.java:簡稱PMS,負責Andorid系統(tǒng)中電源管理方面的工作。作為系統(tǒng)核心服務(wù)之一,主要處理系統(tǒng)中與power相關(guān)的計算,然后決策系統(tǒng)該如何反應(yīng)。同時PowerManagerService與其他服務(wù)及HAL層等都有交互關(guān)系,協(xié)調(diào)power如何與系統(tǒng)其他模塊的交互,比如沒有用戶活動時屏幕變暗等。

DisplayPowerController.java:簡稱DPC管理Display設(shè)備的電源狀態(tài)。僅在PowerManagerService中實例化了一個對象,它算是PowerManagerService的一部分,只不過是獨立出來了而已。主要處理和距離傳感器,

燈光傳感器,以及包括關(guān)屏在內(nèi)的一些動畫,通過異步回調(diào)的方式來通知PowerManagerService某些事情發(fā)生了變化。

DisplayPowerState.java:簡稱DPS,在本質(zhì)上類似于View,只不過用來描述一個display的屬性,當這些屬性發(fā)生變化時,可以通過一個序列化的命令,讓這些和display電源狀態(tài)的屬性一起產(chǎn)生變化。

這個類的對象只能被DispalyPowerController的Looper持有。而這個Looper應(yīng)該就是PowerManagerService中新建的一個HandlerThread中的Looper。和PowerManager相關(guān)的,

包括DisplayPowerState和DisplayPowerController相關(guān)的消息處理應(yīng)該都可以通過這個HandlerThread進行運轉(zhuǎn)的

Notifier.java:將power狀態(tài)的重要變化,通過廣播發(fā)送出去,并且參與了與AMS,WMS,IMP的交互。

ColorFade.java:負責屏幕由關(guān)到開,由開到關(guān)的一些GL動畫,由DPC進行控制。

AutomaticBrightnessController.java:主要處理光傳感器,將底層上傳的參數(shù)進行處理計算,將計算的新的亮度值傳給DPC。

RampAnimator.java:處理屏幕亮度漸變動畫。

  • 代碼流程分析
  • Power事件上報跟蹤
  • 正常我們按下power鍵后,出觸發(fā)Kernel關(guān)于該事件的中斷。然后inputReader通過EventHub獲取該事件,并做出事件處理,之后由inputdispatch進行事件分發(fā)。

    因為power事件是key事件,會調(diào)用interceptKeyBeforeQueueing進行處理,通過如果流程

    InputDispatcher.cpp

    ? ->com_android_server_input_InputManagerService.cpp

    ????????? ->InputManagerService.java

    ?????????????????? ->InputMonitor.java

    ?????????????????????????? ->WindowManagerPolicy.java

    ??????????????????????????????????? ->PhoneWindowManager.java

  • PhoneWindowManager.java
  • 最終由PhoneWindowManager.java的interceptKeyBeforeQueueing方法對該次事件進行處理,對power鍵以及屏幕狀態(tài)進行判斷,來決定亮屏還是滅屏等操作。當需要亮屏時,會調(diào)用PowerMangerService中的wakeup函數(shù)進行處理。

    主要代碼如下:

    首先定義以下幾個布爾值,主要是按鍵屬性和屏幕狀態(tài)

    //是否亮屏狀態(tài),代碼是否可以與用戶交互

    final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;

    //按鍵事件是否為down事件

    final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;

    //事件是否被取消

    final boolean canceled = event.isCanceled();

    //按鍵的keycode,不同按鍵 keycode不同,一般power 116

    final int keyCode = event.getKeyCode();

    //是否是輸入事件

    final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;

    //鎖屏界面狀態(tài)

    final boolean keyguardActive = (mKeyguardDelegate == null ? false :(interactive ?isKeyguardShowingAndNotOccluded() :mKeyguardDelegate.isShowing()));

    //flags有wake標記,或者按鍵(isWakeKey函數(shù))為KEYCODE_BACK, KEYCODE_MENU, KEYCODE_WAKEUP, KEYCODE_PAIRING, KEYCODE_STEM_1, KEYCODE_STEM_2, KEYCODE_STEM_3設(shè)置isWakeKey為true

    boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 || event.isWakeKey();

    ?

    ?

    if (isValidGlobalKey(keyCode)//有效的全局按鍵 (KEYCODE_POWER:KEYCODE_WAKEUP:KeyEvent.KEYCODE_SLEEP:),

    ????????? && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {//在com.android.internal.R.xml.global_keys 有定義

    ? if (isWakeKey) {

    ????????? wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");喚醒屏幕

    ? }

    ? return result;

    }

    ?

    接下來是對特殊按鍵的處理,這里只關(guān)注power鍵

    ?switch (keyCode) {

    ? ?case KeyEvent.KEYCODE_POWER: {

    ????????? result &= ~ACTION_PASS_TO_USER;

    ????????? isWakeKey = false; // wake-up will be handled separately

    ????????? if (down) {

    ?????????????????? interceptPowerKeyDown(event, interactive);//處理power按下

    ????????? } else {

    ?????????????????? interceptPowerKeyUp(event, interactive, canceled);//處理power松開

    ????????? }

    ????????? break;

    ? }

    ?

    power down 鍵的處理

    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {

    ? // 獲取wakelock,報錯CPU喚醒狀態(tài)

    ? if (!mPowerKeyWakeLock.isHeld()) {

    ????????? mPowerKeyWakeLock.acquire();

    ? }

    ?

    ? // 取消多次按下超時監(jiān)測

    ? if (mPowerKeyPressCounter != 0) {

    ????????? mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);

    ? }

    ?

    ? // Detect user pressing the power button in panic when an application has

    ? // taken over the whole screen.

    boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,

    ?????????????????? SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),

    ?????????????????? isNavBarEmpty(mLastSystemUiFlags));

    ? if (panic) {

    ????????? mHandler.post(mHiddenNavPanic);

    ? }

    ?

    ? // Latch power key state to detect screenshot chord.

    ? if (interactive && !mScreenshotChordPowerKeyTriggered

    ?????????????????? && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {

    ????????? mScreenshotChordPowerKeyTriggered = true;

    ????????? mScreenshotChordPowerKeyTime = event.getDownTime();

    ????????? interceptScreenshotChord();//屏幕截屏

    ????????? interceptDisableTouchModeChord();? //添加口袋模式

    ? }

    ?

    ? // 當power鍵按下,停止電話響鈴或者結(jié)束通話

    ? TelecomManager telecomManager = getTelecommService();

    ? boolean hungUp = false;

    ? if (telecomManager != null) {

    ????????? if (telecomManager.isRinging()) {

    ?????????????????? 停止響鈴

    ?????????????????? telecomManager.silenceRinger();

    ????????? } else if ((mIncallPowerBehavior

    ?????????????????????????? & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0

    ?????????????????????????? && telecomManager.isInCall() && interactive) {

    ?????????????????? Setting數(shù)據(jù)庫讀取設(shè)置,如果開了掛斷電話

    ?????????????????? hungUp = telecomManager.endCall();

    ????????? }

    ? }

    ?

    ? SprdGestureLauncherService gestureService = LocalServices.getService(

    ?????????????????? SprdGestureLauncherService.class);

    ? boolean gesturedServiceIntercepted = false;

    ? if (gestureService != null) {

    ????????? gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,

    ?????????????????????????? mTmpBoolean);

    ????????? if (mTmpBoolean.value && mGoingToSleep) {

    ?????????????????? mCameraGestureTriggeredDuringGoingToSleep = true;

    ????????? }

    ? }

    ?

    ? // If the power key has still not yet been handled, then detect short

    ? // 如果power鍵還沒有被處理,判斷是短按,多按,長按等場景并做出對應(yīng)處理

    ? mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered

    ?????????????????? || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;

    ? if (!mPowerKeyHandled) {

    ????????? if (interactive) {

    ?????????????????? //如果屏幕是亮的,長按動作處理對應(yīng)的長按動作

    ?????????????????? if (hasLongPressOnPowerBehavior()) {

    ?????????????????????????? Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);

    ?????????????????????????? msg.setAsynchronous(true);

    ?????????????????????????? mHandler.sendMessageDelayed(msg,

    ??????????????????????????????????? ??????? ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());

    ?????????????????? }

    ? ??????? } else {//屏幕休眠的狀態(tài),喚醒屏幕

    ?????????????????? wakeUpFromPowerKey(event.getDownTime());

    ?

    ?????????????????? if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {

    ?????????????????????????? Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);

    ?????????????????????????? msg.setAsynchronous(true);

    ?????????????????????????? mHandler.sendMessageDelayed(msg,//如果長按動作繼續(xù)執(zhí)行長按操作

    ??????????????????????????????????? ??????? ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());

    ?????????????????????????? mBeganFromNonInteractive = true;

    ?????????????????? } else {

    ?????????????????????????? final int maxCount = getMaxMultiPressPowerCount();

    ?

    ?????????????????????????? if (maxCount <= 1) {

    ??????????????????????????????????? mPowerKeyHandled = true;

    ?????????????????????????? } else {

    ??????????????????????????????????? mBeganFromNonInteractive = true;

    ......

    power up 鍵的處理

    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {

    ? final boolean handled = canceled || mPowerKeyHandled; //power鍵是否被處理了

    ? mScreenshotChordPowerKeyTriggered = false;

    ? cancelPendingScreenshotChordAction();

    ? cancelPendingPowerKeyAction();

    ?

    ? if (!handled) {

    ????????? // power press 加1

    ????????? mPowerKeyPressCounter += 1;

    ????????

    ????????? final int maxCount = getMaxMultiPressPowerCount();//多按的次數(shù)

    ????????? final long eventTime = event.getDownTime();//press power 時間

    ????????? if (mPowerKeyPressCounter < maxCount) {

    ?????????????????? // 這種情況可能是一個多次按鍵事件,等待一會做確認處理

    ?????????????????? Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,

    ??????????????????????????????????? interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);

    ?????????????????? msg.setAsynchronous(true);

    ?????????????????? mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());

    ?????????????????? return;

    ????????? }

    ?

    ????????? // 沒有其他action,繼續(xù)處理power按下事件

    ????????? powerPress(eventTime, interactive, mPowerKeyPressCounter);

    ? }

    ?

    ? // Done.? Reset our state.

    ? finishPowerKeyPress();//power按鍵處理結(jié)束

    }

    private void finishPowerKeyPress() {

    ? mBeganFromNonInteractive = false;

    ? mPowerKeyPressCounter = 0;

    ? if (mPowerKeyWakeLock.isHeld()) {

    ????????? mPowerKeyWakeLock.release();//釋放wakelock

    ? }

    }

    下面繼續(xù)跟蹤powerPress函數(shù)

    private void powerPress(long eventTime, boolean interactive, int count) {

    ? if (mScreenOnEarly && !mScreenOnFully) {

    ????????? Slog.i(TAG, "Suppressed redundant power key press while "

    ?????????????????????????? + "already in the process of turning the screen on.");

    ????????? return;

    ? }

    ?

    ? if (count == 2) {//按兩次power事件

    ????????? powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);

    ? } else if (count == 3) {//按三次power事件

    ????????? powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);

    ? } else if (interactive && !mBeganFromNonInteractive) {//屏幕如果亮著而且mBeganFromNonInteractive為false會執(zhí)行下面操作

    ????????? switch (mShortPressOnPowerBehavior) {//根據(jù)配置om.android.internal.R.integer.config_shortPressOnPowerBehavior 決定對應(yīng)值 此處為1

    ?????????????????? case SHORT_PRESS_POWER_NOTHING:

    ?????????????????????????? break;

    ?????????????????? case SHORT_PRESS_POWER_GO_TO_SLEEP:

    ?????????????????????????? mPowerManager.goToSleep(eventTime,

    ??????????????????????????????????? ??????? PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);//執(zhí)行滅屏操作

    ?????????????????????????? break;

    ?????????????????? ......

    }

    ?

    我們繼續(xù)跟蹤亮屏操作,從power down事件處理可知,調(diào)用wakeUpFromPowerKey點亮屏幕

    private void wakeUpFromPowerKey(long eventTime) {

    ? Slog.d(TAG, "wake Up From Power Key"); // 此處會打印這句log,可作為分析問題是注意點

    ? wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");//調(diào)用wakeup繼續(xù)執(zhí)行亮屏操作,注意調(diào)用mPowerManager.wakeUp操作

    }

  • PowerManager.wakeUp
  • 下面我們看下PowerManager.wakeUp的相關(guān)處理

    public void wakeUp(long time) {

    ? try {

    ????????? mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());//調(diào)用到PWM.wakeUpInternal->PWM.wakeUpNoUpdateLocked

    ? } catch (RemoteException e) {

    ????????? throw e.rethrowFromSystemServer();

    ? }

    }

    ?

    當power接收到亮滅屏調(diào)用后,會先進行設(shè)置手機wakefullness狀態(tài). 之后發(fā)送亮滅屏廣播通知其他應(yīng)用手機處于亮屏還是滅屏狀態(tài)。

    private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,

    ????????? String opPackageName, int opUid) {

    ? //mWakefulness標識系統(tǒng)當前狀態(tài)共有四種定義:

    ? WAKEFULNESS_ASLEEP:表示系統(tǒng)當前處于休眠狀態(tài),只能被wakeUp()調(diào)用喚醒。

    ? WAKEFULNESS_AWAKE:表示系統(tǒng)目前處于正常運行狀態(tài)。

    ? WAKEFULNESS_DREAMING:表示系統(tǒng)當前正處于互動屏保的狀態(tài)。

    ? WAKEFULNESS_DOZING:表示系統(tǒng)正處于“doze”狀態(tài)

    ? if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE

    ?????????????????? || !mBootCompleted || !mSystemReady) {//按鍵時間在睡下去之前,屏幕是正常狀態(tài),沒有完成開機流程,系統(tǒng)沒有準備完成,這四種情況不繼續(xù)執(zhí)行喚醒流程

    ????????? return false;

    ? }

    ?

    ? try {//系統(tǒng)不是點亮狀態(tài),打出相關(guān)log

    ????????? switch (mWakefulness) {

    ?????????????????? case WAKEFULNESS_ASLEEP:

    ?????????????????? case WAKEFULNESS_DREAMING:

    ?????????????????? case WAKEFULNESS_DOZING:

    ?????????????????????????? Slog.i(TAG, "Waking up from dozing due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");

    ?????????????????????????? break;

    ????????? }

    ?

    ????????? mLastWakeTime = eventTime;//更新wake時間

    ????????? setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);//更新mWakefulness,并調(diào)用Notifier.onWakefulnessChangeStarted發(fā)送亮屏廣播?

    ????????? mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);//調(diào)用Notifier通知battery處理?

    ????????? userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);//更新最后一次用戶事件的時間

    ? } finally {

    ? }

    ? return true;

    }

    ?

  • Notifier.java
  • 然后主要就是在Notifier.java中與AMS,window,input進行交互,通知各模塊手機狀態(tài)發(fā)生了改變,根據(jù)屏幕狀態(tài)各自進行處理, 最后發(fā)送亮滅屏廣播, 通知相關(guān)的模塊.

    private void setWakefulnessLocked(int wakefulness, int reason) {

    ? if (mWakefulness != wakefulness) {

    ????????? mWakefulness = wakefulness;//更新mWakefulness變量

    ????????? mWakefulnessChanging = true;

    ????????? mDirty |= DIRTY_WAKEFULNESS;

    ????????? mNotifier.onWakefulnessChangeStarted(wakefulness, reason);//調(diào)用Notify的函數(shù)onWakefulnessChangeStarted 發(fā)廣播通知

    ? }

    }

    public void onWakefulnessChangeStarted(final int wakefulness, int reason) {

    ??? //獲取交互模式變量,亮屏為true, 滅屏為false

    ? final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);

    ?

    ? 通知AMS wakefulness狀態(tài)的變化

    ? mHandler.post(new Runnable() {

    ????????? @Override

    ????????? public void run() {

    ?????????????????? mActivityManagerInternal.onWakefulnessChanged(wakefulness);

    ????????? }

    ? });

    ?

    ? //interactive 變化時才會執(zhí)行里面的邏輯

    ? if (mInteractive != interactive) {

    ????????? // Finish up late behaviors if needed.

    ????????? if (mInteractiveChanging) {

    ?????????????????? handleLateInteractiveChange();

    ????????? }

    ?

    ????????? //在input中記錄現(xiàn)在的屏幕狀態(tài)

    ????????? mInputManagerInternal.setInteractive(interactive);

    ????????? mInputMethodManagerInternal.setInteractive(interactive);

    ?

    ????????? //喚醒battery狀態(tài)

    ????????? try {

    ?????????????????? mBatteryStats.noteInteractive(interactive);

    ????????? } catch (RemoteException ex) { }

    ?

    ????????? // Handle early behaviors.

    ????????? mInteractive = interactive;

    ????????? mInteractiveChangeReason = reason;

    ????????? mInteractiveChanging = true;

    ????????? handleEarlyInteractiveChange();//處理交互模式改變

    ? }

    }

    ?

    private void handleEarlyInteractiveChange() {

    ? synchronized (mLock) {

    ????????? if (mInteractive) {//mInteractive 為true代表要執(zhí)行亮屏邏輯

    ?????????????????? // Waking up...

    ?????????????????? mHandler.post(new Runnable() {

    ?????????????????????????? @Override

    ?????????????????????????? public void run() {

    ??????????????????????????????????? // Note a SCREEN tron event is logged in PowerManagerService.

    ??????????????????????????????????? mPolicy.startedWakingUp();//調(diào)用PhoneWindowManager 方法開始亮屏流程

    ?????????????????????????? }

    ?????????????????? });

    ?

    ?????????????????? // 更新亮屏廣播

    ?????????????????? mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;

    ?????????????????? mPendingWakeUpBroadcast = true;

    ?????????????????? updatePendingBroadcastLocked();//mSuspendBlocker.acquire();持有partial 鎖

    ????????? } else {//mInteractive 為false代表要執(zhí)行滅屏邏輯

    ?????????????????? final int why = translateOffReason(mInteractiveChangeReason);

    ?????????????????? mHandler.post(new Runnable() {

    ?????????????????????????? @Override

    ?????????????????????????? public void run() {

    ??????????????????????????????????? mPolicy.startedGoingToSleep(why);//調(diào)用PhoneWindowManager 方法開始滅屏流程

    ?????????????????????????? }

    ?????????????????? });

    ????????? }

    ? }

    }

    ?

  • 廣播更新的流程
  • 調(diào)用updatePendingBroadcastLocked函數(shù)發(fā)出handle msg 消息

    Message msg = mHandler.obtainMessage(MSG_BROADCAST);

    msg.setAsynchronous(true);

    mHandler.sendMessage(msg);

    然后handle收到后執(zhí)行sendNextBroadcast函數(shù)

    case MSG_BROADCAST:

    ? sendNextBroadcast();

    ? break;

    private void sendNextBroadcast() {

    ? final int powerState;

    ? //mBroadcastedInteractiveState 這個變量記錄當前的系統(tǒng)亮滅屏情況

    ? synchronized (mLock) {

    ????????? if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {

    ?????????????????? // 當前狀態(tài)位置更新為喚醒狀態(tài)

    ?????????????????? mPendingWakeUpBroadcast = false;

    ?????????????????? mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;

    ????????? } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {

    ?????????????????? // 當前是喚醒狀態(tài),更新為滅屏狀態(tài)

    ?????????????????? if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast

    ??????????????????????????????????? || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {

    ?????????????????????????? mPendingGoToSleepBroadcast = false;

    ?????????????????????????? mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;

    ?????????????????? } else {

    ?????????????????????????? finishPendingBroadcastLocked();//釋放partial 鎖

    ?????????????????????????? return;

    ?????????????????? }

    ????????? } else {

    ?????????????????? // 當前是滅屏狀態(tài),更新為喚醒狀態(tài)

    ?????????????????? if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast

    ?????????????????? ???????????????? || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {

    ?????????????????????????? mPendingWakeUpBroadcast = false;

    ?????????????????????????? mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;

    ?????????????????? } else {

    ?????????????????????????? finishPendingBroadcastLocked();

    ?????????????????????????? return;

    ?????????????????? }

    ????????? }

    ????????? //記錄下當前系統(tǒng)時間為廣播開始時間

    ????????? mBroadcastStartTime = SystemClock.uptimeMillis();

    ????????? powerState = mBroadcastedInteractiveState;

    ? }

    ?

    EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);//打出event log

    ?

    ? if (powerState == INTERACTIVE_STATE_AWAKE) {//根據(jù)powerState的值決定發(fā)亮屏還是滅屏廣播

    ????????? sendWakeUpBroadcast();

    ? } else {

    ????????? sendGoToSleepBroadcast();

    ? }

    }

    廣播都是前臺廣播,然后其他模塊收到廣播后作出對應(yīng)處理

    mScreenOnIntent.addFlags(

    ? Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND

    ? | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);

    mScreenOffIntent.addFlags(

    ? Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND

    ? | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);

    Notify 收到這個廣播后會,繼續(xù)調(diào)用sendNextBroadcast,因為mPendingWakeUpBroadcast值變化,會調(diào)用finishPendingBroadcastLocked();釋放partial 鎖

    private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {

    ? @Override

    ? public void onReceive(Context context, Intent intent) {

    ? ?? EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,

    ?????????????????????????? SystemClock.uptimeMillis() - mBroadcastStartTime, 1);

    ????????? sendNextBroadcast();

    ? }

    };

    總結(jié):當power接收到亮滅屏調(diào)用后,會先進行設(shè)置手機wakefullness狀態(tài),之后發(fā)送亮滅屏廣播通知其他模塊手機處于亮屏還是滅屏狀態(tài)。并且在發(fā)送廣播過程中power也與AMS,window,input進行交互,通知各模塊手機狀態(tài)發(fā)生了改變,根據(jù)屏幕狀態(tài)各自進行處理。其中發(fā)送亮滅屏廣播的主要實現(xiàn)在Notifier.java中。

    當wakefulness狀態(tài)發(fā)生改變,AMS收到通知。如果亮屏操作,AMS就會通過函數(shù)comeOutOfSleepIfNeedLocked調(diào)用到ActivityStackSupervisor中,將sleep超時消息移除,最后將在棧頂?shù)腶ctivity顯示出來。

    power是通過WindowManagerPolicy與PhoneWindowManager進行交互,當屏幕在喚醒時需要通知window進行更新手勢監(jiān)聽,更新方向監(jiān)聽,更新鎖屏超時時間。最后通知keyguard屏幕點亮了,進行刷新鎖屏界面時間,之后通過回調(diào)接口,回調(diào)回PhoneWindowManager的onShown函數(shù),通知window keyguard準備完成。

    當亮屏時通過InputManagerService將當前屏幕狀態(tài)傳入JNI中進行記錄,當再次發(fā)生power鍵事件可以方便確認該事件是需要亮屏還是滅屏。

    ?

  • Power狀態(tài)的更新和處理
  • 當廣播處理完畢后就會調(diào)用PMS的內(nèi)部函數(shù)updatePowerStateLocked來更新全局電源狀態(tài)。其實在PMS中很多函數(shù)都只是對一些必須的屬性進行賦值,大部分最終都會調(diào)用到updatePowerStateLocked函數(shù)中進行功能執(zhí)行,其中更新電源狀態(tài)主要依據(jù)就是變量mDirty。mDirty就是用來記錄power state的變化的標記位,這樣的狀態(tài)變化在系統(tǒng)中一共定義了12個,每一個狀態(tài)對應(yīng)一個固定的數(shù)字,都是2的倍數(shù)。這樣,若有多個狀態(tài)一塊變化,進行按位取或這樣結(jié)果既是唯一的,又能準確標記出各個狀態(tài)的變化。在updatePowerStateLocked中主要做了如下事情:

    • 首先判斷手機是否處于充電狀態(tài),如果標記位DIRTY_BATTERY_STATE發(fā)生改變時就證明電池狀態(tài)發(fā)生了改變,然后通過對比判斷(通過電池前后變化與充電狀態(tài)的變化),確認手機是否處于充電狀態(tài)。如果手機處于充電狀態(tài)會將表示充電的標記位記入mDirty中。當有USB插拔時我們也可以通過配置信息來決定是否需要點亮屏幕。并且是否在充電或者充電方式發(fā)生改變,系統(tǒng)都會認為發(fā)生了一次用戶事件進行更新最后用戶操作時間,以此來重新計算屏幕超時時間。

    private void updateIsPoweredLocked(int dirty) {

    ? if ((dirty & DIRTY_BATTERY_STATE) != 0) {

    ????????? final boolean wasPowered = mIsPowered;//是否在充電?

    ????????? final int oldPlugType = mPlugType;//充電類型?

    ????????? final boolean oldLevelLow = mBatteryLevelLow;//低電模式

    ????????? mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);

    ????????? mPlugType = mBatteryManagerInternal.getPlugType();

    ????????? mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();

    ????????? mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();

    ????????? if (wasPowered != mIsPowered || oldPlugType != mPlugType) {

    ?????????????????? mDirty |= DIRTY_IS_POWERED;//如果充電中設(shè)置mDirty

    ?????????????????? /* < Bug#696466 optimization for sceenoff */

    ?????????????????? if (wasPowered != mIsPowered)

    ?????????????????????????? SystemProperties.set("sys.sprd.power.ispowered", (mIsPowered? "1": "0"));//設(shè)置屬性sys.sprd.power.ispowered

    ?????????????????? /* Bug#696466 optimization for sceenoff > */

    ?????????????????? //無線充電

    ?????????????????? final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(

    ??????????????????????????????????? mIsPowered, mPlugType, mBatteryLevel);

    ?????????????????? final long now = SystemClock.uptimeMillis();

    ?????????????????? if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,

    ??????????????????????????????????? dockedOnWirelessCharger)) {//插拔USB是否要點亮屏幕

    ?????????????????????????? wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,

    ??????????????????????????????????????????? mContext.getOpPackageName(), Process.SYSTEM_UID);

    ?????????????????? }

    ?????????????????? userActivityNoUpdateLocked(//插拔USB算一次用戶事件,重新設(shè)置最后一次用戶事件的時間點

    ??????????????????????????????????? now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);

    ?????????????????? // Tell the notifier whether wireless charging has started so that

    ?????????????????? // it can provide feedback to the user.

    ?????????????????? if (dockedOnWirelessCharger) {

    ?????????????????????????? mNotifier.onWirelessChargingStarted();

    ?????????????????? }

    ????????? }

    ????????? if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {//低電模式

    ?????????????????? if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {

    ?????????????????????????? mAutoLowPowerModeSnoozing = false;

    ?????????????????? }

    ?????????????????? updateLowPowerModeLocked();//更新低電模式

    ????????? }

    ? }

    }

    • 更新wakefulness

    for (;;) {

    ? int dirtyPhase1 = mDirty;

    ? dirtyPhase2 |= dirtyPhase1;

    ? mDirty = 0;

    ? updateWakeLockSummaryLocked(dirtyPhase1);

    ? updateUserActivitySummaryLocked(now, dirtyPhase1);

    ? if (!updateWakefulnessLocked(dirtyPhase1)) {

    ????????? break;

    ? }

    }

    updateWakeLockSummaryLocked函數(shù)將wakeLock的類型用mWakeLockSummary進行記錄,最后與Wakefulness狀態(tài)結(jié)合重新算出新的mWakeLockSummary值,再判斷是否需要睡眠時會使用。

    之后updateUserActivitySummaryLocked就會更新屏幕超時時間,根據(jù)最后一次的用戶事件與屏幕超時時間與dim持續(xù)時間來計算屏幕超時的時間,然后與現(xiàn)在的時間進行對比,來決定屏幕要繼續(xù)高亮,還是要變?yōu)閐im狀態(tài)。

    PowerManagerHandler接收屏幕超時的消息, 并且調(diào)用handleUserActivityTimeout進行處理, 該函數(shù)之后就在Handler線程中運行

    ?

    private final class PowerManagerHandler extends Handler {?

    ??? public PowerManagerHandler(Looper looper) {?

    ??????? super(looper, null, true /*async*/);?

    ??? }?

    ?

    ??? @Override?

    ??? public void handleMessage(Message msg) {?

    ??????? switch (msg.what) {?

    ??????????? case MSG_USER_ACTIVITY_TIMEOUT:?

    ??????????????? handleUserActivityTimeout();??? //處理用戶超時事件?

    ??????????????? break;?

    ??????????? case MSG_SANDMAN:?

    ??????????????? handleSandman();?

    ??????????????? break;?

    ??????????? case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:?

    ????? ??????????handleScreenBrightnessBoostTimeout();?

    ??????????????? break;?

    ??????? }?

    ??? }?

    }?

    ?

    private void handleUserActivityTimeout() { // runs on handler thread?

    ??? synchronized (mLock) {?

    ??????? if (DEBUG_SPEW) {?

    ??????????? Slog.d(TAG, "handleUserActivityTimeout");?

    ??????? }?

    ?

    ??????? mDirty |= DIRTY_USER_ACTIVITY;? //設(shè)置有用戶活動的mDirty值?

    ??????? updatePowerStateLocked();?? //更新電源狀態(tài), 最后去判斷是否要睡眠?

    ??? }?

    }?

    ?

    根據(jù)前面流程圖可以看出更新wakefulness過程是通過一個死循環(huán)來執(zhí)行的,只有調(diào)用函數(shù)updateWakefulnessLocked返回false時才會跳出循環(huán)。在循環(huán)中對wakeLockSummary進行更新,并且更新自動滅屏時間后,進行判斷系統(tǒng)是否該睡眠了,是否可以跳出循環(huán)。

    在updateWakefulnessLocked中主要根據(jù)是否存在wakeLock,用戶活動進行判斷設(shè)備是否需要進入睡眠狀態(tài)。從函數(shù)isBeingKeptAwakeLocked可以看出當device拿著一個wake lock,有用戶事件,有距離傳感器等都不會滅屏進行睡眠狀態(tài)。如果需要睡眠就會往下面調(diào)用,最后跳出循環(huán)。

    private boolean updateWakefulnessLocked(int dirty) {?

    ??? boolean changed = false;?

    ??? if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED?

    ??????????? | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE?

    ??????????? | DIRTY_DOCK_STATE)) != 0) {?

    ??????? if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {?? //mWakefulness為AWAKE, 并且到了睡覺時間, 就去睡覺?

    ??????????? if (DEBUG_SPEW) {?

    ??????????????? Slog.d(TAG, "updateWakefulnessLocked: Bed time...");????

    ??????????? }?

    ??????????? final long time = SystemClock.uptimeMillis();?

    ??????????? if (shouldNapAtBedTimeLocked()) {??

    ??????????????? changed = napNoUpdateLocked(time, Process.SYSTEM_UID);? //睡覺前先小憩一會?

    ??????????? } else {?

    ??????????????? changed = goToSleepNoUpdateLocked(time,?

    ??????????????????????? PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);? //直接睡覺?

    ??????????? }?

    ??????? }?

    ??? }?

    ??? return changed;?

    }?

    [java] view plain copy

    private boolean isItBedTimeYetLocked() {// 對所有該喚醒的情況取反, 就是該休眠了?

    ??? return mBootCompleted && !isBeingKeptAwakeLocked();???

    }?

    private boolean isBeingKeptAwakeLocked() {?

    ??? return mStayOn? //設(shè)置了stay on?

    ??????????? || mProximityPositive? //距離傳感器返回一個positive結(jié)果,保持喚醒?

    ??????????? || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0? //當有wake lock時保持喚醒?

    ??????????? || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT?

    ??????????????????? | USER_ACTIVITY_SCREEN_DIM)) != 0?? //有user activity時保持喚醒?

    ??????????? || mScreenBrightnessBoostInProgress;?

    }?

    [java] view plain copy

    ???? mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,?

    ??????????? Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,?

    ??????????? mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,?

    ??????????? UserHandle.USER_CURRENT) != 0);???? //從settings數(shù)據(jù)庫獲取對應(yīng)值?

    ??? mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,?

    ??????????? Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,?

    ??????????? mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,?

    ??????????? UserHandle.USER_CURRENT) != 0);?

    ?

    ?private boolean shouldNapAtBedTimeLocked() {? //當返回true, 設(shè)備自動nap?

    ??? return mDreamsActivateOnSleepSetting?

    ??????????? || (mDreamsActivateOnDockSetting?

    ??????????????????? && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);?

    }?

    [java] view plain copy

    private boolean napNoUpdateLocked(long eventTime, int uid) {?

    ??? if (DEBUG_SPEW) {?

    ??????? Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);?

    ??? }?

    ?

    ??? if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE?

    ??????????? || !mBootCompleted || !mSystemReady) {?

    ??????? return false;?

    ??? }?

    ?

    ??? Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");?

    ??? try {?

    ??????? Slog.i(TAG, "Nap time (uid " + uid +")...");?

    ?

    ??????? mSandmanSummoned = true;?

    ??????? setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);? //設(shè)置WAKEFULNESS_DREAMING?

    ??? } finally {?

    ??????? Trace.traceEnd(Trace.TRACE_TAG_POWER);?

    ??? }?

    ??? return true;?

    }?

    調(diào)用goToSleepNoUpdateLocked進行睡眠, 當按power鍵滅屏是也會調(diào)用該函數(shù).

    ?

    [java] view plain copy

    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {?

    ??? if (DEBUG_SPEW) {?

    ??????? Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime?

    ??????????????? + ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);?

    ??? }?

    ?

    ??? if (eventTime < mLastWakeTime?

    ??????????? || mWakefulness == WAKEFULNESS_ASLEEP?

    ??????????? || mWakefulness == WAKEFULNESS_DOZING?

    ??????????? || !mBootCompleted || !mSystemReady) {?

    ??????? return false;?? //判斷設(shè)備是否應(yīng)該睡眠?

    ??? }?

    ?

    ??? Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");?

    ??? try {?

    ??????? switch (reason) {?? //輸出滅屏的原因?

    ??????????? case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:?

    ??????????????? Slog.i(TAG, "Going to sleep due to device administration policy "?

    ??????????????????????? + "(uid " + uid +")...");?

    ??????????????? break;?

    ??????????? case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:?

    ??????????????? Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");?

    ?????? ?????????break;?

    ??????????? case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:?

    ??????????????? Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");?

    ??????????????? break;?

    ??????????? case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON: ?

    ??????????????? Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");?

    ??????????????? break;?

    ??????????? case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:?

    ??????????????? Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");?

    ??????????????? break;?

    ??????????? case PowerManager.GO_TO_SLEEP_REASON_HDMI:?

    ??????????????? Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");?

    ??????????????? break;?

    ??????????? default:?

    ??????????????? Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");?

    ??????????????? reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;?

    ??????????????? break;?

    ??????? }?

    ?

    ??????? mLastSleepTime = eventTime;?

    ??????? mSandmanSummoned = true;?

    ? ??????setWakefulnessLocked(WAKEFULNESS_DOZING, reason);?

    ?

    ??????? // Report the number of wake locks that will be cleared by going to sleep.?

    ??????? int numWakeLocksCleared = 0;?

    ??????? final int numWakeLocks = mWakeLocks.size();???

    ??????? for (int i = 0; i < numWakeLocks; i++) {? //遍歷所有的wakeLocks, 將FULL, BRIGHT, DIM Locks,計入numWakeLocksCleared中?

    ??????????? final WakeLock wakeLock = mWakeLocks.get(i);?

    ??????????? switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {?

    ??????????????? case PowerManager.FULL_WAKE_LOCK:?

    ??????????????? case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:?

    ??????????????? case PowerManager.SCREEN_DIM_WAKE_LOCK:?

    ??????????????????? numWakeLocksCleared += 1;?

    ??????????????????? break;?

    ??????????? }?

    ??????? }?

    ??????? EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);?

    ?

    ??????? // Skip dozing if requested.?

    ??????? if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {?

    ??????????? reallyGoToSleepNoUpdateLocked(eventTime, uid); //如果沒有doze流程,直接設(shè)置WAKEFULNESS_ASLEEP?

    ??????? }?

    ??? } finally {?

    ??????? Trace.traceEnd(Trace.TRACE_TAG_POWER);?

    ??? }?

    ??? return true;?? //返回true?

    }?

    當?shù)谝粋€for循環(huán)中將所有的狀態(tài)都設(shè)置好了, 并且此時也沒有重要的mDirty發(fā)生變化, 在下一次循環(huán)中mDirty的值為0, updateWakefulnessLocked返回false,就會跳出循環(huán).

    當跳出循環(huán)之后在函數(shù)updateDisplayPowerStateLocked中進行獲取需要請求的設(shè)備電源狀態(tài)是亮還是滅或者dim,判斷是否開啟了自動調(diào)節(jié)亮度開關(guān),是否使用了距離傳感器,并經(jīng)過一系列的計算獲取亮度值等,最終都記錄到DisplayPowerRequest中,經(jīng)過DMS傳入DPC中,進行處理。

    在PowerManagerService中對各種狀態(tài)進行判斷后,將其數(shù)值封裝進DisplayPowerRequest中傳入DisplayPowerController中進一步處理。在亮屏過程中DisplayPowerController會根據(jù)傳過來的數(shù)值來設(shè)置新的電源狀態(tài)為亮屏,然后調(diào)用DisplayPowerState來對狀態(tài)進行設(shè)置。由于此時ColorFade level(就是在手機屏幕的一層surface,當level為0是為一層黑幀,level為1.0時為透明)的值為0,表示屏幕還沒有繪制好,所以此時需要block screen直到window界面繪制完成。當需要亮屏時調(diào)用PhoneWindowManager的screenTurningOn函數(shù),通知window屏幕就要點亮了。然后調(diào)用WMS中函數(shù)waitForAllWindowsDrawn函數(shù)等待將所有需要繪制的window繪制完成后回調(diào)回來,超時時間為1000ms。在WMS中獲取需要繪制的window將其加入mWaitingForDrawn中等待繪制,通過檢查mWaitingForDrawn是否為空來判斷,window是否繪制完成。此時screenTurningOn函數(shù)就執(zhí)行完了,剩下的就是等待windows繪制完成。

    總結(jié)

    以上是生活随笔為你收集整理的Android 8.0 手机亮灭屏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。