1. Bright Screen
In fact, when I explained PSensor off-screen above, I already had some knowledge about on-screen display.WakeLock is not held by the process after it goes off, so if you need to light up the screen, you need to apply for WakeLock.Let's tell it with the simplest press of Power
1.Power Key Bright Screen
When the Power key is pressed, the down value is true, and the interceptPowerKeyDown method is executed:
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { // Hold a wake lock until the power key is released. // Request wake-up lock if (!mPowerKeyWakeLock.isHeld()) { mPowerKeyWakeLock.acquire(); } // Cancel multi-press detection timeout. if (mPowerKeyPressCounter != 0) { mHandler.removeMessages(MSG_POWER_DELAYED_PRESS); } mWindowManagerFuncs.onPowerKeyDown(interactive); // Latch power key state to detect screenshot chord. if (interactive && !mScreenshotChordPowerKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mScreenshotChordPowerKeyTriggered = true; mScreenshotChordPowerKeyTime = event.getDownTime(); interceptScreenshotChord(); interceptRingerToggleChord(); } // Stop ringing or end call if configured to do so when power is pressed. TelecomManager telecomManager = getTelecommService(); boolean hungUp = false; if (telecomManager != null) { if (telecomManager.isRinging()) { // Pressing Power while there's a ringing incoming // call should silence the ringer. telecomManager.silenceRinger(); } else if ((mIncallPowerBehavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 && telecomManager.isInCall() && interactive) { // Otherwise, if "Power button ends call" is enabled, // the Power button will hang up any current active call. hungUp = telecomManager.endCall(); } } GestureLauncherService gestureService = LocalServices.getService( GestureLauncherService.class); boolean gesturedServiceIntercepted = false; if (gestureService != null) { gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, mTmpBoolean); if (mTmpBoolean.value && mRequestedOrGoingToSleep) { mCameraGestureTriggeredDuringGoingToSleep = true; } } // Inform the StatusBar; but do not allow it to consume the event. sendSystemKeyToStatusBarAsync(event.getKeyCode()); schedulePossibleVeryLongPressReboot(); // If the power key has still not yet been handled, then detect short // press, long press, or multi press and decide what to do. mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted; if (!mPowerKeyHandled) { if (interactive) { // When interactive, we're already awake. // Wait for a long press or for the button to be released to decide what to do. // Long press the power key if (hasLongPressOnPowerBehavior()) { if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { powerLongPress(); } else { Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); msg.setAsynchronous(true); if (hasVeryLongPressOnPowerBehavior()) { Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS); longMsg.setAsynchronous(true); mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout); } } } } else { // Bright Screen Processing wakeUpFromPowerKey(event.getDownTime()); if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { powerLongPress(); } else { Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); msg.setAsynchronous(true); if (hasVeryLongPressOnPowerBehavior()) { Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS); longMsg.setAsynchronous(true); mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout); } } mBeganFromNonInteractive = true; } else { final int maxCount = getMaxMultiPressPowerCount(); if (maxCount <= 1) { mPowerKeyHandled = true; } else { mBeganFromNonInteractive = true; } } } } }Look at wakeUpFromPowerKey Method:
You can see that you apply for a WakeLock lock before performing a highlight action.Call the wakeUpFromPowerKey method:
private void wakeUpFromPowerKey(long eventTime) { wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER"); }
Next, look at the implementation of wakeUp:
private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason, String details) { 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, details); return true; }
The third parameter passed in is the reason for the highlight: WAKE_REASON_POWER_BUTTON (press Power to highlight).Eventually you'll go to PowerManager's wakeup method (passing three parameters):
public void wakeUp(long time, @WakeReason int reason, String details) { try { mService.wakeUp(time, reason, details, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
The wakeUp method of PowerManagerService is called:
@Override // Binder call public void wakeUp(long eventTime, @WakeReason int reason, String details, String opPackageName) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException("event time must not be in the future"); } // Judging DEVICE_POWER Permissions mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { wakeUpInternal(eventTime, reason, details, uid, opPackageName, uid); } finally { Binder.restoreCallingIdentity(ident); } }
Execute to wakeUpInternal method:
private void wakeUpInternal(long eventTime, @WakeReason int reason, String details, int uid, String opPackageName, int opUid) { synchronized (mLock) { if (wakeUpNoUpdateLocked(eventTime, reason, details, uid, opPackageName, opUid)) { updatePowerStateLocked(); } } }
After locking, wakeUpNoUpdateLocked is called first to determine whether updates are required, generally returning true.Ultimately, it will be on updatePowerStateLocked, the key method of PowerManager Service.
private boolean wakeUpNoUpdateLocked(long eventTime, @WakeReason int reason, String details, 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 || mForceSuspendActive) { return false; } Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0); Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp"); try { Slog.i(TAG, "Waking up from " + PowerManagerInternal.wakefulnessToString(mWakefulness) + " (uid=" + reasonUid + ", reason=" + PowerManager.wakeReasonToString(reason) + ", details=" + details + ")..."); // Set the last time to show, that is, this time mLastWakeTime = eventTime; // Set the reason for the last display, that is, the reason for this time mLastWakeReason = reason; // Set wakefulness to WAKEFULNESS_AWAKE setWakefulnessLocked(WAKEFULNESS_AWAKE, reason, eventTime); // Notify BatteryStatsService to show statistics mNotifier.onWakeUp(reason, details, reasonUid, opPackageName, opUid); // Update user activity time userActivityNoUpdateLocked( eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true; }
Next, look at the implementation of the setWakefulnessLocked method:
void setWakefulnessLocked(int wakefulness, int reason, long eventTime) { if (mWakefulness != wakefulness) { mWakefulness = wakefulness; mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; if (mNotifier != null) { mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime); } mAttentionDetector.onWakefulnessChangeStarted(wakefulness); } }
The onWakefulnessChangeStarted method of the Notifier class is called here to notify the device that the wake-up state is changing:
public void onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime) { final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); 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. // Wake up Activity Manager Service mHandler.post(new Runnable() { @Override public void run() { mActivityManagerInternal.onWakefulnessChanged(wakefulness); } }); // 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) { // Processing at the end of the period handleLateInteractiveChange(); } // Start input as soon as we start waking up or going to sleep. // Start Input mInputManagerInternal.setInteractive(interactive); mInputMethodManagerInternal.setInteractive(interactive); // Notify battery stats. // Notify battery status try { mBatteryStats.noteInteractive(interactive); } catch (RemoteException ex) { } StatsLog.write(StatsLog.INTERACTIVE_STATE_CHANGED, interactive ? StatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON : StatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF); // Handle early behaviors. // Pre-processing Behavior mInteractive = interactive; mInteractiveChangeReason = reason; mInteractiveChangeStartTime = eventTime; mInteractiveChanging = true; handleEarlyInteractiveChange(); } }
handleEarlyInteractiveChange method for handling pre-interaction:
private void handleEarlyInteractiveChange() { synchronized (mLock) { if (mInteractive) { // Waking up... mHandler.post(new Runnable() { @Override public void run() { final int why = translateOnReason(mInteractiveChangeReason); // Callback PhoneWindowManager mPolicy.startedWakingUp(why); } }); // Send interactive broadcast. // Send off-screen 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); } }); } } }
The call stack information is as follows:
12-09 03:31:37.397 1086 1192 I xw : at android.os.PowerManager.wakeUp(PowerManager.java:1208) 12-09 03:31:37.397 1086 1192 I xw : at com.android.server.policy.PhoneWindowManager.wakeUp(PhoneWindowManager.java:4981) 12-09 03:31:37.397 1086 1192 I xw : at com.android.server.policy.PhoneWindowManager.wakeUpFromPowerKey(PhoneWindowManager.java:4965) 12-09 03:31:37.397 1086 1192 I xw : at com.android.server.policy.PhoneWindowManager.interceptPowerKeyDown(PhoneWindowManager.java:1124) 12-09 03:31:37.397 1086 1192 I xw : at com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:4283) 12-09 03:31:37.397 1086 1192 I xw : at com.android.server.wm.InputManagerCallback.interceptKeyBeforeQueueing(InputManagerCallback.java:164) 12-09 03:31:37.397 1086 1192 I xw : at com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1827)
##2. Summary
Part of the PowerManager Services highlight process involved here.The whole wake-up process is that the bottom passes power key s to the top --> PowerManager ServiceProcessing --> Initialize keyguard/wake-up bottom --> Write brightness to the device node.