zoukankan      html  css  js  c++  java
  • 安卓手机来电亮屏流程分析

    来电亮屏流程分析

    本文档是针对手机来电时候自主点亮屏幕这一流程的分析,非常自然的就将其分为2个阶段,第一个是来电,第二个是点亮屏幕。

    来电的流程:

    来电消息是从RIL层接收到的。然后才開始传递上来。

    AT      : RING                             

    AT      : AT< RING                            

    AT      : RIL_URC_READER:RING                 

    AT      : RIL_URC_READER Enter processLine    

    use-Rlog/RLOG-RIL: Nw URC:RING                

    use-Rlog/RLOG-RIL: receiving RING!!!!!!       

    use-Rlog/RLOG-RIL: receiving first RING!!!!!! 

    use-Rlog/RLOG-RIL: sending ECPI!!!!!!  

     同一时候也向RIL.java上报UNSOL_RESPONSE_CALL_STATE_CHANGED消息,RIL.java收到将才标志转换为RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,这告诉我们真正处理代码在哪个分支里,看以下代码:  

    processUnsolicited (Parcel p) {//主动上报的命令  

    …省略代码……  

    case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:  

    mCallStateRegistrants .notifyRegistrants(new AsyncResult(null, null, null);

    break; 

    }

    上面这个通知发到GsmCallTracker.java文件里的构造函数中。在这里面就能看到要找的事件(EVENT_CALL_STATE_CHANGE)了:

     GsmCallTracker (GSMPhone phone) {

        this.phone = phone;

        cm = phone.mCM;

        cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);

        cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);

        cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);

    在文件BaseCommands.java中有对函数的实现:

    public void registerForCallStateChanged(Handler h, int what, Object obj) {

            Registrant r = new Registrant (h, what, obj);

            mCallStateRegistrants.add(r);

        }   

    当然EVENT_CALL_STATE_CHANGE这个消息的上会有非常多原因。除了来电消息RING,还有挂断消息NOCARRIER、电话状态改变消息CLCC等,RIL都会作为EVENT_CALL_STATE_CHANGE报给GsmCallTracker.javaGsmCalTracker.java收到之后会。在handleMessage()相应分支中进行处理。代码例如以下:

    case EVENT_CALL_STATE_CHANGE:

    pollCallsWhenSafe();

    break;

    进入pollCallsWhenSafe()方法中,又见消息。这回是主动查询CLCC,查询一下通话列表,即查询全部的通话详情,在这个分支 EVENT_POLL_CALLS_RESULT里获得查询结果:

        protected void pollCallsWhenSafe() {

            needsPoll = true;

            if (checkNoOperationsPending()) {

                lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);

                cm.getCurrentCalls(lastRelevantPoll);

            }

    }

    处理EVENT_POLL_CALLS_RESULT消息是在GsmCallTracker.java中:

        case EVENT_POLL_CALLS_RESULT:

            ar = (AsyncResult)msg.obj;

     

            if (msg == lastRelevantPoll) {

                if (DBG_POLL) log(

                        "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");

                needsPoll = false;

                lastRelevantPoll = null;

                handlePollCalls((AsyncResult)msg.obj);

            }

    break;

    进入handlePollCalls()方法中。在这种方法里将揭开CLCC命令返回參数和connections集合里的元素的是什么关系?handlePollCalls()方法中会进行一个for循环操作。底层查的通话列表用DriverCall类表示。FrameWork层则抽象为GsmConnection类。在这里先看一个关于CLCC命令的样例:

        CLCC : 1、0、2、0、0   1881234578 …..

        先是CLCC这个command。后面

        第一个參数表示 index序号,

        每二个如是0表示来电、1表示去电,

        第三个是电话状态。

        第四个表示是数据业务还是语音业务。

        第五个表示是否是视频会议。后面再跟着号码。

    CLCC返回的电话列表中,第一个參数就是没路通话的编号,从1開始编号,相同能够看到GsmCallTracker中保存的GsmConnection的集合connections集合对象是一个数组,数组编号是从0開始的,所以我们会看到会有一个dc.index == i+1;的操作。相应关系就是这里建立的。

    之后会把底层查的DriverCall对象和GsmCallTracker中保存的GsmConnection对象进行比較。如DriverCall对象为空,我们本地保持的GsmConnection对象存在,非常显然,是这路电话挂断了。反之如过DriverCall对象有,GsmConnection对象不存在,则是一个来电:

    if (conn == null && dc != null){  

    if (newRinging != null) {

          phone.notifyNewRingingConnection(newRinging);

    }}

    在phoneBase.java里发出通知  

    protected void notifyNewRingingConnectionP(Connection cn) {  

    if (!mIsVoiceCapable)  

    return;  

    syncResult ar = new AsyncResult(null, cn, null);  

    mNewRingingConnectionRegistrants.notifyRegistrants(ar);  

     }

    再后面的代码就离开Framework层了,这里把来电消息通知给上层应用:

    private void registerForNotifications() {  

    mCM.registerForNewRingingConnection(this,PHONE_NEW_RINGING_CONNECTION, null);  

     ….后面的代码省略   

     }   

    public void registerForNewRingingConnection(  

    Handler h, int what, Object obj) {  

    checkCorrectThread(h);        

    mNewRingingConnectionRegistrants.addUnique(h, what, obj);  

    }

    PHONE_NEW_RINGING_CONNECTION这个消息发送出去之后,是在CallNotifier.java文件里处理的:

    public void handleMessage(Message msg) {

            if(handleMessageMTK(msg)) {

                return;

            }

            switch (msg.what) {

                case CallStateMonitor.PHONE_NEW_RINGING_CONNECTION:

                    log("RINGING... (new)");

                    onNewRingingConnection((AsyncResult) msg.obj);

                    mSilentRingerRequested = false;

                    break;

    }…省略代码…

    }

    以下有对来电铃音连接事件的处理:

    /**

    * Handles a "new ringing connection" event from the telephony layer.

    */

    private void onNewRingingConnection(AsyncResult r) {

            Connection c = (Connection) r.result;

            log("onNewRingingConnection(): state = " + mCM.getState() + ", conn = { " + c + " }");

            Call ringing = c.getCall();

            Phone phone = ringing.getPhone(); 

    if (ignoreAllIncomingCalls(phone)) {//在这里面会有去查询黑名单或则其它操作,从而决定是否自己主动拒接来电

                

                PhoneUtils.hangupRingingCall(ringing);

                return;

            }      

    …省略代码…        

    Call.State state = c.getState();//手机状态

            // State will be either INCOMING or WAITING.

            if (VDBG) log("- connection is ringing!  state = " + state);        

            if (PhoneUtils.isRealIncomingCall(state)) {                       

    PhoneUtils.setAudioControlState(PhoneUtils.AUDIO_RINGING);           

                if (mApplication.getWiredHeadsetManager().isHeadsetPlugged() && isIncomingMuteOrVibrate()) {

                    playCallWaitingTone();

                }           

                PhoneUtils.setAudioMode();

                } else {           

                 mShouldSkipRing = true;

             }

            startIncomingCallQuery(c);       

            sendEmptyMessageDelayed(DELAY_AUTO_ANSWER, 3000);       

            if (VDBG) log("- onNewRingingConnection() done.");

        }

    在这之后会依据获取当前手机的状态模式推断是否处于摘机状态等。

    PhoneConstants.State state = mCM.getState();

    推断响铃的模式:

    public void setRingerMode(int ringerMode) {…代码省略…}

    startIncomingCallQuery(c)//取数据库查找相应的资源,比方用什么铃音就会去里面查找:

    private void startIncomingCallQuery(Connection c) {

    if (shouldStartQuery) {

    setDefaultRingtoneUri(c);//设置默认的铃声

    }

    }

    public void applyDeviceVolume(int device) {…代码省略…}//设置设备音量

    public Uri getDefaultRingtone(int type) {}//依据传入的type类型设置默认的铃音,1为TYPE_RINGTONE,2为TYPE_NOTIFICATION

    public static CallerInfoToken startGetCallerInfo(Context context, Connection c,CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie,RawGatewayInfo info){}//这里面能够看到呼叫方的号码,和当前电话用的什么网络。

    startIncomingCallQuery中最后会运行响铃并通知有来电了:

    private void ringAndNotifyOfIncomingCall(Connection c) {

    mCallModeler.onNewRingingConnection(c);

    }

    函数onNewRingingConnection的实现:

    Call onNewRingingConnection(Connection conn) {

            Log.i(TAG, "onNewRingingConnection");

            updateDualTalkCallInfo();

            final Call call = getCallFromMap(mCallMap, conn, true);

            if (call != null) {

                updateCallFromConnection(call, conn, false);

                for (int i = 0; i < mListeners.size(); ++i) {

                    mListeners.get(i).onIncoming(call);

                }

            }

            PhoneGlobals.getInstance().updateWakeState();//这里開始更新唤醒状态

            return call;

        }

    更新唤醒状态:

    void updateWakeState() {

    …省略代码…

    requestWakeState(keepScreenOn ?

     WakeState.FULL : WakeState.SLEEP);

    }

    public void requestWakeState(WakeState ws) {

            synchronized (this) {

                if (mWakeState != ws) {

                    if(is82SMBPlugged()){

                        ws = WakeState.SLEEP;

                    }

                    switch (ws) {

                        case PARTIAL:

                            mPartialWakeLock.acquire();

                            if (mWakeLock.isHeld()) {

                                mWakeLock.release();

                            }

                            break;

                        case FULL:

                            mWakeLock.acquire();

                            if (mPartialWakeLock.isHeld()) {

                                mPartialWakeLock.release();

                            }

                            break;

                        case SLEEP:

                        default:

                            if (mWakeLock.isHeld()) {

                                mWakeLock.release();

                            }

                            if (mPartialWakeLock.isHeld()) {

                                mPartialWakeLock.release();

                            }

                            break;

                    }

                    mWakeState = ws;

                }

            }

        }

    以上就基本上完毕了来电流程的总结。

    亮屏的流程:

    点亮屏幕是从唤醒開始的:

    首先依据mProximityPositive的值检查屏幕当前是否处于远离状态,假设是远离状态的话才会去点亮,否则是不会去点亮的。

    假设处于远离状态须要去推断唤醒锁是否须要更新。假设须要更新那么就会去运行更新操作。

    函数wakeUpNoUpdateLocked(eventTime)的作用就是去推断唤醒锁是否须要更新,首先会依据mWakefulness的值去运行相应的操作,假设为WAKEFULNESS_ASLEEP,且mIPOShutdown为false时候。运行例如以下操作:

    case WAKEFULNESS_ASLEEP://接收到唤醒消息

        if (!mIPOShutdown) {

            sendPendingNotificationsLocked();

            mNotifier.onWakeUpStarted();//開始唤醒

            mSendWakeUpFinishedNotificationWhenReady = true;

        }

        break;

    要開始唤醒就须要捕获亮屏堵塞个数。每捕获一次就添加一个。

    然后更新广播锁,即是运行函数updatePendingBroadcastLocked()。首先也是捕获堵塞块,也是捕获一次就添加一个,然后发送一个MSG_BROADCAST的消息。且这个消息是异步运行的。

    接收到MSG_BROADCAST这个消息后会运行sendNextBroadcast()方法。假设powerState的值等于POWER_STATE_AWAKE,那么就发送唤醒广播。否则就发送休眠广播。

    if (powerState == POWER_STATE_AWAKE) {

    sendWakeUpBroadcast();//发起唤醒广播

    } else {

    sendGoToSleepBroadcast(goToSleepReason);//发送休眠广播

    }

    推断用户界面锁是否更新,依据mUserActivityPending的值决定是否发送异步运行的消息MSG_USER_ACTIVITY,从而运行方法sendUserActivity()。

    发送的唤醒广播最重要的操作就是运行方法:

    ActivityManagerNative.getDefault().wakingUp(),这种方法不是马上就能完毕的。可能会有一定延迟才干完毕。可是当他完毕后,且系统已经准备好就会发出一个唤醒已经结束的广播:

    if (ActivityManagerNative.isSystemReady()) {

    mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,mWakeUpBroadcastDone, mHandler, 0, null, null);        

    } else {

    EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);

        sendNextBroadcast();

    }

    这个广播的接收器例如以下:

    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();

            }

    }

    这里的广播从发送到接收到有一定延迟。甚至可能出现有巨大延迟的状况,由于仅仅有系统觉得亮屏结束的时候才会认定广播接收完毕。

    当确认须要更新唤醒锁。即是wakeUpNoUpdateLocked(eventTime)的值为true时,就会去运行更新就是运行方法updatePowerStateLocked()。

    updatePowerStateLocked(eventTime)这个函数非常重要,他会去更新非常多锁的状态代码例如以下:

    private void updatePowerStateLocked() {

    if (!mSystemReady || mDirty == 0) {

         return;

        }

    updateIsPoweredLocked(mDirty);

    updateStayOnLocked(mDirty);

     

    final long now = SystemClock.uptimeMillis();

    int dirtyPhase2 = 0;

    for (;;) {

        int dirtyPhase1 = mDirty;

        dirtyPhase2 |= dirtyPhase1;

        mDirty = 0;

        updateWakeLockSummaryLocked(dirtyPhase1);

    updateUserActivitySummaryLocked(now, dirtyPhase1);

        if (!updateWakefulnessLocked(dirtyPhase1)) {

            break;

        }

    }

     

    updateDreamLocked(dirtyPhase2);

    updateDisplayPowerStateLocked(dirtyPhase2);

     

    if (mDisplayReady) {

         sendPendingNotificationsLocked();

    }

    updateSuspendBlockerLocked();

    }

    updateWakeLockSummaryLocked(dirtyPhase1):更新唤醒锁主锁,依据wakeLocked中flag值与上PowerManager.WAKE_LOCK_LEVEL_MASK进行匹配,依据各种匹配结果对mWakeLockSummary进行赋值。这里一共同拥有例如以下几种锁:

    PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。

    SCREEN_DIM_WAKE_LOCK:保持CPU 运转,同意保持屏幕显示但有可能是灰的,同意关闭键盘灯

    SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转。同意保持屏幕高亮显示。同意关闭键盘灯

    FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度

    我们这里关注的就是FULL_WAKE_LOCK。当mWakefulness不为WAKEFULNESS_ASLEEP

    mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT。假设此时mWakefulness还等于WAKEFULNESS_AWAKE那么还要或上WAKE_LOCK_STAY_AWAKE。

    updateUserActivitySummaryLocked(now, dirtyPhase1):这个函数作用就依据不同的情况设置mUserActivitySummary的值,而此时就须要注意给其赋值的三个參数,各自是:按键亮:USER_ACTIVITY_BUTTON_BRIGHT。屏幕亮:USER_ACTIVITY_SCREEN_BRIGHT。和屏幕暗:USER_ACTIVITY_SCREEN_DIM。

    updateDisplayPowerStateLocked(dirtyPhase2):这个函数的作用是更新显示状态锁的。这里面最重要的newScreenState屏幕状态值,screenBrightness屏幕亮度值。

    函数中会对按键背光亮灭做处理:

    if ( ( (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0 ) ||

           ( (mUserActivitySummary & USER_ACTIVITY_BUTTON_BRIGHT) != 0) ) {

    mButtonLight.setBrightness(screenBrightness);

    } else {

    mButtonLight.turnOff();

    }

    mDisplayReady显示是否准备好,他会通过mDisplayPowerController的requestPowerState方法推断得出,注意这里有延时,或者是说有了反馈消息才干获得mDisplayReady的值。requestPowerState方法返回的是mDisplayReadyLocked。而仅仅有当change的值为false,即是状态锁没有更新的时候。

    在有更改的时候可能会去发送更新电源状态锁即是运行函数sendUpdatePowerStateLocked(),而这个函数的作用就是发出一个更新电源状态的消息:MSG_UPDATE_POWER_STATE。接收消息的地方是:

    switch (msg.what) {

    case MSG_UPDATE_POWER_STATE:

        updatePowerState();

        break;

    }

    updatePowerState():更新电源状态,这个函数非常重要,后文重点说明。

    updateSuspendBlockerLocked():这个函数主要是对mWakeLockSuspendBlocker和mDisplaySuspendBlocker的获取和释放进行操作。并对相应的锁进行设值,获取设为true。释放设为false。

    updateDreamLocked(dirtyPhase2):更新休眠锁,这个函数是对休眠状态下进行一些处理。当中会发出一个MSG_SANDMAN消息,处理这个消息的是handleSandman()方法。

    以下重点介绍下updatePowerState()方法:

    private void updatePowerState() {

    …省略代码…

    …依据距离传感器设置亮灭屏和是否激活距离传感器…

    …光感功能…

    if (wantScreenOn(mPowerRequest.screenState)) {//反馈屏幕状态亮屏 

         if (mScreenAutoBrightness >= 0 && mLightSensorEnabled && mPowerRequest.useAutoBrightness) {                

                    target = mScreenAutoBrightness;

                    slow = mUsingScreenAutoBrightness;

                    mUsingScreenAutoBrightness = true;

                } else {           

                    target = mPowerRequest.screenBrightness;

                    slow = false;

                    mUsingScreenAutoBrightness = false;

                }

            if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {//灭屏

                    target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,

                            mScreenBrightnessDimConfig);

                    slow = false;               

                    if (FeatureOption.MTK_AAL_SUPPORT) {

                        nativeSetScreenState(SCREEN_STATE_DIM, clampScreenBrightness(target));

                    }               

                } else if (wasDim) {

                    slow = false;                

                    if (FeatureOption.MTK_AAL_SUPPORT) {

                        nativeSetScreenState(SCREEN_STATE_ON, clampScreenBrightness(target));

                    }

                }

                animateScreenBrightness(clampScreenBrightness(target),

                        slow ?

     BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);//动态决定缓慢改变亮度还是迅速改变

            } else {            

                mUsingScreenAutoBrightness = false;

            }

      //动态运行屏幕亮或者屏幕灭

          if (!mScreenOffBecauseOfProximity || mPowerRequest.forceWakeUpEnable) {

                if (wantScreenOn(mPowerRequest.screenState)) {            

                    if (!mElectronBeamOffAnimator.isStarted()) {

                        setScreenOn(true); //设置屏亮

                        mSbScreenOnIsStart = true;

                        if (mPowerRequest.blockScreenOn//亮屏处于堵塞状态且电量等级为0,0为灭屏,1为亮屏

                                && mPowerState.getElectronBeamLevel() == 0.0f) {                    

                            blockScreenOn();//堵塞亮屏

                            mPowerState.updateElectronBeam();

                        } else {

                            unblockScreenOn();//开启亮屏

                            if (USE_ELECTRON_BEAM_ON_ANIMATION) {

    条件一直为false,里面代码忽略

                            } else {//设置亮屏

                                mPowerState.setElectronBeamLevel(1.0f);                            

                                mPowerState.dismissElectronBeam();

                                mSbScreenOnIsStart = false;

                            }

                        }

                    }

                } else {//灭屏时就会运行这里              

                    if (!mElectronBeamOnAnimator.isStarted()) {

                        if (!mElectronBeamOffAnimator.isStarted()) {

                            if (mPowerState.getElectronBeamLevel() == 0.0f || mShutDownFlag_D) {

                                setScreenOn(false);//设置灭屏

                                mShutDownFlag_D = false; 

                            } else if (mPowerState.prepareElectronBeam(

                                    mElectronBeamFadesConfig ?

                                            ElectronBeam.MODE_FADE :

                                                    ElectronBeam.MODE_COOL_DOWN)

                                    && mPowerState.isScreenOn()) {

                                mElectronBeamOffAnimator.start();

                            } else {;

                                mElectronBeamOffAnimator.end();

                            }

                        }

                    }

                }

            }

            if (mustNotify

                    && !mScreenOnWasBlocked

                    && !mElectronBeamOnAnimator.isStarted()

                    && !mElectronBeamOffAnimator.isStarted()

                    && mPowerState.waitUntilClean(mCleanListener)) {

                synchronized (mLock) {//确定显示是否准备好,亮度是否变化。异步

                    if (!mPendingRequestChangedLocked) {

                        mDisplayReadyLocked = true;

                    }

                }

                sendOnStateChangedWithWakelock();

            }

        }

    setScreenOn(boolean on):设置亮屏的方法:

    if (mPowerState.isScreenOn() != on) {//要处于亮屏状态

         mPowerState.setScreenOn(on);

         if (on) {

              mNotifier.onScreenOn();

         } else {

             mNotifier.onScreenOff();

         }          

    }

    public void setScreenOn(boolean on) {// mPowerState.setScreenOn(on)

        if (mScreenOn != on) {

            mScreenOn = on;

            mScreenReady = false;

            scheduleScreenUpdate();//使屏幕更新

        }

    }

    public void onScreenOn() {

            try {

                mBatteryStats.noteScreenOn();

            } catch (RemoteException ex) {

            }

        }

    scheduleScreenUpdate()终于会去实现接口mScreenUpdateRunnable,会依据是否亮屏mScreenOn ,电子束等级mElectronBeamLevel,屏幕亮度值mScreenBrightness这三个參数设置更新后的屏幕亮度。然后会对方法返回值进行推断即是:

    mPhotonicModulator .setState(mScreenOn, brightness)的返回值,它返回的是mChangeInProgress的值,假设为true,则觉得屏幕更新准备好,假设为false。则觉得屏幕更新没有准备好。在这函数运行中可能去实现一个接口,而接口mTask的实现是:

       private final Runnable mTask = new Runnable() {

                public void run() {                

    //申请变更知道完毕

                    for (;;) {//强制反复运行,直到有条件跳出来

                        final boolean on;

                        final boolean onChanged;

                        final int backlight;

                        final boolean backlightChanged;

                        synchronized (mLock) {

                            on = mPendingOn;

                            onChanged = (on != mActualOn);

                            backlight = mPendingBacklight;

                            backlightChanged = (backlight != mActualBacklight);

                            if (!onChanged && !backlightChanged) {

                                mChangeInProgress = false;

                                break;

                            }

                            mActualOn = on;

                            mActualBacklight = backlight;

                        }

                        if (onChanged && on) {//有变化且是需点亮状态

                            mDisplayBlanker.unblankAllDisplays();//点亮屏幕

                        }

                        if (mShutDownFlag) {

                            try {

                                Thread.sleep(mDelay);  

                            } catch (InterruptedException e) {}

                        }

                        if (backlightChanged) {//期望亮度值mPendingBacklight和真实亮度值mActualBacklight是否相等,相等时backlightChanged为false,否则为true

                            mBacklight.setBrightness(backlight);//这里会去底层设置点亮屏。非常重要。backlightChanged才会决定亮不亮屏

                            mDisplayBlanker.setBlNotify();

                            if (on) {

                                Handler monitorHandler = MessageMonitorLogger.getMsgLoggerHandler();

                                if (monitorHandler != null && monitorHandler.hasMessages(MessageMonitorLogger.START_MONITOR_EXECUTION_TIMEOUT_MSG, monitorHandler)) {                                monitorHandler.removeMessages(MessageMonitorLogger.START_MONITOR_EXECUTION_TIMEOUT_MSG, monitorHandler);

                                                               }

                            }

                        }

                        if (onChanged && !on) {//有变化且是需熄灭状态

                            mDisplayBlanker.blankAllDisplays();//熄灭屏幕

                        }

                    }

                    postScreenUpdateThreadSafe();

                }

        };

       public void unblankAllDisplays() {//开启全显示,这里有可能会有延时

        synchronized (this) {

            nativeSetAutoSuspend(false);

            nativeSetInteractive(true);            mDisplayManagerService.unblankAllDisplaysFromPowerManager();

             mBlanked = false;

             mHDMI.hdmiPowerEnable(true); 

             mWfdShouldBypass = false;

             }

       }

    unblankAllDisplaysFromPowerManager():开启显示,终于会依据全显示的状态值来确定设备开不开启锁,代码例如以下:

    switch (mAllDisplayBlankStateFromPowerManager) {

                    case DISPLAY_BLANK_STATE_BLANKED:

                        device.blankLocked();

                        break;

                    case DISPLAY_BLANK_STATE_UNBLANKED:

                        device.unblankLocked();

                        break;

                }

    wakingUp()是在ActivityManagerNative.getDefault().wakingUp()调用时才运行,而要掉这里应该是监听到了亮屏,监听器: mPolicy.screenTurningOn(mScreenOnListener)。

    private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =

                new WindowManagerPolicy.ScreenOnListener() {

            @Override

            public void onScreenOn() {

                synchronized (mLock) {

                    if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {

                        mScreenOnBlockerAcquired = false;

                        mScreenOnBlocker.release();

                    }

                }

            }

        }//这个非常重要

    public void wakingUp() {

           if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)

                    != PackageManager.PERMISSION_GRANTED) {

                throw new SecurityException("Requires permission "

                        + android.Manifest.permission.DEVICE_POWER);

            }

     

            synchronized(this) {

                mWentToSleep = false;

                updateEventDispatchingLocked();

                comeOutOfSleepIfNeededLocked();//从休眠状态退出来

            }

        }

    手机在感受到距离由近及远的时候也会去点亮屏幕:

    private final SensorEventListener mProximitySensorListener = new SensorEventListener() {//距离传感器监听器

            @Override

            public void onSensorChanged(SensorEvent event) {

                if (mProximitySensorEnabled) {

                    final long time = SystemClock.uptimeMillis();

                    final float distance = event.values[0];

                    boolean positive = distance >= 0.0f && distance < mProximityThreshold;

                    handleProximitySensorEvent(time, positive); // positive 的值为false,表示离开。为true,表示靠近。

     

                }

            }

        };

     

    当mDisplayReady为true时会运行方法sendPendingNotificationsLocked(),这个函数的作用就是发送关于锁结束的提示,不管是亮屏结束还是熄屏结束都会调用这里,实现的地方例如以下:

    if (mSendWakeUpFinishedNotificationWhenReady) {//唤醒过程结束

        mSendWakeUpFinishedNotificationWhenReady = false;

        mNotifier.onWakeUpFinished();

    }

    if (mSendGoToSleepFinishedNotificationWhenReady) {//休眠过程结束

        mSendGoToSleepFinishedNotificationWhenReady = false;

        mNotifier.onGoToSleepFinished();

    }

    mSendWakeUpFinishedNotificationWhenReady这个值在刚进入唤醒阶段就被置为了true的,所以最重要的还是什么时候mDisplayReady的值为true。

    真正运行亮屏的是底层驱动去做的,而通知底层驱动的是函数:

    public void setBrightness(int brightness) {// Task中的

    //mBacklight.setBrightness(backlight)

    setBrightness(brightness, BRIGHTNESS_MODE_USER);

    }

     

    public void setBrightness(int brightness, int brightnessMode) {

    synchronized (this) {

         int color = brightness & 0x000000ff;

         color = 0xff000000 | (color << 16) | (color << 8) | color;

                    setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);

    }

    }

    protected void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {

    if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {

    setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);//这个函数就会实现去通知底层驱动更新屏幕亮度

    }

    }

  • 相关阅读:
    MODIS系列之NDVI(MOD13Q1)三:.jdk文件配置+MRT安装
    MODIS系列之NDVI(MOD13Q1)二:modis数据相关信息
    MODIS系列之NDVI(MOD13Q1)一:数据下载(二)基于FTP
    MODIS系列之NDVI(MOD13Q1)一:数据下载(一)基于插件
    Python 1基础语法四(数字类型、输入输出汇总和命令行参数)
    Python 1基础语法三(变量和标识符的区别)
    mysql Can't connet MySQL server to '@localhost'
    使用get传参的时候,参数在后头获取不到或者出现别的错误。
    搭建nexus后,进入首页的时候出现warning: Could not connect to Nexus.错误
    在配置dubbo框架的时候出现dubbo:application标签无法识别问题。
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8569993.html
Copyright © 2011-2022 走看看