PowerManagerServiceの起動WackLock処理に関するプロセス
37426 ワード
Step 1: frameworksbaseservicesjavacomandroidserverSystemServer.java PowerManagerServiceサービスを開始
Step 2:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
次に、PowerManagerServiceの起動時の準備手順を分析します.
主なワークフローは次のとおりです.
1.デフォルト、最大、最小の3種類の画面輝度を取得
2.SensorServiceと対話するためのSystemSensorManagerオブジェクトを作成します.SensorServiceはnativeのサービスであり、SystemServerプロセスにも存在し、様々なセンシングデバイスを管理しています.
3.Notiferオブジェクトを作成します.Notiferオブジェクトは、画面を閉じたり開いたりするなど、システム内のPower関連の変化をブロードキャストするために使用されます.
4.ワイヤレス充電検出用のWirelessChargerServiceオブジェクトを作成するセンサ
5.DisplayManagerServiceのinitPowerManagement()を呼び出す方法でPower管理モジュールを初期化する
6.登録Observerリスニングシステムの設定の変更.
7.他のモジュールをリスニングするIntentを登録します.
Step 3:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
updatePowerStatedLockedはPowerManagerService全体のコアメソッドであり、すべての以前のステータス変数の数値と関連サービスは現在のメソッドを搭載して操作する必要があります.
次に具体的な方法について具体的に紹介します.
updateIsPoweredLockedの主な役割は、現在の電源ステータスを更新することです.
updateStayOnLocked
充電しているかどうか、画面の明るさなど、携帯電話のある状態を表すと理解しています.
updateScreenBrightnessBoostLocked(mDirty);//画面の明るさの状態を更新
以下の論理は、現在の画面が最も明るい状態であるか否かを判断し、現在の携帯電話の状態が最も明るい状態であれば、遅延メッセージを送信し、後で再度判断すると理解できる.
そうでない場合は、次のmScreenBrightness BoostInProgressをfalseに設定し、mNotifer.onScreenBrightness BoostChanged()に移動します.画面の状態変化を設定する
updateWakeLockSummaryLocked
//PowerManagerServiceのWackLockオブジェクトのタイプに基づいて、最終的なタイプのセットを計算します.
updateUserActivitySummaryLocked();//最後にuserActivityが呼び出された時刻を判断し、画面の状態を表す変数mUserActivity Summaryの値をSCREEN_に設定できるかどうかを計算します.STATE_DIM(暗くなる)またはSCREEN_STATE_OFF(OFF)
メモuserActivityユーザープロセスがPowerManagerServiceに現在のユーザーがスリープに影響する時間を報告するために使用
updateDreamLocked(dirtyPhase2, displayBecameReady);//スクリーンセーバーを起動するかどうかを判断する
Step 4:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
updateSuspendBlockerLocked();//sys/powerにデータを格納する
Step 4:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java 次にacquireとreleaseの方法の具体的な状況を見てみましょう
Step 5:
frameworks\base\services\core\jni\com_android_server_power_PowerManagerService.cpp
次に見てみましょう
nativeReleaseSuspendBlockerのJNI層での実装
Step 6: hardware\libhardware_legacy\power\power.c
次に見てみましょう
HAL層はどのように数値を書きます
Step 7:
kernel層とHAL層がどのように相互作用するかについては、こちらでは詳しく分析していませんが、コード情報を検索することで基本的にはここまでwacklockを処理していることがわかりました.
kernel-3.18\kernel\power\wakelock.c
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.デフォルト、最大、最小の3種類の画面輝度を取得
2.SensorServiceと対話するためのSystemSensorManagerオブジェクトを作成します.SensorServiceはnativeのサービスであり、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);//画面の明るさの状態を更新
以下の論理は、現在の画面が最も明るい状態であるか否かを判断し、現在の携帯電話の状態が最も明るい状態であれば、遅延メッセージを送信し、後で再度判断すると理解できる.
そうでない場合は、次のmScreenBrightness BoostInProgressをfalseに設定し、mNotifer.onScreenBrightness BoostChanged()に移動します.画面の状態変化を設定する
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が呼び出された時刻を判断し、画面の状態を表す変数mUserActivity Summaryの値をSCREEN_に設定できるかどうかを計算します.STATE_DIM(暗くなる)またはSCREEN_STATE_OFF(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'
", 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'
", 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 != '
') {
/* 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] == '
')
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;
}