PhoneWindowManager响应电源键

首先按下power键后调用frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java的interceptKeyBeforeQueueing方法:

    // TODO(b/117479243): handle it in InputPolicy/** {@inheritDoc} */@Overridepublic int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {......// Handle special keys.switch (keyCode) {......case KeyEvent.KEYCODE_POWER: {EventLogTags.writeInterceptPower(KeyEvent.actionToString(event.getAction()),mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter);// Any activity on the power button stops the accessibility shortcutcancelPendingAccessibilityShortcutAction();result &= ~ACTION_PASS_TO_USER;isWakeKey = false; // wake-up will be handled separatelyif (down) {interceptPowerKeyDown(event, interactive);} else {interceptPowerKeyUp(event, interactive, canceled);}break;}......}......}

调用了PhoneWindowManager的interceptPowerKeyUp方法:

    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {final boolean handled = canceled || mPowerKeyHandled;mScreenshotChordPowerKeyTriggered = false;cancelPendingScreenshotChordAction();cancelPendingPowerKeyAction();if (!handled) {......// No other actions.  Handle it immediately.powerPress(eventTime, interactive, mPowerKeyPressCounter);}// Done.  Reset our state.finishPowerKeyPress();}

调用了PhoneWindowManager的powerPress方法:

    private void powerPress(long eventTime, boolean interactive, int count) {......if (count == 2) {powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);} else if (count == 3) {powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);} else if (interactive && !mBeganFromNonInteractive) {switch (mShortPressOnPowerBehavior) {......case SHORT_PRESS_POWER_GO_TO_SLEEP:goToSleepFromPowerButton(eventTime, 0);break;......}}}

调用了PhoneWindowManager的goToSleepFromPowerButton方法:

    /*** Sends the device to sleep as a result of a power button press.** @return True if the was device was sent to sleep, false if sleep was suppressed.*/private boolean goToSleepFromPowerButton(long eventTime, int flags) {// Before we actually go to sleep, we check the last wakeup reason.// If the device very recently woke up from a gesture (like user lifting their device)// then ignore the sleep instruction. This is because users have developed// a tendency to hit the power button immediately when they pick up their device, and we// don't want to put the device back to sleep in those cases.final PowerManager.WakeData lastWakeUp = mPowerManagerInternal.getLastWakeup();if (lastWakeUp != null && lastWakeUp.wakeReason == PowerManager.WAKE_REASON_GESTURE) {final int gestureDelayMillis = Settings.Global.getInt(mContext.getContentResolver(),Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS);final long now = SystemClock.uptimeMillis();if (mPowerButtonSuppressionDelayMillis > 0&& (now < lastWakeUp.wakeTime + mPowerButtonSuppressionDelayMillis)) {Slog.i(TAG, "Sleep from power button suppressed. Time since gesture: "+ (now - lastWakeUp.wakeTime) + "ms");return false;}}goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, flags);return true;}

调用了PhoneWindowManager的goToSleep方法:

    private void goToSleep(long eventTime, int reason, int flags) {mRequestedOrGoingToSleep = true;mPowerManager.goToSleep(eventTime, reason, flags);}

PowerMangerService处理灭屏

调用了frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java的静态内部类BinderService的goToSleep方法:

        @Override // Binder callpublic void goToSleep(long eventTime, int reason, int flags) {if (eventTime > mClock.uptimeMillis()) {throw new IllegalArgumentException("event time must not be in the future");}mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);final int uid = Binder.getCallingUid();final long ident = Binder.clearCallingIdentity();try {goToSleepInternal(eventTime, reason, flags, uid);} finally {Binder.restoreCallingIdentity(ident);}}

调用了PowerManagerService的goToSleepInternal方法:

    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {synchronized (mLock) {if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {updatePowerStateLocked();}}}

调用了PowerManagerService的goToSleepNoUpdateLocked方法:

    /*** Puts the system in doze.** This method is called goToSleep for historical reasons but actually attempts to DOZE,* and only tucks itself in to SLEEP if requested with the flag* {@link PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE}.*/@SuppressWarnings("deprecation")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|| getWakefulnessLocked() == WAKEFULNESS_ASLEEP|| getWakefulnessLocked() == WAKEFULNESS_DOZING|| !mSystemReady|| !mBootCompleted) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");try {reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)+ " (uid " + uid + ")...");mLastSleepTime = eventTime;mLastSleepReason = reason;mSandmanSummoned = true;mDozeStartInProgress = true;setWakefulnessLocked(WAKEFULNESS_DOZING, reason, eventTime);// 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++) {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;}}EventLogTags.writePowerSleepRequested(numWakeLocksCleared);// Skip dozing if requested.if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {reallyGoToSleepNoUpdateLocked(eventTime, uid);}} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;}

调用了PowerManagerService的setWakefulnessLocked方法,传入了WAKEFULNESS_DOZING:

    @VisibleForTestingvoid setWakefulnessLocked(int wakefulness, int reason, long eventTime) {if (getWakefulnessLocked() != wakefulness) {// Under lock, invalidate before set ensures caches won't return stale values.mInjector.invalidateIsInteractiveCaches();mWakefulnessRaw = wakefulness;mWakefulnessChanging = true;mDirty |= DIRTY_WAKEFULNESS;// This is only valid while we are in wakefulness dozing. Set to false otherwise.mDozeStartInProgress &= (getWakefulnessLocked() == WAKEFULNESS_DOZING);if (mNotifier != null) {mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime);}mAttentionDetector.onWakefulnessChangeStarted(wakefulness);}}

调用了frameworks/base/services/core/java/com/android/server/power/Notifier.java的onWakefulnessChangeStarted方法:

    /*** Notifies that the device is changing wakefulness.* This function may be called even if the previous change hasn't finished in* which case it will assume that the state did not fully converge before the* next transition began and will recover accordingly.*/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.mHandler.post(new Runnable() {@Overridepublic 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) {handleLateInteractiveChange();}// Start input as soon as we start waking up or going to sleep.mInputManagerInternal.setInteractive(interactive);mInputMethodManagerInternal.setInteractive(interactive);// Notify battery stats.try {mBatteryStats.noteInteractive(interactive);} catch (RemoteException ex) { }FrameworkStatsLog.write(FrameworkStatsLog.INTERACTIVE_STATE_CHANGED,interactive ? FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__ON :FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF);// Handle early behaviors.mInteractive = interactive;mInteractiveChangeReason = reason;mInteractiveChangeStartTime = eventTime;mInteractiveChanging = true;handleEarlyInteractiveChange();}}

这个方法首先通知AMS状态变为WAKEFULNESS_DOZING,然后通知InputManager为不可交互状态,最后调用了Notifier的handleEarlyInteractiveChange方法:

    /*** Handle early interactive state changes such as getting applications or the lock* screen running and ready for the user to see (such as when turning on the screen).*/private void handleEarlyInteractiveChange() {synchronized (mLock) {if (mInteractive) {// Waking up...mHandler.post(new Runnable() {@Overridepublic void run() {final int why = translateOnReason(mInteractiveChangeReason);mPolicy.startedWakingUp(why);}});// 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() {@Overridepublic void run() {mPolicy.startedGoingToSleep(why);}});}}}

PhoneWindowManager执行startedGoingToSleep

调用了frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java的startedGoingToSleep方法:

    // Called on the PowerManager's Notifier thread.@Overridepublic void startedGoingToSleep(int why) {if (DEBUG_WAKEUP) {Slog.i(TAG, "Started going to sleep... (why="+ WindowManagerPolicyConstants.offReasonToString(why) + ")");}mGoingToSleep = true;mRequestedOrGoingToSleep = true;if (mKeyguardDelegate != null) {mKeyguardDelegate.onStartedGoingToSleep(why);}}

通知keyguard的onStartedGoingToSleep

调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java的onStartedGoingToSleep方法:

    public void onStartedGoingToSleep(int why) {if (mKeyguardService != null) {mKeyguardService.onStartedGoingToSleep(why);}mKeyguardState.offReason = why;mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;}

调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java的onStartedGoingToSleep方法:

    @Overridepublic void onStartedGoingToSleep(int reason) {try {mService.onStartedGoingToSleep(reason);} catch (RemoteException e) {Slog.w(TAG , "Remote Exception", e);}}

通过binder调用了systemui进程中frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java的成员变量mBinder的onStartedGoingToSleep方法:

        @Override // Binder interfacepublic void onStartedGoingToSleep(int reason) {checkPermission();mKeyguardViewMediator.onStartedGoingToSleep(reason);mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.STARTED_GOING_TO_SLEEP);}

PowerManagerService更新电源状态

回到PowerManagerService的goToSleepInternal方法中,接下来调用了PowerManagerService的updatePowerStateLocked方法:

    /*** Updates the global power state based on dirty bits recorded in mDirty.** This is the main function that performs power state transitions.* We centralize them here so that we can recompute the power state completely* each time something important changes, and ensure that we do it the same* way each time.  The point is to gather all of the transition logic here.*/private void updatePowerStateLocked() {if (!mSystemReady || mDirty == 0) {return;}if (!Thread.holdsLock(mLock)) {Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");}Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");try {// Phase 0: Basic state updates.updateIsPoweredLocked(mDirty);updateStayOnLocked(mDirty);updateScreenBrightnessBoostLocked(mDirty);// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.final long now = mClock.uptimeMillis();int dirtyPhase2 = 0;for (;;) {int dirtyPhase1 = mDirty;dirtyPhase2 |= dirtyPhase1;mDirty = 0;updateWakeLockSummaryLocked(dirtyPhase1);updateUserActivitySummaryLocked(now, dirtyPhase1);updateAttentiveStateLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Lock profiles that became inactive/not kept awake.updateProfilesLocked(now);// Phase 3: Update display power state.final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);// Phase 4: Update dream state (depends on display ready signal).updateDreamLocked(dirtyPhase2, displayBecameReady);// Phase 5: Send notifications, if needed.finishWakefulnessChangeIfNeededLocked();// Phase 6: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}}

在Phase 3中调用了PowerManagerService的updateDisplayPowerStateLocked方法:

    /*** Updates the display power state asynchronously.* When the update is finished, mDisplayReady will be set to true.  The display* controller posts a message to tell us when the actual display power state* has been updated so we come back here to double-check and finish up.** This function recalculates the display power state each time.** @return True if the display became ready.*/private boolean updateDisplayPowerStateLocked(int dirty) {final boolean oldDisplayReady = mDisplayReady;if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |DIRTY_QUIESCENT)) != 0) {if ((dirty & DIRTY_QUIESCENT) != 0) {sQuiescent = false;}mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();// Determine appropriate screen brightness and auto-brightness adjustments.final boolean autoBrightness;final float screenBrightnessOverride;if (!mBootCompleted) {// Keep the brightness steady during boot. This requires the// bootloader brightness and the default brightness to be identical.autoBrightness = false;screenBrightnessOverride = mScreenBrightnessSettingDefault;} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {autoBrightness = false;screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;} else {autoBrightness = (mScreenBrightnessModeSetting ==Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;}// Update display power request.mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;mDisplayPowerRequest.useAutoBrightness = autoBrightness;mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0&& !mDrawWakeLockOverrideFromSidekick) {if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;}if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {mDisplayPowerRequest.dozeScreenState = Display.STATE_ON;}}mDisplayPowerRequest.dozeScreenBrightness =mDozeScreenBrightnessOverrideFromDreamManagerFloat;} else {mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;mDisplayPowerRequest.dozeScreenBrightness =PowerManager.BRIGHTNESS_INVALID_FLOAT;}mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,mRequestWaitForNegativeProximity);mRequestWaitForNegativeProximity = false;if (DEBUG_SPEW) {Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady+ ", policy=" + mDisplayPowerRequest.policy+ ", mWakefulness=" + getWakefulnessLocked()+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)+ ", mBootCompleted=" + mBootCompleted+ ", screenBrightnessOverride=" + screenBrightnessOverride+ ", useAutoBrightness=" + autoBrightness+ ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress+ ", mIsVrModeEnabled= " + mIsVrModeEnabled+ ", sQuiescent=" + sQuiescent);}}return mDisplayReady && !oldDisplayReady;}

DisplayManagerService更新电源状态

通过mDisplayManagerInternal.requestPowerState调用了frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java的内部类LocalService的requestPowerState方法:

        @Overridepublic boolean requestPowerState(DisplayPowerRequest request,boolean waitForNegativeProximity) {synchronized (mSyncRoot) {return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity);}}

DisplayPowerController更新电源状态

调用了frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java的requestPowerState方法:

        @Overridepublic boolean requestPowerState(DisplayPowerRequest request,boolean waitForNegativeProximity) {synchronized (mSyncRoot) {return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity);}}

调用了DisplayPowerController的sendUpdatePowerStateLocked方法:

    private void sendUpdatePowerStateLocked() {if (!mPendingUpdatePowerStateLocked) {mPendingUpdatePowerStateLocked = true;Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);mHandler.sendMessage(msg);}}

这个消息在DisplayPowerController的内部类DisplayControllerHandler的handleMessage方法中处理:

        @Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_UPDATE_POWER_STATE:updatePowerState();break;......}}

调用了DisplayPowerController的updatePowerState方法:

    private void updatePowerState() {......animateScreenStateChange(state, performScreenOffTransition);......}

调用了DisplayPowerController的animateScreenStateChange方法:

    private void animateScreenStateChange(int target, boolean performScreenOffTransition) {......if (target == Display.STATE_ON) {......} else if (target == Display.STATE_VR) {......} else if (target == Display.STATE_DOZE) {......} else if (target == Display.STATE_DOZE_SUSPEND) {......} else if (target == Display.STATE_ON_SUSPEND) {......} else {// Want screen off.mPendingScreenOff = true;if (!mColorFadeEnabled) {mPowerState.setColorFadeLevel(0.0f);}if (mPowerState.getColorFadeLevel() == 0.0f) {// Turn the screen off.// A black surface is already hiding the contents of the screen.setScreenState(Display.STATE_OFF);mPendingScreenOff = false;mPowerState.dismissColorFadeResources();} else if (performScreenOffTransition&& mPowerState.prepareColorFade(mContext,mColorFadeFadesConfig ?ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)&& mPowerState.getScreenState() != Display.STATE_OFF) {// Perform the screen off animation.mColorFadeOffAnimator.start();} else {// Skip the screen off animation and add a black surface to hide the// contents of the screen.mColorFadeOffAnimator.end();}}}

这里第一次进来会调用mColorFadeOffAnimator.start开始ColorFade动画,再次进来时ColorFade动画跑完了,条件mPowerState.getColorFadeLevel() == 0.0f满足,会调用DisplayPowerController的setScreenState方法:

    private boolean setScreenState(int state) {return setScreenState(state, false /*reportOnly*/);}private boolean setScreenState(int state, boolean reportOnly) {final boolean isOff = (state == Display.STATE_OFF);if (mPowerState.getScreenState() != state) {// If we are trying to turn screen off, give policy a chance to do something before we// actually turn the screen off.if (isOff && !mScreenOffBecauseOfProximity) {if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);blockScreenOff();mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);unblockScreenOff();} else if (mPendingScreenOffUnblocker != null) {// Abort doing the state change until screen off is unblocked.return false;}}if (!reportOnly) {Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);// TODO(b/153319140) remove when we can get this from the above trace invocationSystemProperties.set("debug.tracing.screen_state", String.valueOf(state));mPowerState.setScreenState(state);// Tell battery stats about the transition.try {mBatteryStats.noteScreenState(state);} catch (RemoteException ex) {// same process}}}// Tell the window manager policy when the screen is turned off or on unless it's due// to the proximity sensor.  We temporarily block turning the screen on until the// window manager is ready by leaving a black surface covering the screen.// This surface is essentially the final state of the color fade animation and// it is only removed once the window manager tells us that the activity has// finished drawing underneath.if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF&& !mScreenOffBecauseOfProximity) {setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);unblockScreenOn();mWindowManagerPolicy.screenTurnedOff();} else if (!isOff&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {// We told policy already that screen was turning off, but now we changed our minds.// Complete the full state transition on -> turningOff -> off.unblockScreenOff();mWindowManagerPolicy.screenTurnedOff();setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);}......// Return true if the screen isn't blocked.return mPendingScreenOnUnblocker == null;}

PhoneWindowManager执行screenTurningOff

这个方法首先调用了frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java的screenTurningOff方法:

    @Overridepublic void screenTurningOff(ScreenOffListener screenOffListener) {mWindowManagerFuncs.screenTurningOff(screenOffListener);synchronized (mLock) {if (mKeyguardDelegate != null) {mKeyguardDelegate.onScreenTurningOff();}}}

在灭屏前截屏

这个方法首先调用了frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java的screenTurningOff方法:

    @Overridepublic void screenTurningOff(ScreenOffListener listener) {mTaskSnapshotController.screenTurningOff(listener);}

调用了frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java的screenTurningOff方法:

    /*** Called when screen is being turned off.*/void screenTurningOff(ScreenOffListener listener) {if (shouldDisableSnapshots()) {listener.onScreenOff();return;}// We can't take a snapshot when screen is off, so take a snapshot now!mHandler.post(() -> {try {synchronized (mService.mGlobalLock) {mTmpTasks.clear();mService.mRoot.forAllTasks(task -> {if (task.isVisible()) {mTmpTasks.add(task);}});// Allow taking snapshot of home when turning screen off to reduce the delay of// waking from secure lock to home.final boolean allowSnapshotHome =mService.mPolicy.isKeyguardSecure(mService.mCurrentUserId);snapshotTasks(mTmpTasks, allowSnapshotHome);}} finally {listener.onScreenOff();}});}

在这里截了屏,并调用listener.onScreenOff停止阻塞灭屏。

通知keyguard的onScreenTurningOff

回到PhoneWindowManager的screenTurningOff方法,后面还调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java的onScreenTurningOff方法:

    public void onScreenTurningOff() {if (mKeyguardService != null) {if (DEBUG) Log.v(TAG, "onScreenTurningOff()");mKeyguardService.onScreenTurningOff();}mKeyguardState.screenState = SCREEN_STATE_TURNING_OFF;}

调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java的onScreenTurningOff方法:

    @Overridepublic void onScreenTurningOff() {try {mService.onScreenTurningOff();} catch (RemoteException e) {Slog.w(TAG , "Remote Exception", e);}}

通过binder调用了systemui进程中frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java的成员变量mBinder的onScreenTurningOff方法:

        @Override // Binder interfacepublic void onScreenTurningOff() {checkPermission();mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_OFF);}

PhoneWindowManager执行screenTurnedOff

DisplayPowerController的setScreenState方法后面还会调用frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java的screenTurnedOff方法:

    // Called on the DisplayManager's DisplayPowerController thread.@Overridepublic void screenTurnedOff() {if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");updateScreenOffSleepToken(true);mDefaultDisplayPolicy.screenTurnedOff();synchronized (mLock) {if (mKeyguardDelegate != null) {mKeyguardDelegate.onScreenTurnedOff();}}mDefaultDisplayRotation.updateOrientationListener();reportScreenStateToVrManager(false);}

这里通过updateScreenOffSleepToken(true)获取了灭屏的SleepToken,会对resume的Activity进行pause,详见SleepToken机制。

通知keyguard的onScreenTurnedOff

调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java的onScreenTurnedOff方法:

    public void onScreenTurnedOff() {if (mKeyguardService != null) {if (DEBUG) Log.v(TAG, "onScreenTurnedOff()");mKeyguardService.onScreenTurnedOff();}mKeyguardState.screenState = SCREEN_STATE_OFF;}

调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java的onScreenTurnedOff方法:

    @Overridepublic void onScreenTurnedOff() {try {mService.onScreenTurnedOff();} catch (RemoteException e) {Slog.w(TAG , "Remote Exception", e);}}

通过binder调用了systemui进程中frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java的成员变量mBinder的onScreenTurnedOff方法:

        @Override // Binder interfacepublic void onScreenTurnedOff() {checkPermission();mKeyguardViewMediator.onScreenTurnedOff();mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);}

PhoneWindowManager执行finishedGoingToSleep

回到PowerManagerService的updatePowerStateLocked方法,在Phase 5调用了PowerManagerService的finishWakefulnessChangeIfNeededLocked方法:

    private void finishWakefulnessChangeIfNeededLocked() {if (mWakefulnessChanging && mDisplayReady) {if (getWakefulnessLocked() == WAKEFULNESS_DOZING&& (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {return; // wait until dream has enabled dozing} else {// Doze wakelock acquired (doze started) or device is no longer dozing.mDozeStartInProgress = false;}if (getWakefulnessLocked() == WAKEFULNESS_DOZING|| getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {logSleepTimeoutRecapturedLocked();}if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);final int latencyMs = (int) (mClock.uptimeMillis() - mLastWakeTime);if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {Slog.w(TAG, "Screen on took " + latencyMs + " ms");}}mWakefulnessChanging = false;mNotifier.onWakefulnessChangeFinished();}}

调用了frameworks/base/services/core/java/com/android/server/power/Notifier.java的onWakefulnessChangeFinished方法:

    /*** Notifies that the device has finished changing wakefulness.*/public void onWakefulnessChangeFinished() {if (DEBUG) {Slog.d(TAG, "onWakefulnessChangeFinished");}if (mInteractiveChanging) {mInteractiveChanging = false;handleLateInteractiveChange();}}

调用了Notifier的handleLateInteractiveChange方法:

    /*** Handle late interactive state changes once they are finished so that the system can* finish pending transitions (such as turning the screen off) before causing* applications to change state visibly.*/private void handleLateInteractiveChange() {synchronized (mLock) {final int interactiveChangeLatency =(int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime);if (mInteractive) {// Finished waking up.........} else {// Finished going to sleep...// This is a good time to make transitions that we don't want the user to see,// such as bringing the key guard to focus.  There's no guarantee for this// however because the user could turn the device on again at any time.// Some things may need to be protected by other mechanisms that defer screen on.// Cancel pending user activity.if (mUserActivityPending) {mUserActivityPending = false;mHandler.removeMessages(MSG_USER_ACTIVITY);}// Tell the policy we finished going to sleep.final int why = translateOffReason(mInteractiveChangeReason);mHandler.post(new Runnable() {@Overridepublic void run() {LogMaker log = new LogMaker(MetricsEvent.SCREEN);log.setType(MetricsEvent.TYPE_CLOSE);log.setSubtype(why);log.setLatency(interactiveChangeLatency);log.addTaggedData(MetricsEvent.FIELD_SCREEN_SLEEP_REASON, mInteractiveChangeReason);MetricsLogger.action(log);EventLogTags.writePowerScreenState(0, why, 0, 0, interactiveChangeLatency);mPolicy.finishedGoingToSleep(why);}});// Send non-interactive broadcast.mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;mPendingGoToSleepBroadcast = true;updatePendingBroadcastLocked();}}}

通过mHandler.post方法切换线程后调用了frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java的finishedGoingToSleep方法:

    // Called on the PowerManager's Notifier thread.@Overridepublic void finishedGoingToSleep(int why) {EventLogTags.writeScreenToggled(0);if (DEBUG_WAKEUP) {Slog.i(TAG, "Finished going to sleep... (why="+ WindowManagerPolicyConstants.offReasonToString(why) + ")");}MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);mGoingToSleep = false;mRequestedOrGoingToSleep = false;mDefaultDisplayPolicy.setAwake(false);// We must get this work done here because the power manager will drop// the wake lock and let the system suspend once this function returns.synchronized (mLock) {updateWakeGestureListenerLp();updateLockScreenTimeout();}mDefaultDisplayRotation.updateOrientationListener();if (mKeyguardDelegate != null) {mKeyguardDelegate.onFinishedGoingToSleep(why,mCameraGestureTriggeredDuringGoingToSleep);}if (mDisplayFoldController != null) {mDisplayFoldController.finishedGoingToSleep();}mCameraGestureTriggeredDuringGoingToSleep = false;}

首先打印了event log:screen_toggled: 0

通知keyguard的onFinishedGoingToSleep

然后调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java的onFinishedGoingToSleep方法:

    public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {if (mKeyguardService != null) {mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered);}mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;}

调用了frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java的onFinishedGoingToSleep方法:

    @Overridepublic void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {try {mService.onFinishedGoingToSleep(reason, cameraGestureTriggered);} catch (RemoteException e) {Slog.w(TAG , "Remote Exception", e);}}

通过binder调用了systemui进程中frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java的成员变量mBinder的onFinishedGoingToSleep方法:

        @Override // Binder interfacepublic void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {checkPermission();mKeyguardViewMediator.onFinishedGoingToSleep(reason, cameraGestureTriggered);mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.FINISHED_GOING_TO_SLEEP);}

总结

1 可以和亮屏流程对比来学习。

2 PhoneWindowManager会依次调用startedGoingToSleep、screenTurningOff、screenTurnedOff、finishedGoingToSleep方法

3 灭屏时SleepToken的获取和Keyguard的出现都会导致所有Activity被stop掉。

4 灭屏前会截屏,然后在灭屏动画中,这个截屏会盖在屏幕最前面,挡住所有窗口直到屏幕全黑。

灭屏流程 - 安卓R相关推荐

  1. 亮屏流程 - 安卓R

    PhoneWindowManager响应电源键 首先按下power键后调用frameworks/base/services/core/java/com/android/server/policy/Ph ...

  2. 截屏流程 - 安卓R

    截屏类型有三种,分别是全屏截屏.区域截屏和使用提供的图片作为截屏,定义在frameworks/base/core/java/android/view/WindowManager.java中: /*** ...

  3. 录屏流程 - 安卓R

    根据安卓实现录屏app可知,安卓录屏时要创建一个VirtualDisplay.本文介绍安卓录屏的底层原理. 从frameworks/base/media/java/android/media/proj ...

  4. Android 手机灭屏流程分析详解

    参考地址:https://www.jianshu.com/p/9241f3a91095 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 1.前言 2.Pow ...

  5. qcom平台 LCD亮灭屏流程及LCD知识点总结

    一.LK中亮屏流程 1.gcdb_display_init(),进行display初始化的起始地方: 2.oem_panel_select(),在这里去选择哪一款屏,也可以在这里添加新一款屏: 3.d ...

  6. Android Keyguard 亮灭屏流程分析

    文章目录 概述 Keyguard 关键文件 Power 灭屏 超时灭屏 Power 亮屏 FAQ 亮屏慢 概述 Keyguard 锁屏流程: Keyguard 加载时机:一个是开机的时候:另一个是灭屏 ...

  7. 常见的亮灭屏流程分析

    一 . 亮屏主要关键log 驱动按键时间 ??-?? ??:??:??.??? <3>[14082.058160]  (0)[70:pmic_thread]kpd: Power Key g ...

  8. Android6.0 亮屏灭屏流程(DisplayPowerControler、WMS)(二)亮度设置

    http://blog.csdn.net/kc58236582/article/details/54616756 上一篇博客我们主要分析了在setScreenState中调用PhoneWindowMa ...

  9. 窗口布局流程 - 安卓R

    窗口布局简介 在安卓的窗口管理系统中,经常要执行的一个操作是布局. 布局会做许多事情,例如更新焦点窗口.调整所有的窗口位置.设置wallpaperTarget以显示或隐藏壁纸.开始过渡动画等. 很多时 ...

最新文章

  1. python环境管理命令_conda管理Python环境
  2. 【计算机图形学课程】一.MFC基本绘图函数使用方法
  3. location.search
  4. 学习《apache源代码全景分析》之网络连接部分摘录
  5. linux卸载db2cli,DB2 for linux 安装
  6. 张娟娟(为奥运冠军名字作诗)
  7. leetcode180. 连续出现的数字(SQL)
  8. DevOps - 配置管理 - Ansible
  9. pythonjava app切出后无网络连接_Python爬虫爬资源时由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。怎么破?...
  10. html中加一个框与底部平齐,div+CSS实现单选复选框与文本对齐
  11. 暴力解决配置HTTPS后无法使用Hermit
  12. Android无线测试之—UiAutomator UiSelector API介绍之三
  13. 商品进销存管理系统、ERP系统源码
  14. 2020中青杯本科题目学习
  15. scanf 用法及陷阱(转)
  16. 如何高效的自学编程(新手篇)
  17. 三角函数之间的转换公式
  18. Low-Resource Knowledge-Grounded Dialogue Generation_biji
  19. win下apache2.4 支持php8.0
  20. 百家号如何提高推荐量和阅读量,百家号提高推荐量和阅读量的方法

热门文章

  1. 6pen Art - AI绘画平台
  2. 小米面试题:手机分身,电话号码隐藏。
  3. 深信服应用交付(AD)学习笔记
  4. 用AI画一只漂亮的羽毛
  5. sqlite 数据库连接问题以及解决方法
  6. 智能科学与技术 毕业设计怎么做 - 选题推荐 - 疑问解答
  7. 山东大学软件学院项目实训-创新实训-山大软院网络攻防靶场实验平台(七)-SQL注入字符型
  8. 群发邮件的方法有哪些?怎样大量群发邮件?
  9. 使用 JavaScript 和 CSS 做一个图片转 PDF 的转换器
  10. SVN修改提交用户名