PowerManagerService開機啟動關於WackLock處理的相關流程
Step 1:
frameworks\base\services\java\com\android\server\SystemServer.java
開啟PowerManagerService服務
private void startOtherServices() { ... try { // TODO: use boot phase mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); } catch (Throwable e) { reportWtf("making Power Manager Service ready", e); } ... }
Step 2:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
接下來分析下PowerManagerService載開機啟動的時候準備過程
主要工作流程如下:
1.獲取預設,最大,最小的三種螢幕亮度
2.建立SystemSensorManager物件,用於和SensorService互動。SensorService是一個native的Service,也存在於SystemServer程序中,管理各種感測裝置。
3.建立Notifer物件。Notifer物件用於廣播系統中和power相關的變化,例如螢幕關閉和開啟
4.建立WirelessChargerService物件,用於無線充電檢測的感測器
5.呼叫DisplayManagerService的initPowerManagement()的方法來初始化Power管理模組
6.註冊Observer監聽系統設定的變化。
7.註冊監聽其他模組的Intent。
public void systemReady(IAppOpsService appOps) { synchronized (mLock) { mSystemReady = true; mAppOps = appOps; //獲取DreamManagerService mDreamManager = getLocalService(DreamManagerInternal.class); //獲取DisplayManagerService mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class); mPolicy = getLocalService(WindowManagerPolicy.class); //獲得BatteryManagerService mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class); //以下獲取最大預設,最大和最小螢幕亮度 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting(); mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting(); mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting(); if (DEBUG_SPEW) { Slog.d(TAG, "mScreenBrightnessSettingMinimum = " + mScreenBrightnessSettingMinimum + " mScreenBrightnessSettingMinimum = " + mScreenBrightnessSettingMaximum + " mScreenBrightnessSettingDefault = " + mScreenBrightnessSettingDefault); } //建立預設SensorManager物件,用於和SensorService互動 SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper()); // The notifier runs on the system server's main looper so as not to interfere // with the animations and other critical functions of the power manager. //得到BatteryStatsService的引用物件 mBatteryStats = BatteryStatsService.getService(); //建立Notifier物件 mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats, mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy); //建立檢測無線充電物件WirelessChargerDetector mWirelessChargerDetector = new WirelessChargerDetector(sensorManager, createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"), mHandler); //建立系統設定變化的物件 mSettingsObserver = new SettingsObserver(mHandler); //初始化LightsService物件 mLightsManager = getLocalService(LightsManager.class); mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION); mButtonLight = mLightsManager.getLight(LightsManager.LIGHT_ID_BUTTONS); mBacklight = mLightsManager.getLight(LightsManager.LIGHT_ID_BACKLIGHT); //初始化Power模組 // Initialize display power management. mDisplayManagerInternal.initPowerManagement( mDisplayPowerCallbacks, mHandler, sensorManager); // Register for broadcasts from other components of the system. IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler); filter = new IntentFilter(); filter.addAction(Intent.ACTION_DREAMING_STARTED);//屏保啟動廣播 filter.addAction(Intent.ACTION_DREAMING_STOPPED);//屏保關閉廣播 mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler); filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_SWITCHED);//使用者切換廣播 mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler); filter = new IntentFilter(); filter.addAction(Intent.ACTION_DOCK_EVENT);//Dock 插拔事件廣播 mContext.registerReceiver(new DockReceiver(), filter, null, mHandler); // Register for SD Hot Plug notification filter = new IntentFilter(); filter.addAction(Intent.ACTION_SD_INSERTED);//SD 插入事件廣播 filter.addDataScheme("file"); mContext.registerReceiver(new SDHotPlugReceiver(), filter, null, mHandler); // Register for wfd notification mContext.registerReceiver(new WifiDisplayStatusChangedReceiver(), new IntentFilter(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED), null, mHandler); filter = new IntentFilter(); filter.addAction("com.mediatek.SCREEN_TIMEOUT_MINIMUM"); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) { Slog.d(TAG, "SCREEN_TIMEOUT_MINIMUM."); } mPreWakeUpWhenPluggedOrUnpluggedConfig = mWakeUpWhenPluggedOrUnpluggedConfig; mWakeUpWhenPluggedOrUnpluggedConfig = false; mUserActivityTimeoutMin = true; } }, filter, null, mHandler); filter = new IntentFilter(); filter.addAction("com.mediatek.SCREEN_TIMEOUT_NORMAL"); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) { Slog.d(TAG, "SCREEN_TIMEOUT_NORMAL."); } mWakeUpWhenPluggedOrUnpluggedConfig = mPreWakeUpWhenPluggedOrUnpluggedConfig; mUserActivityTimeoutMin = false; } }, filter, null, mHandler); // Register for settings changes. final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SCREENSAVER_ENABLED), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_OFF_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SLEEP_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.STAY_ON_WHILE_PLUGGED_IN), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_BRIGHTNESS), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_BRIGHTNESS_MODE), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.LOW_POWER_MODE), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.THEATER_MODE_ON), false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.DOUBLE_TAP_TO_WAKE), false, mSettingsObserver, UserHandle.USER_ALL); // Go. if (DEBUG) { Slog.d(TAG, "system ready!"); } readConfigurationLocked(); updateSettingsLocked(); mDirty |= DIRTY_BATTERY_STATE; updatePowerStateLocked(); } }
Step 3:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
updatePowerStatedLocked是整個PowerManagerService的核心方法,所有的之前狀態變數的數值以及相關服務都需要載目前這個方法進行操作
接下來針對具體方法具體介紹。
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {//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);//設定DIRTY_STAY_ON是否發生變化
updateScreenBrightnessBoostLocked(mDirty);//更新螢幕亮度狀態
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);//是根據PowerManagerService中所以的WackLock物件的型別,計算一個最終的型別集合
updateUserActivitySummaryLocked(now, dirtyPhase1);//用於判斷最後一次呼叫userActivity的時間,計算現在是否可以將表示螢幕狀態的變數mUserActivitySummary的值設定為SCREEN_STATE_DIM(變暗)或者SCREEN_STATE_OFF(關閉)
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);//判斷是否啟動屏保
// Phase 4: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();//在sys/power 儲存資料
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
updateIsPoweredLocked主要作用是更新當前電源狀態
private void updateIsPoweredLocked(int dirty) {
if ((dirty & DIRTY_BATTERY_STATE) != 0) {
final boolean wasPowered = mIsPowered;
final int oldPlugType = mPlugType;
final boolean oldLevelLow = mBatteryLevelLow;
mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);//表示是否在充電
mPlugType = mBatteryManagerInternal.getPlugType();//表示充電的型別
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();//表示當前電池電量等級
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+ ", mIsPowered=" + mIsPowered
+ ", oldPlugType=" + oldPlugType
+ ", mPlugType=" + mPlugType
+ ", mBatteryLevel=" + mBatteryLevel);
}
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {//是否充電或者充電型別改變了
mDirty |= DIRTY_IS_POWERED;
// Update wireless dock detection state.
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(//無線充電相關
mIsPowered, mPlugType, mBatteryLevel);
// Treat plugging and unplugging the devices as a user activity.
// Users find it disconcerting when they plug or unplug the device
// and it shuts off right away.
// Some devices also wake the device when plugged or unplugged because
// they don't have a charging LED.
final long now = SystemClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) {
wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
mContext.getOpPackageName(), Process.SYSTEM_UID);
}
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
// Tell the notifier whether wireless charging has started so that
// it can provide feedback to the user.
if (dockedOnWirelessCharger) {//是否需要喚醒裝置
mNotifier.onWirelessChargingStarted();
}
}
if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");
}
mAutoLowPowerModeSnoozing = false;
}
updateLowPowerModeLocked();//更新低功耗模式
}
}
}
updateStayOnLocked
我理解成表示手機的某種狀態,如是否在充電,螢幕亮度的情況
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {//當dirty是電池狀態和設定的狀態改變時
final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0//這個值從資源中讀取,一般設定的話代表哪種充電時可以常亮
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
//看有沒有設mMaximumScreenOffTimeoutFromDeviceAdmin螢幕最大亮屏.
mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);//用於判斷是否在充電
} else {
mStayOn = false;
}
if (mStayOn != wasStayOn) {
mDirty |= DIRTY_STAY_ON;
}
}
}
updateScreenBrightnessBoostLocked(mDirty);//更新螢幕亮度狀態
以下邏輯可以理解為判斷當前螢幕是否為最亮狀態,如果是當前手機狀態是最亮狀態,傳送一個延遲訊息,回頭再次進行判斷。
如果不是,走到下面的mScreenBrightnessBoostInProgress設定為false,走到mNotifier.onScreenBrightnessBoostChanged();對螢幕狀態變化進行設定
private void updateScreenBrightnessBoostLocked(int dirty) {
if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
if (mScreenBrightnessBoostInProgress) {//當前螢幕是否是最亮螢幕狀態
final long now = SystemClock.uptimeMillis();
mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
if (mLastScreenBrightnessBoostTime > mLastSleepTime) {//看當前時間是否小於最亮螢幕結束的時間
final long boostTimeout = mLastScreenBrightnessBoostTime +
SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
if (boostTimeout > now) {
Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);//傳送一個延遲的訊息,到最亮螢幕結束的時候接受到訊息,將標誌位置為DIRTY_SCREEN_BRIGHTNESS_BOOST後,重新再回到這個函式
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, boostTimeout);
return;
}
}
mScreenBrightnessBoostInProgress = false;//回到這個函式時,直接將這個螢幕最亮狀態的標誌位改成false
mNotifier.onScreenBrightnessBoostChanged();
userActivityNoUpdateLocked(now,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
}
}
updateWakeLockSummaryLocked
//是根據PowerManagerService中所以的WackLock物件的型別,計算一個最終的型別集合
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
mWakeLockSummary = 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) {//先根據wakelock的flag,mWakeLockSummary或上各種狀態
case PowerManager.PARTIAL_WAKE_LOCK://只儲存CPU執行,螢幕背光和鍵盤背光關閉
if (!wakeLock.mDisabled) {
// We only respect this if the wake lock is not disabled.
mWakeLockSummary |= WAKE_LOCK_CPU;
}
break;
case PowerManager.FULL_WAKE_LOCK://CPU,螢幕背光和鍵盤背光都不關閉
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK://CPU和螢幕背光不關閉,鍵盤背光關閉
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK://CPU和螢幕背光不關閉,鍵盤背光關閉,但是CPU和螢幕背光可以變暗
mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK://開啟距離感測器相關控制螢幕的功能
mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
break;
case PowerManager.DOZE_WAKE_LOCK://讓屏保管理器實現doze模式
mWakeLockSummary |= WAKE_LOCK_DOZE;
break;
case PowerManager.DRAW_WAKE_LOCK://讓屏保管理器實現DRAW模式
mWakeLockSummary |= WAKE_LOCK_DRAW;
break;
}
}
// Cancel wake locks that make no sense based on the current state.
if (mWakefulness != WAKEFULNESS_DOZING) {
mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);//下面根據各種狀態,將上面或上的mWakeLockSummary,有的減去
}
if (mWakefulness == WAKEFULNESS_ASLEEP
|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
| WAKE_LOCK_BUTTON_BRIGHT);
if (mWakefulness == WAKEFULNESS_ASLEEP) {
/* Power Key Force Wakeup to Keep Proximity Wakelock */
// mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
}
// Infer implied wake locks where necessary based on the current state.
if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {//只要有螢幕鎖,cpu鎖必須持有
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
} else if (mWakefulness == WAKEFULNESS_DREAMING) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
}
if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
}
}
}
updateUserActivitySummaryLocked();//用於判斷最後一次呼叫userActivity的時間,計算現在是否可以將表示螢幕狀態的變數mUserActivitySummary的值設定為SCREEN_STATE_DIM(變暗)或者SCREEN_STATE_OFF(關閉)
備註userActivity用於使用者程序向PowerManagerService報告當前使用者影響休眠的時間
/**
* Updates the value of mUserActivitySummary to summarize the user requested
* state of the system such as whether the screen should be bright or dim.
* Note that user activity is ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
Slog.d(TAG+"zewei","updateUserActivitySummaryLocked" + "start");
long nextTimeout = 0;
/*狀態為awake dreaming dozing,否則mUserActivitySummary = 0*/
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
final int sleepTimeout = getSleepTimeoutLocked();/*睡眠時間*/
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);//滅屏的timeout
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);//螢幕由亮變暗的timeout
final int screenButtonLightDuration = getButtonLightDurationLocked(screenOffTimeout);
Slog.d(TAG+"zewei","updateUserActivitySummaryLocked" + "mWakefulness == WAKEFULNESS_AWAKE || mWakefulness == WAKEFULNESS_DREAMING || mWakefulness == WAKEFULNESS_DOZING wwwww "
+ "sleepTimeout == " + sleepTimeout +" " + "screenOffTimeout == " + screenOffTimeout + " " + "screenDimDuration ==" + screenDimDuration + " " + "screenButtonLightDuration == " + screenButtonLightDuration);
mUserActivitySummary = 0;
if (mLastUserActivityTime >= mLastWakeTime) {//userActivity的time大於上次喚醒的時間
if ( (mLastUserActivityButtonTime >= mLastWakeTime) && (now < mLastUserActivityButtonTime + screenButtonLightDuration) ) {
mUserActivitySummary |= USER_ACTIVITY_BUTTON_BRIGHT;
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
nextTimeout = mLastUserActivityButtonTime + screenButtonLightDuration;
Slog.d(TAG+"zewei","updateUserActivitySummaryLocked" +"(mLastUserActivityButtonTime >= mLastWakeTime) && (now < mLastUserActivityButtonTime + screenButtonLightDuration) wwwww "
+ "nextTimeout == " + nextTimeout);
} else if (now < mLastUserActivityTime + screenOffTimeout - screenDimDuration) {
nextTimeout = mLastUserActivityTime + screenOffTimeout - screenDimDuration;//這個時間代表是比較亮的一個時間的結束點
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
Slog.d(TAG+"zewei","updateUserActivitySummaryLocked" +"now < mLastUserActivityTime + screenOffTimeout - screenDimDuration wwwww "
+ "nextTimeout == " + nextTimeout);
} else {
nextTimeout = mLastUserActivityTime + screenOffTimeout;//這個時間代表是比較暗的一個時間的結束點
Slog.d(TAG+"zewei","else wwwww "
+ "nextTimeout == " + nextTimeout);
if (now < nextTimeout) {
mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
Slog.d(TAG+"zewei","mLastUserActivityTime >= mLastWakeTime wwwww");
}
}
}
if (mUserActivitySummary == 0
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
Slog.d(TAG+"zewei","mUserActivitySummary == 0&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime wwwww " + "nextTimeout == " + nextTimeout);
if (now < nextTimeout) {
Slog.d(TAG+"zewei","mUserActivitySummary == 0&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime" + "now < nextTimeout wwwww ");
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0) {
Slog.d(TAG+"zewei","mUserActivitySummary == 0 wwwww ");
if (sleepTimeout >= 0) {
final long anyUserActivity = Math.max(mLastUserActivityTime,
mLastUserActivityTimeNoChangeLights);
if (anyUserActivity >= mLastWakeTime) {
nextTimeout = anyUserActivity + sleepTimeout;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
}
}
} else {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;//該值為-1,下面就不會發送訊息了
Slog.d(TAG+"zewei","mUserActivitySummary == 0 wwwww " + "nextTimeout == " + nextTimeout);
}
}
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
Slog.d(TAG+"zewei","mUserActivitySummary != 0 && nextTimeout >= 0 wwwww ");
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);//到下個時間timeout結束的時候傳送訊息,重新進入這個函式
}
} else {
mUserActivitySummary = 0;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
}
}
}
updateDreamLocked(dirtyPhase2, displayBecameReady);//判斷是否啟動屏保
private void updateDreamLocked(int dirty, boolean displayBecameReady) {
if ((dirty & (DIRTY_WAKEFULNESS
| DIRTY_USER_ACTIVITY
| DIRTY_WAKE_LOCKS
| DIRTY_BOOT_COMPLETED
| DIRTY_BOOT_IPO
| DIRTY_SETTINGS
| DIRTY_IS_POWERED
| DIRTY_STAY_ON
| DIRTY_SD_STATE
| DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
if (mDisplayReady) {
scheduleSandmanLocked();
}
}
}
Step 4:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
updateSuspendBlockerLocked();//在sys/power 儲存資料
private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);//看cpu是否要持鎖
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();//現在Display沒好,需要持Display的鎖
final boolean autoSuspend = !needDisplaySuspendBlocker;
final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
// Disable auto-suspend if needed.
// FIXME We should consider just leaving auto-suspend enabled forever since
// we already hold the necessary wakelocks.
if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(false);//呼叫JNI
}
// First acquire suspend blockers if needed.、
//如果不能休眠,呼叫底層的wak_lock 函式
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
//如果需要保持螢幕長亮,呼叫底層的wak_lock 函式
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
// Inform the power HAL about interactive mode.
// Although we could set interactive strictly based on the wakefulness
// as reported by isInteractive(), it is actually more desirable to track
// the display policy state instead so that the interactive state observed
// by the HAL more accurately tracks transitions between AWAKE and DOZING.
// Refer to getDesiredScreenPolicyLocked() for details.
if (mDecoupleHalInteractiveModeFromDisplayConfig) {
// When becoming non-interactive, we want to defer sending this signal
// until the display is actually ready so that all transitions have
// completed. This is probably a good sign that things have gotten
// too tangled over here...
if (interactive || mDisplayReady) {
setHalInteractiveModeLocked(interactive);
}
}
// Then release suspend blockers if needed.
//如果可以休眠,呼叫底層的解鎖函式
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
//如果不需要儲存螢幕長亮,呼叫底層的解鎖函式
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
// Enable auto-suspend if needed.
if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
}
Step 4:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
接下來我們看下acquire和release方法的具體情況 @Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
}
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
}
nativeReleaseSuspendBlocker(mName);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
} else if (mReferenceCount < 0) {
Slog.wtf(TAG, "Suspend blocker \"" + mName
+ "\" was released without being acquired!", new Throwable());
mReferenceCount = 0;
}
}
}
Step 5:
frameworks\base\services\core\jni\com_android_server_power_PowerManagerService.cpp
接下來我們看下
nativeReleaseSuspendBlocker 在JNI層的實現
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
release_wake_lock(name.c_str());
}
Step 6:
hardware\libhardware_legacy\power\power.c接下來我們看下
HAL層怎麼把數值寫進去的
const char * const OLD_PATHS[] = {
"/sys/android_power/acquire_partial_wake_lock",
"/sys/android_power/release_wake_lock",
};
const char * const NEW_PATHS[] = {
"/sys/power/wake_lock",
"/sys/power/wake_unlock",
};
...
initialize_fds(void)
{
// XXX: should be this:
//pthread_once(&g_initialized, open_file_descriptors);
// XXX: not this:
if (g_initialized == 0) {
if(open_file_descriptors(NEW_PATHS) < 0)
open_file_descriptors(OLD_PATHS);
g_initialized = 1;
}
}
int
acquire_wake_lock(int lock, const char* id)
{
initialize_fds();
// ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
if (g_error) return -g_error;
int fd;
if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return -EINVAL;
}
return write(fd, id, strlen(id));
}
int
release_wake_lock(const char* id)
{
initialize_fds();
// ALOGI("release_wake_lock id='%s'\n", id);
if (g_error) return -g_error;
ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
return len >= 0;
}
Step 7:
至於kernel層與HAL層怎麼進行互動的,我這邊沒有進行仔細分析了,但是通過搜尋程式碼資訊發現基本上走到這裡處理wacklock
kernel-3.18\kernel\power\wakelock.c
int pm_wake_lock(const char *buf)
{
const char *str = buf;
struct wakelock *wl;
u64 timeout_ns = 0;
size_t len;
int ret = 0;
if (!capable(CAP_BLOCK_SUSPEND))
return -EPERM;
while (*str && !isspace(*str))
str++;
len = str - buf;
if (!len)
return -EINVAL;
if (*str && *str != '\n') {
/* Find out if there's a valid timeout string appended. */
ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);
if (ret)
return -EINVAL;
}
mutex_lock(&wakelocks_lock);
wl = wakelock_lookup_add(buf, len, true);
if (IS_ERR(wl)) {
ret = PTR_ERR(wl);
goto out;
}
if (timeout_ns) {
u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;
do_div(timeout_ms, NSEC_PER_MSEC);
__pm_wakeup_event(&wl->ws, timeout_ms);
} else {
__pm_stay_awake(&wl->ws);
}
wakelocks_lru_most_recent(wl);
out:
mutex_unlock(&wakelocks_lock);
return ret;
}
int pm_wake_unlock(const char *buf)
{
struct wakelock *wl;
size_t len;
int ret = 0;
if (!capable(CAP_BLOCK_SUSPEND))
return -EPERM;
len = strlen(buf);
if (!len)
return -EINVAL;
if (buf[len-1] == '\n')
len--;
if (!len)
return -EINVAL;
mutex_lock(&wakelocks_lock);
wl = wakelock_lookup_add(buf, len, false);
if (IS_ERR(wl)) {
ret = PTR_ERR(wl);
goto out;
}
__pm_relax(&wl->ws);
wakelocks_lru_most_recent(wl);
wakelocks_gc();
out:
mutex_unlock(&wakelocks_lock);
return ret;
}