一.PowerManagerService
1.概述
???????PowerManagerService是負責管理、協(xié)調設備電源管理的系統(tǒng)服務之一,設備常見功能如亮滅屏、亮度調節(jié)、低電量模式、保持CPU喚醒等,都會通過PMS的協(xié)調和處理。其繼承自SystemService,因此具有SystemService子類的共性:具有生命周期方法,由SystemServer啟動、注冊到系統(tǒng)服務中,通過Binder和其他組件進行交互等。
2.結構圖
3.啟動過程
???????和SystemService的其他子類一樣,PMS由SystemServer通過反射的方式啟動,看一下PMS的構造方法:
3.1.構造方法
public PowerManagerService(Context context) {
super(context);
mContext = context;
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
qcNsrmPowExt = new QCNsrmPowerExtension(this);
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
mWakefulness = WAKEFULNESS_AWAKE;
sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
nativeInit();
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
}
}
???????通過上面可以看到,在構造方法中首先創(chuàng)建了一個HandlerThread;其次獲取了兩個Suspend鎖,SuspendBlocker是一種鎖機制,只用于系統(tǒng)內部,上層申請的Wakelock鎖在PMS中都會反映為SuspendBlocker鎖。這里獲取的兩個Suspend鎖在申請Wakelock時會用到;最后調用了native方法,這幾個方法會通過JNI層調用到HAL層。
3.2.onStart()
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
publishLocalService(PowerManagerInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
???????在該方法中,首先對該服務進行Binder注冊和本地注冊,當進行Binder注冊后,在其他模塊中就可以通過Binder機制獲取其實例,同理,當進行本地注冊后,只有在System進程才能獲取到其實例;最后設置Watchdog的監(jiān)聽。
3.3.onBootPhase()
@Override
public void onBootPhase(int phase) {
synchronized (mLock) {
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
incrementBootCount();
} else if (phase == PHASE_BOOT_COMPLETED) {
final long now = SystemClock.uptimeMillis();
mBootCompleted = true;
mDirty |= DIRTY_BOOT_COMPLETED;
userActivityNoUpdateLocked(now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0,
Process.SYSTEM_UID, Display.DEFAULT_DISPLAY);
updatePowerStateLocked();
if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
for (Runnable r : mBootCompletedRunnables) {
BackgroundThread.getHandler().post(r);
}
}
mBootCompletedRunnables = null;
}
}
}
???????在這個方法中,設置mBootCompleted為true,表示啟動完成,將mDirty置位,mDirty是一個二進制的標記位,用來表示電源狀態(tài)哪一部分發(fā)生了改變,通過對其進行置位(|操作)、清零(~操作),得到二進制數(shù)各個位的值(0或1),進行不同的處理 ,然后執(zhí)行updatePowerStateLocked()方法,這是整個PMS中最重要的方法,這塊會在下文中具體功能中進行詳細分析。
3.4.systemReady()
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
mAppOps = appOps;
mDreamManager = getLocalService(DreamManagerInternal.class);
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
mPolicy = getLocalService(WindowManagerPolicy.class);
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
mScreenBrightnessForVrSettingDefault = pm.getDefaultScreenBrightnessForVrSetting();
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.
mBatteryStats = BatteryStatsService.getService();
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
// Go.
readConfigurationLocked();
updateSettingsLocked();
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
final ContentResolver resolver = mContext.getContentResolver();
mConstants.start(resolver);
mBatterySaverPolicy.start(resolver);
// Register for settings changes.
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ENABLED),
false, mSettingsObserver, UserHandle.USER_ALL);
..........
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.DREAM_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
..............
// 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);
..............
}
???????該方法內主要有5個重要功能:
a.獲取各類本地服務和遠程服務,如屏保(DreamMangerService)、窗口(PhoneWindowManager)、電池狀態(tài)監(jiān)聽服務(BatteryService)等服務,用于進行交互;
b.注冊用于和其他Sytem交互的廣播;
c.調用updateSettingsLocked()方法更新Settings中值的變化;
d.調用readConfigurationLocked()方法讀取配置文件中的默認值;
e.注冊SettingsObserver監(jiān)聽;
以上就是PowerManagerService的整個啟動過程;
二.屏幕亮度調節(jié)
1.調節(jié)流程
???????當通過系統(tǒng)設置等進行屏幕亮度調節(jié)時,會調用到PMS內部的updatePowerStateLocked(),通過該方法進行接下來的邏輯執(zhí)行,最終通過HAL層來設置屏幕亮度,本文基于Android 8.1版本進行分析:
1.1.PowerManagerService.java
1.1.1.updatePowerStateLocked()
protected void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
...................
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
updateScreenBrightnessBoostLocked(mDirty);
// Phase 1: Update wakefulness.
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
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.
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
???????當亮度調節(jié)時,處理邏輯主要是在phase 2,即updateDisplayPowerStateLocked(dirtyPhase2),一起看一下該方法:
1.1.2.updateDisplayPowerStateLocked()
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) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
int screenBrightness;
boolean autoBrightness;
if (!mBootCompleted)
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
screenBrightness = mScreenBrightnessSettingMinimum;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
screenBrightness = Math.max(Math.min(screenBrightness,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
autoBrightness = false;
} else {
autoBrightness = (mScreenBrightnessModeSetting ==
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
screenBrightness = -1;
}
....................
// Update display power request.
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
........................
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if ((dirty & DIRTY_QUIESCENT) != 0) {
sQuiescent = false;
}
...............
}
return mDisplayReady && !oldDisplayReady;
}
???????該方法內部主要做了兩件事:
a.封裝DisplayPowerRequest實例mDisplayPowerRequest,包括通過
getDesiredScreenPolicyLocked()獲取policy,此處為DisplayPowerRequest.POLICY_BRIGHT;還有screenBrightness等;
b.調用DisplayManagerInternal的requestPowerState(),上步封裝的DisplayPowerRequest作為參數(shù)傳入,mDisplayManagerInternal是在systemReady()內部獲取的;
1.2.DisplayPowerController.java
1.2.1.requestPowerState()
???????DisplayManagerInternal內部的requestPowerState為抽象方法,因此會調用到實現(xiàn)類中,具體是在DisplayManagerService內部的LocalService,看一下具體實現(xiàn):
public boolean requestPowerState(DisplayPowerRequest request,
return mDisplayPowerController.requestPowerState(request,waitForNegativeProximity);
}
???????最終會調用到DisplayPowerController內部的requestPowerState()方法:
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mLock) {
boolean changed = false;
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
} else if (!mPendingRequestLocked.equals(request)) {
mPendingRequestLocked.copyFrom(request);
changed = true;
}
if (changed) {
mDisplayReadyLocked = false;
}
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
return mDisplayReadyLocked;
}
}
???????在該方法內部先將傳入的DisplayPowerRequest對象賦值給mPendingRequestLocked,后續(xù)會使用;接著執(zhí)行sendUpdatePowerStateLocked(),在該方法內部會發(fā)送異步消息MSG_UPDATE_POWER_STATE,對應處理方法為updatePowerState();
1.2.2.updatePowerState()
private void updatePowerState() {
...............
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
mustNotify = !mDisplayReadyLocked;
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
initialize();
}
int state;
int brightness = PowerManager.BRIGHTNESS_DEFAULT;
boolean performScreenOffTransition = false;
switch (mPowerRequest.policy) {
case DisplayPowerRequest.POLICY_OFF:
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
............
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON;
break;
}
..........................
..........................
final int oldState = mPowerState.getScreenState();
animateScreenStateChange(state, performScreenOffTransition);
state = mPowerState.getScreenState();
....................................
.....根據(jù)策略選擇最終的brightness值.....
....................................
animateScreenBrightness(brightness,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
...........
}
???????該方法內部主要干了6件事:
a.將要更新的DisplayPowerRequest實例賦值給mPowerRequest;
b.如果為首次執(zhí)行的話,需要執(zhí)行initialize()來執(zhí)行初始化操作,創(chuàng)建DisplayPowerState實例mPowerState、RampAnimator實例mScreenBrightnessRampAnimator等;
private void initialize() {
// Initialize the power state object for the default display.
// In the future, we might manage multiple displays independently.
mPowerState = new DisplayPowerState(mBlanker,
mColorFadeEnabled ? new ColorFade(Display.DEFAULT_DISPLAY) : null);
mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
// Initialize screen state for battery stats.
try {
mBatteryStats.noteScreenState(mPowerState.getScreenState());
mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
} catch (RemoteException ex) {
// same process
}
}
???????c.根據(jù)mPowerRequest.policy來更新state,此處為Display.STATE_ON;
d.執(zhí)行animateScreenStateChange(state, performScreenOffTransition)來更新DisplayPowerState;
e.根據(jù)策略進行選擇,最終確定要更新的brightness值;
f.執(zhí)行animateScreenBrightness(brightness,slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast)來進行更新;
1.3.RampAnimator.java
1.3.1.animateScreenBightness()
private void animateScreenBrightness(int target, int rate) {
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
try {
mBatteryStats.noteScreenBrightness(target);
} catch (RemoteException ex) {
// same process
}
}
}
1.3.2.animateTo()
public boolean animateTo(int target, int rate) {
// Immediately jump to the target the first time.
if (mFirstTime || rate <= 0) {
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false;
mRate = 0;
mTargetValue = target;
mCurrentValue = target;
mProperty.setValue(mObject, target);
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd();
}
return true;
}
return false;
}
......................
return changed;
}
???????可以看到,在animateTo()內部會執(zhí)行mProperty.setValue(mObject, target),mProperty對應的是
DisplayPowerState.SCREEN_BRIGHTNESS,mObject對應的是mPowerState,都是在DisplayPowerController內部的initialize()內部傳入的,接下來就進入了DisplayPowerState內部了;
1.4.DisplayPowerState.java
1.4.1.setScreenBightness()
public void setScreenBrightness(int brightness) {
if (mScreenBrightness != brightness) {
if (DEBUG) {
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
}
mScreenBrightness = brightness;
if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate();
}
}
}
???????scheduleScreenUpdate()會執(zhí)行到postScreenUpdateThreadSafe(),然后會post mScreenUpdateRunnable;
1.4.2.mScreenUpdateRunnable
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
int brightness = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : 0;
if (mPhotonicModulator.setState(mScreenState, brightness)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
};
1.4.3.PhotonicModulator.setState()
private final class PhotonicModulator extends Thread {
................
................
public boolean setState(int state, int backlight) {
synchronized (mLock) {
boolean stateChanged = state != mPendingState;
boolean backlightChanged = backlight != mPendingBacklight;
if (stateChanged || backlightChanged) {
mPendingState = state;
mPendingBacklight = backlight;
..................
if (!changeInProgress) {
mLock.notifyAll();
}
}
}
return !mStateChangeInProgress;
}
@Override
public void run() {
for (;;) {
// Get pending change.
final int state;
final boolean stateChanged;
final int backlight;
final boolean backlightChanged;
synchronized (mLock) {
state = mPendingState;
stateChanged = (state != mActualState);
backlight = mPendingBacklight;
backlightChanged = (backlight != mActualBacklight);
if (!stateChanged) {
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;
}
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
if (!stateChanged && !backlightChanged) {
try {
mLock.wait();
} catch (InterruptedException ex) { }
continue;
}
mActualState = state;
mActualBacklight = backlight;
}
// Apply pending change.
if (DEBUG) {
Slog.d(TAG, "Updating screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
mBlanker.requestDisplayState(state, backlight);
}
}
}
}
???????可以看到,在執(zhí)行setState()后,最終會執(zhí)行mBlanker.requestDisplayState(state, backlight),mBlanker是DisplayBlanker實例,初始化是在DisplayPowerController構造方法內,在DisplayPowerController內部的initialize()內部傳入的,根據(jù)調用關系會追溯到DisplayMangerService的LocalService的initPowerManagerment()方法,該方法是在PowerManagerService的systemReady()方法內執(zhí)行的;
1.5.DisplayManagerService.java
1.5.1.requestDisplayState()
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
DisplayBlanker blanker = new DisplayBlanker() {
@Override
public void requestDisplayState(int state, int brightness) {
// The order of operations is important for legacy reasons.
if (state == Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
callbacks.onDisplayStateChange(state);
if (state != Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
}
};
mDisplayPowerController = new DisplayPowerController(
mContext, callbacks, handler, sensorManager, blanker);
}
}
???????由于傳入的state為Display.STATE_ON,執(zhí)行到requestGlobalDisplayStateInternal(state, brightness),根據(jù)調用關系最終會執(zhí)行到updateDisplayStateLocked()獲取Runnable實例;
1.5.2.updateDisplayStateLocked()
private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) {
DisplayDevice device = mDisplayDevices.get(i);
Runnable runnable = updateDisplayStateLocked(device);
if (runnable != null) {
workQueue.add(runnable);
}
}
}
private Runnable updateDisplayStateLocked(DisplayDevice device) {
// Blank or unblank the display immediately to match the state requested
// by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
}
return null;
}
???????根據(jù)調用關系看到,會通過DisplayDevice的requestDisplayStateLocked()來獲取到Runnable;
在DisplayManagerService的onStart()內發(fā)送消息來執(zhí)行registerDisplayAdapterLocked(new LocalDisplayAdapter())加載BUILT_IN_DISPLAY_IDS_TO_SCAN對應的LocalDisplayDevice(繼承DisplayDevice),加載成功后存入mDisplayDevices列表內進行管理;
在創(chuàng)建LocalDisplayDeivce時會通過lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT)獲取mBackLight,對應的是LightsService內部的LightImpl繼承l(wèi)ight;
在通過LocalDisplayDevice獲取到Runnable后接著執(zhí)行run(),會執(zhí)行到setDisplayBrightness();
1.6.LocalDisplayDevice
1.6.1.setDisplayBrightness()
private void setDisplayBrightness(int brightness) {
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
try {
mBacklight.setBrightness(brightness);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness", brightness);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
???????在setDisplayBrightness()內部會執(zhí)行到mBacklight.setBrightness(brightness),具體實現(xiàn)邏輯是在LightsService內部;
1.7.LightsService.java
1.7.1.setLightLocked()
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode, int displayId) {
..............
try {
setLight_native(mId, color, mode, onMS, offMS, brightnessMode, displayId);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
???????最終通過native方法調用到HAL層對屏幕的背光進行設置。
1.8.流程總結
2.調節(jié)方式
???????不同的調節(jié)方式對應不同的入口及判斷邏輯,只分析調用入口及涉及的關鍵策略來選擇最終目標brightness值邏輯;
2.1.系統(tǒng)設置調節(jié)
???????系統(tǒng)設置在調節(jié)屏幕亮度時,會實時更新Settings.SCREEN_BRIGHTNESS值,DisplayPowerController在監(jiān)聽到該值變化后會執(zhí)行handleSettingsChanged()方法:
private void handleSettingsChange(boolean userSwitch) {
mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
sendUpdatePowerState();
}
private int getScreenBrightnessSetting() {
final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS,
mScreenBrightnessDefault, UserHandle.USER_CURRENT);
return clampAbsoluteBrightness(brightness);
}
???????監(jiān)聽到變化后,先通過getScreenBrightnessSetting()來獲取到當前值,然后賦值給mPendingScreenBrightnessSetting,接下來執(zhí)行sendUpdatePowerState(),最終執(zhí)行updatePowerState()方法:
private void updatePowerState() {
..................
..................
final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
if (brightness < 0) {
brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting);
Slog.i(TAG, "updatePowerState mCurrentScreenBrightnessSetting="
+ mCurrentScreenBrightnessSetting);
}
private boolean updateUserSetScreenBrightness() {
if (mPendingScreenBrightnessSetting < 0) {
return false;
}
if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
mPendingScreenBrightnessSetting = -1;
mTemporaryScreenBrightness = -1;
return false;
}
mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
mPendingScreenBrightnessSetting = -1;
mTemporaryScreenBrightness = -1;
return true;
}
???????結論:系統(tǒng)設置會根據(jù)mCurrentScreenBrightnessSetting的值來設置對應的目標brightness值;
2.2.快速設置調節(jié)
???????快速設置來滑動進度條來調節(jié)屏幕亮度時,會調用PowerManagerService的setTemporaryScreenBrightnessSettingOverride()方法:
private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
synchronized (mLock) {
mDisplayManagerInternal.setTemporaryBrightness(brightness);
}
}
???????跟隨調用關系,調用到DisplayPowerController的setTemporaryBrightness()方法,發(fā)送MSG_SET_TEMPORARY_BRIGHTNESS消息,設置mTemporaryScreenBrightness為傳入的值,然后執(zhí)行updatePowerState():
private void updatePowerState() {
..................
..................
if (mTemporaryScreenBrightness > 0) {
Slog.i(TAG, "updatePowerState mTemporaryScreenBrightness="
+ mTemporaryScreenBrightness);
brightness = mTemporaryScreenBrightness;
}
}
結論:快速設置會根據(jù)mTemporaryScreenBrightness的值來設置對應的目標brightness值;
2.3.Window屬性調節(jié)
在視頻播放界面可以通過左側上下滑動來調節(jié)屏幕亮度,具體實現(xiàn)方式如下:
private synchronized void adjustLight(Window window, float value) {
value = value / FULL_SCREEN_HEIGHT * 2;
WindowManager.LayoutParams lp = window.getAttributes();
if (lp.screenBrightness < 0) {
lp.screenBrightness = Utils.getSystemBrightness(this);
}
lp.screenBrightness = lp.screenBrightness + value;
if (lp.screenBrightness > 1f) {
lp.screenBrightness = 1f;
} else if (lp.screenBrightness < 0f) {
lp.screenBrightness = 0f;
}
window.setAttributes(lp);
}
???????Window是activity對應的Window,通過getWindow()可以得到,設置WindowManager.LayoutParams內部的screenBrightness后執(zhí)行window.setAttributes(lp)可以來調節(jié)屏幕亮度;
Window執(zhí)行setAttributes()會執(zhí)行到Activity的onWindowAttributesChanged()方法,調用到WindowManagerGlobal的updateViewLayout()最終調用到ViewRootImpl的setLayoutParams來執(zhí)行重新繪制;
繪制流程就不陳述了,最終會執(zhí)行到RootWindowContainer內部的performSurfacePlacement()方法,接下來通過handleNotObscuredLocked()獲取到對應WindowState的w.mAttrs.screenBrightness賦值給mScreenBrightness,然后在performSurfacePlacement()發(fā)送SET_SCREEN_BRIGHTNESS_OVERRIDE消息,最終通過WindowManagerService來調用到PowerManagerService內部的setScreenBrightnessOverrideFromWindowManager()方法:
@Override
public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
|| screenBrightness > PowerManager.BRIGHTNESS_ON) {
screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
}
private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
synchronized (mLock) {
if (mScreenBrightnessOverrideFromWindowManager != brightness) {
mScreenBrightnessOverrideFromWindowManager = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
???????可以看到,在setScreenBrightnessOverrideFromWindowManagerInternal()內部會將brightness賦值給mScreenBrightnessOverrideFromWindowManager,然后執(zhí)行updatePowerStateLocked(),先看
updateDisplayPowerStateLocked()方法:
private boolean updateDisplayPowerStateLocked(int dirty) {
...........................
...........................
else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
screenBrightness = Math.max(Math.min(screenBrightness,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
autoBrightness = false;
}
???????可以看到,screenBrightness會設置為mScreenBrightnessOverrideFromWindowManager,該值默認為-1,經(jīng)過設置后screenBrightness>0,接著執(zhí)行到DisplayPowerController的updatePowerState()方法:
private void updatePowerState() {
..................
..................
if (brightness < 0 && mPowerRequest.screenBrightness >= 0) {
Slog.i(TAG, "updatePowerState mPowerRequest.screenBrightness="
+ mPowerRequest.screenBrightness);
brightness = mPowerRequest.screenBrightness;
// boot or WindowManager override brightness need clear temporary
mTemporaryScreenBrightness = -1;
}
}
結論:Window屬性調節(jié)會根據(jù)mScreenBrightnessOverrideFromWindowManager的值來設置對應的目標brightness值;
2.4.總結
???????設置屏幕亮度時,主要是在DisplayPowerController內部的updatePowerState()來對目標screenBrightness進行設置,screenBrightness默認值為PowerManager.BRIGHTNESS_DEFAULT = -1,會根據(jù)DisplayPowerRequest及其他策略進行選擇,順序依次為:
a.if (brightness < 0 && mPowerRequest.screenBrightness >= 0):通過設置Window屬性來進行調節(jié)(視頻播放界面)
b.if (mTemporaryScreenBrightness > 0):通過快速設置滑動來進行調節(jié)
c.if (brightness < 0) {brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting)}:通過系統(tǒng)設置滑動調節(jié)
三.自動進入屏保
???????當系統(tǒng)設置內部設置了自動進入屏保時間后,如果在此段時間后滿足進入條件,會進入屏保,該邏輯入口是在PMS內部的updatePowerStateLocked(),一起看一下:
1.整體流程
???????本流程只分析滿足條件后進入屏保的整個過程,關于條件判斷會在下一節(jié)中進行分析,先從updatePowerStateLocked()看起:
1.1.PowerManagerService.java
1.1.1.updatePowerStateLocked()
protected void updatePowerStateLocked() {
.................
.................
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
....................
// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
...................
}
???????在該方法內部首先循環(huán)執(zhí)行了三個方法:
a.updateWakeLockSummaryLocked():根據(jù)mWakeLocks來計算得到mWakeLockSummary的值;
???????b.updateUserActivitySummaryLocked():計算得到mUserActivitySummary以及何時進行下一次check;
???????c.updateWakefulnessLocked():判斷是否可以進入屏保及更新mWakefulness狀態(tài);
d.updateDreamLocked():根據(jù)當前狀態(tài)選擇是否進入屏保;
1.1.2.updateWakefulnessLocked()
private boolean updateWakefulnessLocked(int dirty) {
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
| DIRTY_DOCK_STATE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
final long time = SystemClock.uptimeMillis();
if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
}
}
}
return changed;
}
???????當mWakefulness為WAKEFULNESS_AWAKE時,且isItBedTimeYetLocked(),即:副駕滿足進入屏保的條件,看一下該方法的邏輯:
private boolean isItBedTimeYetLocked() {
return mBootCompleted && !isBeingKeptAwakeLocked();
}
private boolean isBeingKeptAwakeLocked() {
return mStayOn
|| mProximityPositive
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0
|| mScreenBrightnessBoostInProgress;
}
???????當滿足以上條件后,執(zhí)行napNoUpdateLocked():
private boolean napNoUpdateLocked(long eventTime, int uid) {
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
try {
Slog.i(TAG, "Nap time (uid " + uid +")...");
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
???????設置mSandmanSummoned為true,更新當前mWakefulness狀態(tài)WAKEFULNESS_DREAMING,最后返回true;
前面的循環(huán)中當結果返回true時,會執(zhí)行下一次循環(huán),重新計算mWakeLockSummary和mUserActivitySummary,最終返回false,執(zhí)行break退出循環(huán),執(zhí)行updateDreamLocked();
1.1.3.updateDreamLocked(xx, xx)
private void updateDreamLocked(int dirty, boolean displayBecameReady) {
if ((dirty & (DIRTY_WAKEFULNESS
| DIRTY_USER_ACTIVITY
| DIRTY_WAKE_LOCKS
| DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS
| DIRTY_IS_POWERED
| DIRTY_STAY_ON
| DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
if (mDisplayReady) {
scheduleSandmanLocked();
}
}
}
???????滿足條件后執(zhí)行scheduleSandmanLocked()來發(fā)送異步消息,執(zhí)行handleSandman(),mDisplayReady是在updateDisplayPowerStateLocked()內部最終通過DisplayPowerController內部返回的;
1.1.4.handleSandman()
private void handleSandman() { // runs on handler thread
// Handle preconditions.
final boolean startDreaming;
final int wakefulness;
synchronized (mLock) {
mSandmanScheduled = false;
wakefulness = mWakefulness;
if (mSandmanSummoned && mDisplayReady) {
startDreaming = canDreamLocked() || canDozeLocked();
mSandmanSummoned = false;
} else {
startDreaming = false;
}
}
final boolean isDreaming;
if (mDreamManager != null) {
// Restart the dream whenever the sandman is summoned.
if (startDreaming) {
mDreamManager.stopDream(false /*immediate*/);
mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
}
isDreaming = mDreamManager.isDreaming();
} else {
isDreaming = false;
}
// Update dream state.
synchronized (mLock) {
// Remember the initial battery level when the dream started.
if (startDreaming && isDreaming) {
mBatteryLevelWhenDreamStarted = mBatteryLevel;
if (wakefulness == WAKEFULNESS_DOZING) {
Slog.i(TAG, "Dozing...");
} else {
Slog.i(TAG, "Dreaming...");
}
}
.....................
// Determine whether the dream should continue.
if (wakefulness == WAKEFULNESS_DREAMING) {
...................
// Dream has ended or will be stopped. Update the power state.
if (isItBedTimeYetLocked()) {
updatePowerStateLocked();
} else {
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",
Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
....................
}
// Stop dream.
if (isDreaming) {
mDreamManager.stopDream(false /*immediate*/);
}
}
???????在handleSandman()先進行判斷,滿足條件后即startDreaming為true時,執(zhí)行stopDream()、startDream(),接下來再執(zhí)行wakeUpNoUpdateLocked(),一起看一下該方法的實現(xiàn):
private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
String opPackageName, int opUid) {
.........................
.........................
try {
switch (mWakefulness) {
case WAKEFULNESS_ASLEEP:
Slog.i(TAG, "Waking up from sleep (uid=" + reasonUid + " reason=" + reason
+ ")...");
break;
case WAKEFULNESS_DREAMING:
Slog.i(TAG, "Waking up from dream (uid=" + reasonUid + " reason=" + reason
+ ")...");
break;
case WAKEFULNESS_DOZING:
Slog.i(TAG, "Waking up from dozing (uid=" + reasonUid + " reason=" + reason
+ ")...");
break;
}
mLastWakeTime = eventTime;
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER,
0, reasonUid, Display.DEFAULT_DISPLAY);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
???????將mWakefulness更新為WAKEFULNESS_AWAKE;然后再執(zhí)行 userActivityNoUpdateLocked()來更新user activity相關信息,接著上面進行分析,執(zhí)行startDream()進入屏保;
1.2.DreamManagerSerivce.java
1.2.1.startDream()
public void startDream(boolean doze) {
startDreamInternal(doze);
}
private void startDreamInternal(boolean doze) {
final int userId = ActivityManager.getCurrentUser();
final ComponentName dream = chooseDreamForUser(doze, userId);
if (dream != null) {
synchronized (mLock) {
startDreamLocked(dream, false /*isTest*/, doze, userId);
}
}
}
private void startDreamLocked(final ComponentName name,
final boolean isTest, final boolean canDoze, final int userId) {
.........................
stopDreamLocked(true /*immediate*/);
Slog.i(TAG, "Entering dreamland.");
final Binder newToken = new Binder();
mCurrentDreamToken = newToken;
mCurrentDreamName = name;
mCurrentDreamIsTest = isTest;
mCurrentDreamCanDoze = canDoze;
mCurrentDreamUserId = userId;
PowerManager.WakeLock wakeLock = mPowerManager
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
mHandler.post(wakeLock.wrap(
() -> mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock)));
}
???????在startDream()邏輯執(zhí)行過程中首先獲取到本地屏保實現(xiàn)的ComponentName,通過在core/res/res/values/config.xml內進行配置:
<string name="config_dreamsDefaultComponent" translatable="false">
com.hly.screensaver/com.hly.screensaver.SevenDreamService
</string>
???????接下來最終通過DreamController的startDream()來啟動;
1.3.DreamController.java
1.3.1.startDream()
public void startDream(Binder token, ComponentName name,
boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
stopDream(true /*immediate*/);
try {
............................
Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
intent.setComponent(name);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
try {
if (!mContext.bindServiceAsUser(intent, mCurrentDream,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
new UserHandle(userId))) {
Slog.e(TAG, "Unable to bind dream service: " + intent);
stopDream(true /*immediate*/);
return;
}
}
........................
}
???????可以看到在startDream()內部通過bindService()來啟動本地實現(xiàn)的屏保服務SevenDreamService;
1.4.SevenDreamService.java
<uses-permission
android:name="android.permission.BIND_DREAM_SERVICE"
tools:ignore="ProtectedPermissions" />
<service
android:name="com.hly.screensaver.SevenDreamService"
android:exported="true"
android:permission="android.permission.BIND_DREAM_SERVICE">
<intent-filter>
<action android:name="android.service.dreams.DreamService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
1.5.總結

2.條件判斷
2.1.updateWakeLockSummaryLocked()
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) {
case PowerManager.PARTIAL_WAKE_LOCK:
if (!wakeLock.mDisabled) {
// We only respect this if the wake lock is not disabled.
mWakeLockSummary |= WAKE_LOCK_CPU;
}
break;
case PowerManager.FULL_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
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:
mWakeLockSummary |= WAKE_LOCK_DOZE;
break;
case PowerManager.DRAW_WAKE_LOCK:
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);
}
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) {
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) {
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;
}
}
}
???????根據(jù)當前持有的mWakeLocks進行處理,計算得到mWakeLockSummary,用來在進入屏保前進行判斷;
private boolean isBeingKeptAwakeLocked() {
return (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| .......);
}
2.2.updateUserActivitySummaryLocked()
private void updateUserActivitySummaryLocked(long now, int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
long screenSaveNextTimeout = 0;
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
..............
final int screenSaveTimeout = getScreenSaveTimeoutLocked();
mUserActivitySummary = 0;
if (mLastUserActivityTime >= mLastWakeTime) {
nextTimeout = mLastUserActivityTime
+ screenOffTimeout - screenDimDuration;
screenSaveNextTimeout = mLastUserActivityTime + screenSaveTimeout;
if (now < nextTimeout) {
if(mScreenSaveEnable && (screenOffTimeout > screenSaveTimeout)
&& (now > ScreenSaveNextTimeout)){
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
} else {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
}
}
}
....................
....................
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
long checkInNextTime = nextTimeout;
if (mScreenSaveEnable && screenOffTimeout > screenSaveTimeout
&& now < screenSaveNextTimeout){
checkInNextTime = screenSaveNextTimeout;
}
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, checkInNextTime);
}
} else {
mUserActivitySummary = 0;
}
}
}
???????根據(jù)用戶最后一次活躍時間得到進入屏保的時間screenSaveNextTimeout,如果當前時間大于screenSaveNextTimeout,則設置mUserActivitySummary為USER_ACTIVITY_SCREEN_DREAM,表示可以進入屏保,否則設置為USER_ACTIVITY_SCREEN_BRIGHT,表示不可以進入屏保;
private boolean isBeingKeptAwakeLocked() {
return (XX
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0
|| XX;
}
???????當滿足進入屏保時,checkInNextTime為最大值,表示不會進行check了;當不滿足進入屏保時,checkInNextTime為screenSaveNextTimeout,表示在該時間時發(fā)送MSG_USER_ACTIVITY_TIMEOUT消息進行check;
3.禁止進入屏保
???????禁止進入屏保就是創(chuàng)造不滿足進入屏保的條件就可以了,主要是來影響mWakeLockSummary和mUserActivitySummary的值;
3.1.申請WakeLock
3.1.1.newWakeLock()
mScreenWakeLock = mPowerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
mScreenWakeLock.acquire();
3.1.2.FLAG_KEEP_SCREEN_ON
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
3.1.3.執(zhí)行流程
???????最終會執(zhí)行到PMS內部的acquireWakeLockInternal()方法:
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag, int uid, int pid, int displayId) {
synchronized (mLock) {
WakeLock wakeLock;
int index = findWakeLockIndexLocked(lock);
boolean notifyAcquire;
.................
wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid,
state, displayId);
try {
lock.linkToDeath(wakeLock, 0);
}
mWakeLocks.add(wakeLock);
setWakeLockDisabledStateLocked(wakeLock);
qcNsrmPowExt.checkPmsBlockedWakelocks(uid, pid, flags, tag, wakeLock);
notifyAcquire = true;
applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
...............
}
}
???????創(chuàng)建WakeLock并加入到mWakeLocks進行管理,更新mDrity值DIRTY_WAKE_LOCKS,接下來執(zhí)行updatePowerStateLocked()來進行新一輪的計算,在方法最后有一個updateSuspendBlockerLocked()方法:
private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
...................
// First acquire suspend blockers if needed.
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
...............
// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
..........................
}
???????可以看到,在該方法內根據(jù)上層申請的WakeLocks計算得到的結果mWakeLockSummary來決定是否通過mWakeLockSuspendBlocker向底層進行acquire();
3.2.更新UserActivity
3.2.1.userActivityWithDisplayId()
3.2.2.userActivityFromNative()
3.2.3.執(zhí)行流程
???????以上兩種方式都會執(zhí)行到userActivityInternal()方法:
private void userActivityInternal(long eventTime, int event, int flags, int uid, int displayId) {
synchronized (mLock) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid, displayId)) {
updatePowerStateLocked();
}
}
}
???????先執(zhí)行userActivityNoUpdateLocked()來執(zhí)行一些更新操作;
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid,
int displayId) {
.....................
try {
....................
if (mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
return false;
}
.................
else {
if(displayId == Display.DEFAULT_DISPLAY) {
if (eventTime > mLastUserActivityTime) {
mLastUserActivityTime = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mDirty |= DIRTY_QUIESCENT;
}
return true;
}
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return false;
}
???????在userActivityNoUpdateLocked()內部主要更新了mLastUserActivityTime,接下來執(zhí)行updatePowerStateLocked()來進行新一輪的計算;
四.設備管理狀態(tài)
1.WAKEFULNESS_AWAKE
???????設備的初始狀態(tài)或設備被喚醒時的狀態(tài),在wakeUpNoUpdateLocked()內調用setWakefulnessLocked()進行設置;
private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
String opPackageName, int opUid) {
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
try {
switch (mWakefulness) {
case WAKEFULNESS_ASLEEP:
Slog.i(TAG, "Waking up from sleep (uid=" + reasonUid + " reason=" + reason
+ ")...");
break;
case WAKEFULNESS_DREAMING:
Slog.i(TAG, "Waking up from dream (uid=" + reasonUid + " reason=" + reason
+ ")...");
break;
case WAKEFULNESS_DOZING:
Slog.i(TAG, "Waking up from dozing (uid=" + reasonUid + " reason=" + reason
+ ")...");
break;
}
mLastWakeTime = eventTime;
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER,
0, reasonUid, Display.DEFAULT_DISPLAY);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
???????當設備被重新喚醒時,會將狀態(tài)設為WAKEFULNESS_AWAKE,并執(zhí)行userActivityNoUpdateLocked()來更新User Actiivty信息;
2. WAKEFULNESS_DREAMING
???????設備在一定時間沒有用戶活動參與和沒有應用持有WakeLock時,會進入DREAMING狀態(tài)啟動屏保來進行關屏;
private boolean napNoUpdateLocked(long eventTime, int uid) {
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
try {
Slog.i(TAG, "Nap time (uid " + uid +")...");
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
???????前面分析到,當定期執(zhí)行updateUserActivitySummaryLocked()去檢測發(fā)現(xiàn)在指定的時間段內沒有用戶活動參與時,會將mUserActivitySummary設為 USER_ACTIVITY_SCREEN_DREAM,接下來將狀態(tài)設置為WAKEFULNESS_DREAMING然后進入屏保;
3.WAKEFULNESS_DOZING
???????WAKEFULNESS_ASLEEP之前的一個過渡狀態(tài),在執(zhí)行goToSleep()如果沒有將flag設置為
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE就會進入該狀態(tài);
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
switch (reason) {
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy "
+ "(uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_HDMI:
Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
break;
default:
Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
break;
}
mLastSleepTime = eventTime;
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
// 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;
Slog.d(TAG, " Wl info: pkg:"+ wakeLock.mPackageName);
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, 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;
}
4.WAKEFULNESS_ASLEEP
???????當power鍵滅屏時,會在PhoneWindowManager中處理按鍵事件后,調用到PMS的gotoSleep()進行滅屏處理,車機上會通過CarService來執(zhí)行goToSleep(),如果flag設置了PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE,則會直接進入ASLEEP狀態(tài);
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
..................
..................
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
reallyGoToSleepNoUpdateLocked(eventTime, uid);
}
return true;
}
private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");
try {
Slog.i(TAG, "Sleeping (uid " + uid +")...");
setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
???????如果Flag沒有設置PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE,則會在updateDreamLocked()中更新屏保狀態(tài)時,如果此時處于Doze狀態(tài)且沒有進行屏保,則會進入ASLEEP狀態(tài);
if (wakefulness == WAKEFULNESS_DREAMING) {
....................
....................
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",
Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);
updatePowerStateLocked();
} else if (wakefulness == WAKEFULNESS_DOZING) {
if (isDreaming) {
return; // continue dozing
}
// Doze has ended or will be stopped. Update the power state.
reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
updatePowerStateLocked();
}
5.狀態(tài)轉換圖
???????未完待續(xù).....