Android knowledge 109 - Android7.0 PowerManagerService the light off screen

Original Address:  https://www.cnblogs.com/dyufei/p/8017604.html

Written in good, stick around!

Benpian after pressing the power button, a key event from InputManagerService spread PhoneWindowManager.java start analyzing power button to do the analysis process off-screen light, on other acts power key reference another blog post ( Android 7.0 Power button process flow )

    (Note: The blog picture display garden is very vague, upload large map, you can save as picture view)

    Closer to home herein, this involved several modules (files) as follows, first a brief introduction about have an intuitive understanding, easy to understand process details later.

Ø  PowerManagerService.Java(/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java)

   PMS, is the power processing services Android system, is responsible for computing and power-related decisions, such as whether to let off the screen or dim the screen, whether the system should be allowed to sleep, and so on.

Ø  DisplayPowerController.java(/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java)

  The DPC, manages the display device (display device is referred to herein as a screen) state, the processing from the main sensor (e.g., when a call is close off screen, when the screen away from light) and the screen blinking animation (screen comprises calculating a target. The optical sensor luminance value). In DisplayManagerService.java (DMS) to instantiate an object to DMS as a bridge to interact with PMS by asynchronous callback mechanism to notify PMS that has changed. But also interact with the WMS.

Ø  DisplayPowerState.java(/frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java)

  DPS, the display state management device only instantiate an object in DPC, the DPC is a part.

Ø  Notifier.java:( /frameworks/base/services/core/java/com/android/server/power/Notifier.java

  The important changes in the power of the state, by broadcasting the notification out.

Ø  ColorFade.java:(/frameworks/base/services/core/java/com/android/server/display/ColorFade.java

  It is responsible for the screen by the Commissioner to open, controlled by the DPC by the opening of some GL animation off.

Ø  AutomaticBrightnessController.java:(/frameworks/base/services/core/java/com/android/server/display/AutomaticBrightnessController.java)

  The main processing optical sensor, the parameter calculation process is performed to upload the bottom, the new luminance value calculated luminance value is set to pass DPC screen (i.e., the light intensity is calculated based on the degree of environmental light-dark screen).

Ø  RampAnimator.java:(/frameworks/base/services/core/java/com/android/server/display/RampAnimator.java)

  Only the screen brightness gradient animation.

First, the report processing Power button

For details see [ Android 7.0 Power  button processing flow ] here's a refresher only slightly, to facilitate the understanding behind.

1) Power button reporting

power key event conversion through a series of processing and eventually transferred to PhoneWindowManager (PWM) of interceptKeyBeforeQueueing () function to do specific business logic. The figure below shows a flow chart reported in InputManagerService received.

 

2) power button on the amount of off-screen treatment

The amount of off-screen processing, mainly in interceptKeyBeforeQueueing () function. Determine whether the isWakeKey , if it is at last by calling this function wakeUp () to handle specific functions, which kicked off this article.

Note: This function is part of a long article delete irrelevant, and retain only part of the amount of off-screen instructions related to specific processing flow. Details Reference [ Android 7.0 Power  button processing flow ]

A: key processing for determining whether the amount of off-screen

 

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {

        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
                || event.isWakeKey();
        if (interactive || (isInjected && !isWakeKey)) {
            // When the device is interactive or the key is injected pass the
            // key to the application.
            result = ACTION_PASS_TO_USER;
            isWakeKey = false;

            if (interactive) {
                // If the screen is awake, but the button pressed was the one that woke the device
                // then don't pass it to the application
                if (keyCode == mPendingWakeKey && !down) {
                    result = 0;
                }
                // Reset the pending key
                mPendingWakeKey = PENDING_KEY_NULL;
            }
        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
            // If we're currently dozing with the screen on and the keyguard showing, pass the key
            // to the application but preserve its wake key status to make sure we still move
            // from dozing to fully interactive if we would normally go from off to fully
            // interactive.
            result = ACTION_PASS_TO_USER;
            // Since we're dispatching the input, reset the pending key
            mPendingWakeKey = PENDING_KEY_NULL;
        } else {
            // When the screen is off and the key is not injected, determine whether
            // to wake the device but don't pass the key to the application.
            result = 0;
            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
                isWakeKey = false;
            }
            // Cache the wake key on down event so we can also avoid sending the up event to the app
            if (isWakeKey && down) {
                mPendingWakeKey = keyCode;
            }
        }

        // If the key would be handled globally, just return the result, don't worry about special
        // key processing.
        if (isValidGlobalKey(keyCode)
                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
            if (isWakeKey) {
                wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
            }
            return result;
        }

     ....................

            case KeyEvent.KEYCODE_ENDCALL: {
                result &= ~ACTION_PASS_TO_USER;
                if (down) {
                    TelecomManager telecomManager = getTelecommService();
                    boolean hungUp = false;
                    if (telecomManager != null) {
                        hungUp = telecomManager.endCall();
                    }
                    if (interactive && !hungUp) {
                        mEndCallKeyHandled = false;
                        mHandler.postDelayed(mEndCallLongPress,
                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
                    } else {
                        mEndCallKeyHandled = true;
                    }
                } else {
                    if (!mEndCallKeyHandled) {
                        mHandler.removeCallbacks(mEndCallLongPress);
                        if (!canceled) {
                            if ((mEndcallBehavior
                                    & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
                                if (goHome()) {
                                    break;
                                }
                            }
                            if ((mEndcallBehavior
                                    & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
                                mPowerManager.goToSleep(event.getEventTime(),
                                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
                                isWakeKey = false;
                            }
                        }
                    }
                }
                break;
            }

  

....................

        if (useHapticFeedback) {
            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
        }

        if (isWakeKey) {
            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
        }

        return result;
    }

 

 

B: wakeUp handling capacity off-screen

 

private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {  
    final boolean theaterModeEnabled = isTheaterModeEnabled();  
    if (!wakeInTheaterMode && theaterModeEnabled) {  
        return false;  
    }  
  
    if (theaterModeEnabled) {  
        Settings.Global.putInt(mContext.getContentResolver(),  
                    Settings.Global.THEATER_MODE_ON, 0);  
        }  
      
        mPowerManager.wakeUp(wakeTime, reason);      //调用PowerManagerService亮屏操作
        return true;  
    } 
}

 

 

Two, PowerManagerService amount of processing off-screen process

Can be seen from the above analysis, the PWM processing key events if needed wake-up screen will be called the PWM wakeUp () function, which calls for PMS wakeUp () function to specifically address.

Can be seen from the above analysis, the PWM processing key events if needed wake-up screen will be called the PWM wakeUp () function, which calls for PMS wakeUp () function to specifically address.

  Note: Due to space limitations listed in this article only important function and procedure calls

First, let a Glance, look mainly to complete the following three things

1) emitted from the Notifier to the broadcast system in accordance with a particular state

2) PMS by updatePowerStateLocked () global power is calculated and updated status

3) PMS latest incoming power status DPC in accordance with the distance sensor and an optical sensor sensing, calculating the specific amount of off screen brightness and screen animations

4) DPC notice PWM draw keyguard and windows (this time will block waiting for rendering complete, off-screen time without rendering) notify DPC continue after drawing is complete

5) DPC specific call display device is turned on or off the screen (off screen executed amount of animation)

1)PowerManagerService--wakeUpNoUpdateLocked()

PMS First talk wakefullness state. After sending the flickering screen broadcast applications Notify other mobile phone screen or off screen in bright state.

 

 private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,  
        String opPackageName, int opUid) {  
    if (DEBUG_SPEW) {  
        Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);  
    }  
  
    if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE  
            || !mBootCompleted || !mSystemReady) {  
        return false;        //判断是否要去亮屏  
     }  
   
     Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");  
     try {  
         switch (mWakefulness) {  
             case WAKEFULNESS_ASLEEP:  
                 Slog.i(TAG, "Waking up from sleep due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");  
                 break;  
             case WAKEFULNESS_DREAMING:  
                 Slog.i(TAG, "Waking up from dream due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");  
                 break;  
             case WAKEFULNESS_DOZING:  
                 Slog.i(TAG, "Waking up from dozing due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");  
                 break;  
         }  
   
         mLastWakeTime = eventTime;   //设置最后一次唤醒的时间  
         setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);   //Notifier调用onWakefulnessChangeStarted发送亮屏广播  
   
         mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);  //调用Notifier通知battery处理  
         userActivityNoUpdateLocked(     //更新最后一次用户事件时间  
                 eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);  
     } finally {  
         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
     }  
     return true;  
 } 

 

1) Notifier sends the amount of off-screen broadcast

Notifier and will be broadcast before sending the AMS, WMS, IMS interactive notification to change the power state of each module, each module will take care of a power state change notification.

A:onWakefulnessChangeStarted()

public void onWakefulnessChangeStarted(final int wakefulness, int reason) {  
   final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); //亮屏true, 灭屏false  
   if (DEBUG) {  
       Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness  
               + ", reason=" + reason + ", interactive=" + interactive);  
   }  
 
   // Tell the activity manager about changes in wakefulness, not just interactivity.  
   // It needs more granularity than other components.  
    mHandler.post(new Runnable() {  
        @Override  
        public void run() {  
            mActivityManagerInternal.onWakefulnessChanged(wakefulness);   //与AMS交互处理  
        }  
    });  
  
    // Handle any early interactive state changes.  
    // Finish pending incomplete ones from a previous cycle.  
    if (mInteractive != interactive) {  
        // Finish up late behaviors if needed.  
        if (mInteractiveChanging) {  
            handleLateInteractiveChange();  
        }  
  
        // Start input as soon as we start waking up or going to sleep.  
        mInputManagerInternal.setInteractive(interactive);    //在IMS中记录现在的屏幕状态  
        mInputMethodManagerInternal.setInteractive(interactive);  
  
        // Notify battery stats.  
        try {  
            mBatteryStats.noteInteractive(interactive);   //唤醒battery状态  
        } catch (RemoteException ex) { }  
  
        // Handle early behaviors.  
        mInteractive = interactive;  
        mInteractiveChangeReason = reason;  
        mInteractiveChanging = true;  
        handleEarlyInteractiveChange();   //初期处理交互模式改变  
    }  
} 

 

 

B: handleEarlyInteractiveChange()

When the screen needs to be updated notification window gesture listening when wakingup, update direction monitor, update lock screen timeout 

private void handleEarlyInteractiveChange() {  
    synchronized (mLock) {  
        if (mInteractive) {  
            // Waking up...    //亮屏  
            mHandler.post(new Runnable() {  
                @Override  
                public void run() {  
                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);  
                    mPolicy.startedWakingUp();   
                 }  
             });  
   
             // Send interactive broadcast.  
             mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;  
             mPendingWakeUpBroadcast = true;  
             updatePendingBroadcastLocked();   //更新亮屏广播  
         } else {  
             // Going to sleep...   //灭屏  
             // Tell the policy that we started going to sleep.  
             final int why = translateOffReason(mInteractiveChangeReason);  
             mHandler.post(new Runnable() {  
                 @Override  
                 public void run() {  
                     mPolicy.startedGoingToSleep(why);  
                 }  
             });  
         }  
     } 

 

(1):updatePendingBroadcastLocked()

    private void updatePendingBroadcastLocked() {
        if (!mBroadcastInProgress
                && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
                && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mPendingInteractiveState != mBroadcastedInteractiveState)) {
            mBroadcastInProgress = true;
            mSuspendBlocker.acquire();
            Message msg = mHandler.obtainMessage(MSG_BROADCAST);
            msg.setAsynchronous(true);
            mHandler.sendMessage(msg);
        }
    }

 

(2)sendNextBroadcast()

 private void sendNextBroadcast() {
        final int powerState;
        synchronized (mLock) {
            if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
                // Broadcasted power state is unknown.  Send wake up.
                mPendingWakeUpBroadcast = false;
                mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
            } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
                // Broadcasted power state is awake.  Send asleep if needed.
                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
                    mPendingGoToSleepBroadcast = false;
                    mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
                } else {
                    finishPendingBroadcastLocked();
                    return;
                }
            } else {
                // Broadcasted power state is asleep.  Send awake if needed.
                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
                    mPendingWakeUpBroadcast = false;
                    mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
                } else {
                    finishPendingBroadcastLocked();
                    return;
                }
            }

            mBroadcastStartTime = SystemClock.uptimeMillis();
            powerState = mBroadcastedInteractiveState;
        }

        EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);

        if (powerState == INTERACTIVE_STATE_AWAKE) {
            sendWakeUpBroadcast();//这里发送亮屏广播
        } else {
            sendGoToSleepBroadcast();
        }
    }

Copy the code

 (3)sendWakeUpBroadcast()

 Note: Notifier bright screen itself also receive broadcast calls finishPendingBroadcastLocked after its subject () function to release wakeLock

 

private void sendWakeUpBroadcast() {
        if (DEBUG) {
            Slog.d(TAG, "Sending wake up broadcast.");
        }

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

Copy the code

 

 

Published 112 original articles · won praise 3 · Views 9701

Guess you like

Origin blog.csdn.net/yush34/article/details/104962034