赞
踩
上一篇介绍了Android 电源键事件流程分析,其中分析了,在按电源键,长按的时候,弹出系统菜单,以及点击其中的关机按键,都执行了哪些操作。这一篇,作为上一篇的补充,主要分析一下,Android按键亮屏、息屏流程。
case KeyEvent.KEYCODE_POWER: { EventLogTags.writeInterceptPower( KeyEvent.actionToString(event.getAction()), mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter); // Any activity on the power button stops the accessibility shortcut cancelPendingAccessibilityShortcutAction(); result &= ~ACTION_PASS_TO_USER; isWakeKey = false; // wake-up will be handled separately if (down) { //interactive 表示当前是否是息屏 interceptPowerKeyDown(event, interactive); } else { interceptPowerKeyUp(event, interactive, canceled); } break; } private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { // Hold a wake lock until the power key is released. 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. //...................... } else { wakeUpFromPowerKey(event.getDownTime()); //...................... } } }
可以看到,在按下电源键的时候,如果判断,当前是息屏状态,则执行wakeUpFromPowerKey()方法,
private void wakeUpFromPowerKey(long eventTime) { wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER"); } 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); // Turn on the connected TV and switch HDMI input if we're a HDMI playback device. final HdmiControl hdmiControl = getHdmiControl(); if (hdmiControl != null) { hdmiControl.turnOnTv(); } return true; }
往下继续追
//android.os.PowerManager
public void wakeUp(long time, @WakeReason int reason, String details) {
try {
mService.wakeUp(time, reason, details, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
通过跨进程通信,我们知道真正的操作是在PowerManagerService类里的wakeUp()方法
@Override // Binder call public void wakeUp(long eventTime, @WakeReason int reason, String details, String opPackageName) { 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 { wakeUpInternal(eventTime, reason, details, uid, opPackageName, uid); } finally { Binder.restoreCallingIdentity(ident); } } 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(); } } }
我们首先分析wakeUpNoUpdateLocked()方法,如果它返回true,则执行updatePowerStateLocked方法
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 || getWakefulnessLocked() == WAKEFULNESS_AWAKE || mForceSuspendActive || !mSystemReady) { return false; } Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0); Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp"); try { //更新屏幕亮屏超时时间 mLastWakeTime = eventTime; mLastWakeReason = reason; setWakefulnessLocked(WAKEFULNESS_AWAKE, reason, eventTime); //通知BatteryStatsService、AppService系统服务状态改变 mNotifier.onWakeUp(reason, details, reasonUid, opPackageName, opUid); //更新用户活动时间 userActivityNoUpdateLocked( eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid); if (sQuiescent) { mDirty |= DIRTY_QUIESCENT; } } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true; }
先来看看setWakefulnessLocked方法
void 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); } }
继续往下追,查看Notifier类里的onWakefulnessChangeStarted方法
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() { @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) { 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(); } }
private void handleEarlyInteractiveChange() { synchronized (mLock) { if (mInteractive) { // Waking up... mHandler.post(new Runnable() { @Override public 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() { @Override public void run() { mPolicy.startedGoingToSleep(why); } }); } } }
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); } } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_BROADCAST: sendNextBroadcast(); break; //....................... } } private void sendWakeUpBroadcast() { if (DEBUG) { Slog.d(TAG, "Sending wake up broadcast."); } /** * mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); * mScreenOnIntent.addFlags( * Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND * | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); */ if (mActivityManagerInternal.isSystemReady()) { mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null, mWakeUpBroadcastDone, mHandler, 0, null, null); } else { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1); sendNextBroadcast(); } }
再来分析updatePowerStateLocked方法,此方法目的是更新PackageManagerService全局状态
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. /** *异步更新显示器电源状态。更新完成后,mDisplayReady 将设置为 true。显示控制器会发布一条消息,告诉我们实际显示电源状态何时更 * 新,因此我们回到这里仔细检查并完成。此功能每次重新计算显示器电源状态。返回:如果显示已准备好,则为true。 *经过这一步后,会将系统的亮度、显示状态等全部设置完毕,此时屏幕已经亮了 */ 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); } }
再来分析 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(); } }
Notifier类里的onWakefulnessChangeFinished
public void onWakefulnessChangeFinished() { if (DEBUG) { Slog.d(TAG, "onWakefulnessChangeFinished"); } if (mInteractiveChanging) { mInteractiveChanging = false; handleLateInteractiveChange(); } } private void handleLateInteractiveChange() { synchronized (mLock) { final int interactiveChangeLatency = (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime); if (mInteractive) { // Finished waking up... final int why = translateOnReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run() { LogMaker log = new LogMaker(MetricsEvent.SCREEN); log.setType(MetricsEvent.TYPE_OPEN); log.setSubtype(why); log.setLatency(interactiveChangeLatency); log.addTaggedData( MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason); MetricsLogger.action(log); EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency); //通知PhoneWindowManager唤醒操作结束 mPolicy.finishedWakingUp(why); } }); } else { } } }
同唤醒操作类似,按键首先会走执行
case KeyEvent.KEYCODE_POWER: { EventLogTags.writeInterceptPower( KeyEvent.actionToString(event.getAction()), mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter); // Any activity on the power button stops the accessibility shortcut cancelPendingAccessibilityShortcutAction(); result &= ~ACTION_PASS_TO_USER; isWakeKey = false; // wake-up will be handled separately if (down) { interceptPowerKeyDown(event, interactive); } else { //手指抬起 interceptPowerKeyUp(event, interactive, canceled); } break; } private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) { final boolean handled = canceled || mPowerKeyHandled; mScreenshotChordPowerKeyTriggered = false; cancelPendingScreenshotChordAction(); cancelPendingPowerKeyAction(); if (!handled) { if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) == 0) { // Abort possibly stuck animations only when power key up without long press case. mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe); } // Figure out how to handle the key now that it has been released. mPowerKeyPressCounter += 1; final int maxCount = getMaxMultiPressPowerCount(); final long eventTime = event.getDownTime(); if (mPowerKeyPressCounter < maxCount) { // This could be a multi-press. Wait a little bit longer to confirm. // Continue holding the wake lock. Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS, interactive ? 1 : 0, mPowerKeyPressCounter, eventTime); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout()); return; } //核心代码 // No other actions. Handle it immediately. powerPress(eventTime, interactive, mPowerKeyPressCounter); } // Done. Reset our state. finishPowerKeyPress(); }
继续往下追
private void powerPress(long eventTime, boolean interactive, int count) { if (mDefaultDisplayPolicy.isScreenOnEarly() && !mDefaultDisplayPolicy.isScreenOnFully()) { Slog.i(TAG, "Suppressed redundant power key press while " + "already in the process of turning the screen on."); return; } Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive + " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive + " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior); 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_NOTHING: break; case SHORT_PRESS_POWER_GO_TO_SLEEP: goToSleepFromPowerButton(eventTime, 0); break; case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP: goToSleepFromPowerButton(eventTime, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); break; //.................... } } } }
查看mShortPressOnPowerBehavior赋值
mShortPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shortPressOnPowerBehavior);
//通过查看配置文件
<!-- Control the behavior when the user short presses the power button.
0 - Nothing
1 - Go to sleep (doze)
2 - Really go to sleep (don't doze)
3 - Really go to sleep and go home (don't doze)
4 - Go to home
5 - Dismiss IME if shown. Otherwise go to home
-->
<integer name="config_shortPressOnPowerBehavior">1</integer>
执行case SHORT_PRESS_POWER_GO_TO_SLEEP,即goToSleepFromPowerButton()方法
//由于按下电源按钮,设备进入睡眠状态。返回:如果设备被发送到睡眠状态,则返回 true,如果睡眠被抑制,则返回 false 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; }
private void goToSleep(long eventTime, int reason, int flags) {
mRequestedOrGoingToSleep = true;
mPowerManager.goToSleep(eventTime, reason, flags);
}
继续往下追PowerManagerService 的goToSleep()
@Override // Binder call public 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); } } private void goToSleepInternal(long eventTime, int reason, int flags, int uid) { synchronized (mLock) { if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) { updatePowerStateLocked();//稍后分析 } } }
@SuppressWarnings("deprecation") private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) { //........................ 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 + ")..."); //同wakeup一样,更新最后一次息屏时间 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; }
同wakeup一样,会走到Notifer类的onWakefulnessChangeStarted()方法
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() { @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) { 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(); } }
继续看handleErarlyInteractiveChange()方法
private void handleEarlyInteractiveChange() { synchronized (mLock) { if (mInteractive) { // Waking up... mHandler.post(new Runnable() { @Override public 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() { @Override public void run() { ///通知PhoneWindowManager执行sleep操作 mPolicy.startedGoingToSleep(why); } }); } } }
我们现在在返回去看updatePowerStateLocked方法,对,没错,唤醒的时候,也会走到这里
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); } }
当息屏执行结束,我们分析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(); } }
我们继续来分析Notifier类的onWakefulnessChangeFinished方法
public void onWakefulnessChangeFinished() {
if (DEBUG) {
Slog.d(TAG, "onWakefulnessChangeFinished");
}
if (mInteractiveChanging) {
mInteractiveChanging = false;
handleLateInteractiveChange();
}
}
private void handleLateInteractiveChange() { synchronized (mLock) { final int interactiveChangeLatency = (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime); if (mInteractive) { // Finished waking up... final int why = translateOnReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run() { LogMaker log = new LogMaker(MetricsEvent.SCREEN); log.setType(MetricsEvent.TYPE_OPEN); log.setSubtype(why); log.setLatency(interactiveChangeLatency); log.addTaggedData( MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason); MetricsLogger.action(log); EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency); mPolicy.finishedWakingUp(why); } }); } 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() { @Override public 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); //通知PhoneWindowManager 息屏完成 mPolicy.finishedGoingToSleep(why); } }); // Send non-interactive broadcast. mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP; mPendingGoToSleepBroadcast = true; //发送息屏广播,和唤醒类似,就不再赘述了。 updatePendingBroadcastLocked(); } } }
好了,从我们分析源码得知
唤醒的时候,唤醒广播是在handleEarlyInteractiveChange方法,就是在通知PhoneWindowManager 去执行startedWakingUp方法,紧跟着就执行updatePendingBroadcastLocked方法,去发送唤醒广播
而在息屏的时候,在handleEarlyInteractiveChange里,我们只是通知PhoneWindowManager去执行startedGoingToSleep方法,最后在updatePowerStateLocked==>finishWakefulnessChangeIfNeededLocked==>Notifier==>onWakefulnessChangeFinished==》handleLateInteractiveChange方法里,在通知PhoneWindowManager执行finishedGoingToSleep()之后,才执行updatePendingBroadcastLocked()方法去发送息屏广播(Intent.ACTION_SCREEN_OFF),这个时机需要特别注意一下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。