文章目录

  • 1. 前言
  • 2. wakeup
    • 2.1 wakeUpNoUpdateLocked
    • 2.2 updatePowerStateLocked
      • 2.2.1 Phase 0
      • 2.2.2 Phase 1
      • 2.2.3 Phase 2
      • 2.2.4 Phase 3
      • 2.2.5 Phase 4
  • 3. gotoSleep
  • 4. userActivity
  • 5. Wakelock
  • 6. 运用场景

1. 前言

写这篇文章是对PowerManagerServcie的一个大体认知,方便我接下来系统定制化操作~

PowerManagerServcie是android系统电源管理的核心服务,它在Framework层建立起一个策略控制方案。向上提供给应用程序相应的操作接口,比如听音乐时持续保持系统唤醒,应用通知来临唤醒手机屏幕等场景,向下决策HAL层以及kernel层来控制设备待机,控制显示屏,背光灯,距离传感器,光线传感器等硬件设备的状态。

下文为了叙述方便,我将PowerManagerServcie简称为POMS,并且会围绕POMS里提供的函数的功能来进行说明,如下:
a、wakeup()
b、gotoSleep()
c、userActivity()
d、Wakelock()

2. wakeup

强制系统从睡眠状态唤醒,此接口对应用是不开放的,应用想唤醒系统必须通过设置亮屏标志;
我们可以就认真看一下这个函数,后面几个小节的函数都是类似的编程思路,不再详述了。
framworks/base/core/java/android/os/PowerManager.java

/*** Forces the device to wake up from sleep.* <p>* If the device is currently asleep, wakes it up, otherwise does nothing.* This is what happens when the power key is pressed to turn on the screen.* </p><p>* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.* </p>** @param time The time when the request to wake up was issued, in the* {@link SystemClock#uptimeMillis()} time base.  This timestamp is used to correctly* order the wake up request with other power management functions.  It should be set* to the timestamp of the input event that caused the request to wake up.** @see #userActivity* @see #goToSleep*/public void wakeUp(long time) {try {mService.wakeUp(time);  //1} catch (RemoteException e) {}}

我们先翻译一哈官方注释:

“强制将设备从睡眠中唤醒,如果设备当前处于睡眠状态,则唤醒它,否则什么也不做,这是
按下电源键打开屏幕时的情况。并且需要有设置{android.Manifest.permission.DEVICE_POWER}权限,
参数是用来指定唤醒设备的时机。”

根据注释对Wakeup这个函数已经有了大致的认知了。再看注释1处的代码,可以看到这里是调用了远程服务端的wakeUp函数,跟踪代码可知这个函数实现为:

framworks/base/services/java/com/android/server/power/PowerManagerService.java

    @Override // Binder callpublic void wakeUp(long eventTime) {if (eventTime > SystemClock.uptimeMillis()) {   //2throw new IllegalArgumentException("event time must not be in the future");}mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);  //3final long ident = Binder.clearCallingIdentity();try {wakeUpInternal(eventTime); //4} finally {Binder.restoreCallingIdentity(ident);   //5}}

先来看注释2处的代码,可以看到这个参数你不能设置为大于系统的当前时间的数,不然就会抛非法参数异常,想想也是,总不能让你等个几十年才唤醒屏幕吧,哈哈哈哈。

然后再来看注释3处的代码,可以看到它通过调用了enforceCallingOrSelfPermission函数检查是否有注册DEVICE_POWER这个权限,这个函数的实现如下:
framworks/base/core/java/android/app/ContextImpl.java

    public void enforceCallingOrSelfPermission(String permission, String message) {enforce(permission,checkCallingOrSelfPermission(permission),  //6true,Binder.getCallingUid(),message);}

上面代码直接看enforce这个核心函数就行了,实现如下:

    private void enforce(String permission, int resultOfCheck,boolean selfToo, int uid, String message) {if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {throw new SecurityException((message != null ? (message + ": ") : "") +(selfToo? "Neither user " + uid + " nor current process has ": "uid " + uid + " does not have ") +permission +".");}}

我们可以发现这里是是通过检查有没有授予权限,如果没有的话程序会直接抛SecurityException异常退出,检查权限函数是在注释6的代码处:

    public int checkCallingOrSelfPermission(String permission) {if (permission == null) {throw new IllegalArgumentException("permission is null");}return checkPermission(permission, Binder.getCallingPid(),Binder.getCallingUid());  //7}

注释7代码往下:

    public int checkPermission(String permission, int pid, int uid) {if (permission == null) {throw new IllegalArgumentException("permission is null");}try {return ActivityManagerNative.getDefault().checkPermission(permission, pid, uid);  //8} catch (RemoteException e) {return PackageManager.PERMISSION_DENIED;}}

上面代码先看注释8的getDefault函数:

    static public IActivityManager getDefault() {return gDefault.get();}

继续往下这个gDefault 是怎么来的:

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {protected IActivityManager create() {IBinder b = ServiceManager.getService("activity");if (false) {Log.v("ActivityManager", "default service binder = " + b);}IActivityManager am = asInterface(b);if (false) {Log.v("ActivityManager", "default service = " + am);}return am;}};

然后发现实际上就是连接activity服务,即连接ActivityManagerService,再回到注释8处,调用的checkPermission函数的实现实际如下:

framworks/base/services/java/com/android/server/am/ActivityManagerService.java

    public int checkPermission(String permission, int pid, int uid) {if (permission == null) {return PackageManager.PERMISSION_DENIED;}return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);  //9}

直接跟着注释9函数往下看:

    int checkComponentPermission(String permission, int pid, int uid,int owningUid, boolean exported) {Identity tlsIdentity = sCallerIdentity.get();if (tlsIdentity != null) {Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"+ tlsIdentity.pid + "," + tlsIdentity.uid + "}");uid = tlsIdentity.uid;pid = tlsIdentity.pid;}if (pid == MY_PID) {return PackageManager.PERMISSION_GRANTED;}return ActivityManager.checkComponentPermission(permission, uid,owningUid, exported);  //10}

继续跟着注释10函数往下看:
framworks/base/core/java/android/app/ActivityManager.java

    /** @hide */public static int checkComponentPermission(String permission, int uid,int owningUid, boolean exported) {// Root, system server get to do everything.if (uid == 0 || uid == Process.SYSTEM_UID) {return PackageManager.PERMISSION_GRANTED;}// Isolated processes don't get any permissions.if (UserHandle.isIsolated(uid)) {return PackageManager.PERMISSION_DENIED;}// If there is a uid that owns whatever is being accessed, it has// blanket access to it regardless of the permissions it requires.if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {return PackageManager.PERMISSION_GRANTED;}// If the target is not exported, then nobody else can get to it.if (!exported) {/*RuntimeException here = new RuntimeException("here");here.fillInStackTrace();Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,here);*/return PackageManager.PERMISSION_DENIED;}if (permission == null) {return PackageManager.PERMISSION_GRANTED;}try {return AppGlobals.getPackageManager().checkUidPermission(permission, uid);   //11} catch (RemoteException e) {// Should never happen, but if it does... deny!Slog.e(TAG, "PackageManager is dead?!?", e);}return PackageManager.PERMISSION_DENIED;}

下面的几个函数跳转跟上面类似:

    public static IPackageManager getPackageManager() {return ActivityThread.getPackageManager();}
 public static IPackageManager getPackageManager() {if (sPackageManager != null) {//Slog.v("PackageManager", "returning cur default = " + sPackageManager);return sPackageManager;}IBinder b = ServiceManager.getService("package");//Slog.v("PackageManager", "default service binder = " + b);sPackageManager = IPackageManager.Stub.asInterface(b);//Slog.v("PackageManager", "default service = " + sPackageManager);return sPackageManager;}

所以最后走到了PackageManagerService的checkUidPermission函数:

frameworks/base/services/java/com/android/server/pm/PackageManagerService.java

public int checkUidPermission(String permName, int uid) {synchronized (mPackages) {Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));if (obj != null) {GrantedPermissions gp = (GrantedPermissions)obj;if (gp.grantedPermissions.contains(permName)) {return PackageManager.PERMISSION_GRANTED;}} else {HashSet<String> perms = mSystemPermissions.get(uid);if (perms != null && perms.contains(permName)) {return PackageManager.PERMISSION_GRANTED;}}}return PackageManager.PERMISSION_DENIED;}

可以发现最后实际上是通过PackageManagerService检查最开始上面下发的权限是否被注册的。

好的,然后我们再回过头来看注释4处的代码:

 wakeUpInternal(eventTime);

这个函数的实现如下:

framworks/base/services/java/com/android/server/power/PowerManagerService.java

    private void wakeUpInternal(long eventTime) {synchronized (mLock) {if (wakeUpNoUpdateLocked(eventTime)) {    //12updatePowerStateLocked(); //13}}}

上面的函数很简单,就两个函数,通过wakeUpNoUpdateLocked来做唤醒系统的相关通知工作,即完成亮屏前的图形绘制工作及亮屏动作,并通过updatePowerStateLocked来更新电源状态。

下来将分别对这两个函数进行详细分析,特别是updatePowerStateLocked函数。

2.1 wakeUpNoUpdateLocked

先介绍第一函数wakeUpNoUpdateLocked:

 private boolean wakeUpNoUpdateLocked(long eventTime) {if (DEBUG_SPEW) {Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime);}if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE|| !mBootCompleted || !mSystemReady) {return false;}HiSysManager hisys = new HiSysManager();hisys.adjustDevState("/proc/inputblock/status","0");switch (mWakefulness) {case WAKEFULNESS_ASLEEP:Slog.i(TAG, "Waking up from sleep...");sendPendingNotificationsLocked();mNotifier.onWakeUpStarted();   //14mSendWakeUpFinishedNotificationWhenReady = true;break;case WAKEFULNESS_DREAMING:Slog.i(TAG, "Waking up from dream...");break;case WAKEFULNESS_NAPPING:Slog.i(TAG, "Waking up from nap...");break;}mLastWakeTime = eventTime;mWakefulness = WAKEFULNESS_AWAKE;mDirty |= DIRTY_WAKEFULNESS;userActivityNoUpdateLocked(eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);return true;}

上面代码看起来比较多,实际上你只需要关注的是注释14处代码所调用的函数:
framworks/base/services/java/com/android/server/power/Notifier.java

public void onWakeUpStarted() {if (DEBUG) {Slog.d(TAG, "onWakeUpStarted");}synchronized (mLock) {if (mActualPowerState != POWER_STATE_AWAKE) {mActualPowerState = POWER_STATE_AWAKE;mPendingWakeUpBroadcast = true;if (!mScreenOnBlockerAcquired) {mScreenOnBlockerAcquired = true;mScreenOnBlocker.acquire();}updatePendingBroadcastLocked();  //15}}}

再然后就看注释15处的代码就好:

  private void updatePendingBroadcastLocked() {if (!mBroadcastInProgress&& mActualPowerState != POWER_STATE_UNKNOWN&& (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast|| mActualPowerState != mBroadcastedPowerState)) {mBroadcastInProgress = true;mSuspendBlocker.acquire();Message msg = mHandler.obtainMessage(MSG_BROADCAST);msg.setAsynchronous(true);mHandler.sendMessage(msg);}}

可以看到这是发了一条消息,消息接收方如下:

 private final class NotifierHandler extends Handler {public NotifierHandler(Looper looper) {super(looper, null, true /*async*/);}@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_USER_ACTIVITY:sendUserActivity();break;case MSG_BROADCAST:sendNextBroadcast();  //16break;case MSG_WIRELESS_CHARGING_STARTED:playWirelessChargingStartedSound();break;case MSG_SMART_SUSPEND_START:sendSuspendStart();break;case MSG_TIMEOUT_REBOOT:sendTimeoutRebootBroadcast();break;}}}

然后根据消息类别,可以知道调用的注释16处的sendNextBroadcast函数:

private void sendNextBroadcast() {final int powerState;final int goToSleepReason;synchronized (mLock) {if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) {// Broadcasted power state is unknown.  Send wake up.mPendingWakeUpBroadcast = false;mBroadcastedPowerState = POWER_STATE_AWAKE;} else if (mBroadcastedPowerState == POWER_STATE_AWAKE) {// Broadcasted power state is awake.  Send asleep if needed.if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast|| mActualPowerState == POWER_STATE_ASLEEP) {mPendingGoToSleepBroadcast = false;mBroadcastedPowerState = POWER_STATE_ASLEEP;} else {finishPendingBroadcastLocked();return;}} else {// Broadcasted power state is asleep.  Send awake if needed.if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast|| mActualPowerState == POWER_STATE_AWAKE) {mPendingWakeUpBroadcast = false;mBroadcastedPowerState = POWER_STATE_AWAKE;} else {finishPendingBroadcastLocked();return;}}mBroadcastStartTime = SystemClock.uptimeMillis();powerState = mBroadcastedPowerState;goToSleepReason = mLastGoToSleepReason;}EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);if (powerState == POWER_STATE_AWAKE) {sendWakeUpBroadcast();   //17} else {sendGoToSleepBroadcast(goToSleepReason);}}

其他先不管,上面代码直接看注释17处的代码,

 private void sendWakeUpBroadcast() {if (DEBUG) {Slog.d(TAG, "Sending wake up broadcast.");}EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);mPolicy.screenTurningOn(mScreenOnListener);  //18try {ActivityManagerNative.getDefault().wakingUp();} catch (RemoteException e) {// ignore it}if (ActivityManagerNative.isSystemReady()) {mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,mWakeUpBroadcastDone, mHandler, 0, null, null);} else {EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);sendNextBroadcast();}}

由代码可知:

private final WindowManagerPolicy mPolicy;

mPolicy实际是WindowManagerPolicy 对象,PhoneWindowManager实现了WindowManagerPolicy 类,则相当于调用的是下面代码:

framworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

  @Overridepublic void screenTurningOn(final ScreenOnListener screenOnListener) {EventLog.writeEvent(70000, 1);if (false) {RuntimeException here = new RuntimeException("here");here.fillInStackTrace();Slog.i(TAG, "Screen turning on...", here);}synchronized (mLock) {mScreenOnEarly = true;updateOrientationListenerLp();updateLockScreenTimeout();}waitForKeyguard(screenOnListener);}

也就是在这里进行开屏的相关操作。

2.2 updatePowerStateLocked

再然后我们再来看这个updatePowerStateLocked函数,这个函数是电源管理核心函数,我们调用了PowerManager之后,都会调用这个函数进行电源相关的更新操作。

framworks/base/core/java/android/os/PowerManager.java

  /*** Updates the global power state based on dirty bits recorded in mDirty.** This is the main function that performs power state transitions.* We centralize them here so that we can recompute the power state completely* each time something important changes, and ensure that we do it the same* way each time.  The point is to gather all of the transition logic here.*/private void updatePowerStateLocked() {if (!mSystemReady || mDirty == 0) {return;}// Phase 0: Basic state updates.updateIsPoweredLocked(mDirty);updateStayOnLocked(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);updateUserActivitySummaryLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Update dreams and display power state.updateDreamLocked(dirtyPhase2);updateDisplayPowerStateLocked(dirtyPhase2);// Phase 3: Send notifications, if needed.if (mDisplayReady) {sendPendingNotificationsLocked();}// Phase 4: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();}

电源状态更新,最重要的标志变量为mDirty,当与电源相关的状态改变,都会通过置位的方法反映在mDirty集合变量了,比如充电状态,屏幕亮度,电源设置,唤醒状态等发生改变都会在mDirty中反映出来

2.2.1 Phase 0

1).updateIsPoweredLocked():该方法主要是通过调用BatteryService更新电池状态,包括电池充电,电量等级等状态。

 mIsPowered = mBatteryService.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);mPlugType = mBatteryService.getPlugType();mBatteryLevel = mBatteryService.getBatteryLevel();

mIsPowered表示是否在充电,mPlugType 表示充电类型,mBatteryLevel 表示当前电量等级

2).updateStayOnLocked()来更新变量mStayOn的值,如果mStayOn如果为true,则屏幕长亮,在Setting中可以设置充电时候屏幕长亮,如果Setting中设置了该选项,updateIsPoweredLocked检查到正在充电,会将mStayOn置为true。

/*** Updates the value of mStayOn.* Sets DIRTY_STAY_ON if a change occurred.*/private void updateStayOnLocked(int dirty) {if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {final boolean wasStayOn = mStayOn;if (mStayOnWhilePluggedInSetting != 0&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting);} else {mStayOn = false;}if (mStayOn != wasStayOn) {mDirty |= DIRTY_STAY_ON;}}}

2.2.2 Phase 1

1).下来是一个无限循环,循环中最先调用updateWakeLockSummaryLocked,来将系统中所有的wakelock锁更新到一个集合变量mWakeLockSummary中,也就是不管系统中创建了多少个wakelock,一个便足以阻止系统进入睡眠状态,因此这里将所有的wakelock总结后通过置位的方法保存到一个变量中,应用创建wakelock时会指定wakelock的类型,不同的wakelock类型置于不同的位。

2)循环调用的第二个方法是updateUserActivitySummaryLocked,在方法中根据系统最后一次调用userActivity()方法的时间计算现在是否可以将屏幕状态的变量mUserActivitySummary置成USER_ACTIVITY_SCREEN_BRIGHT(亮屏)还是USER_ACTIVITY_SCREEN_DIM(暗屏)等,这在上面已经分析过了,这里就不多赘述了。

3).循环中调用的第三个方法是updateWakefulnessLocked(),这个方法是循环结束的关键,如果它的返回值为true,则表示wakefulness的状态发生改变了,降继续循环重新调用前面两个方法更新userActivity和Wakelock集合变量。如果能第二次调用updateWakefulnessLocked()一定会返回false,继而跳出循环,方法实现为

/*** Updates the wakefulness of the device.** This is the function that decides whether the device should start napping* based on the current wake locks and user activity state.  It may modify mDirty* if the wakefulness changes.** Returns true if the wakefulness changed and we need to restart power state calculation.*/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);} else {changed = goToSleepNoUpdateLocked(time,PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);}}}return changed;}

第一个if非常用以满足,第二个条件要求mWakefulness为WAKEFULNESS_AWAKE,且isItBedTimeYetLocked()为true,此函数官方解释为当系统马上要进入睡眠状态时会返回true,也就是当系统一直处于活跃状态,则其返回false所以,updateWakefulnessLocked()方法返回值为false,那么这个死循环只用执行一次就跳出了,这里假定系统一段时间未被操作,即将接下来就要调用进入睡眠状态,则isItBedTimeYetLocked()函数返回true,接下来就该调用shouldNapAtBedTimeLocked()方法了,该方法检查又没有设置睡眠之前启动动态屏保或者插在座充上启动屏保,如果设置了,调用napNoUpdateLocked(),没有设置则调用gotoSleepNoUpdateLocked()。

napNoUpdateLocked方法代码如下:

private boolean napNoUpdateLocked(long eventTime) {if (DEBUG_SPEW) {Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime);}if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE|| !mBootCompleted || !mSystemReady) {return false;}Slog.i(TAG, "Nap time...");mDirty |= DIRTY_WAKEFULNESS;mWakefulness = WAKEFULNESS_NAPPING;return true;}

如果if语句中有一项成立则返回false,则跳出死循环,当时如果第一次调用该方法,正常情况下当为false,如果第二次调用到此肯定会返回false,因为第二次调用时mWakefulness 为,WAKEFULNESS_DREAMING。而gotoSleepNoUpdateLocked前面已作分析,这里就不多讲了。

4).跳出循环则调用到updateDisplayPowerStateLocked()更新屏幕显示,当前面如果申请了亮屏锁和更新userActivity时,mUserActivitySummary带有USER_ACTIVITY_SCREEN_BRIGHT标志,则会将mDisplayPowerRequest.policy置为POLICY_BRIGHT,这个标志在DisplayPowerController中会将屏幕从灭屏状态下唤醒。

2.2.3 Phase 2

1).接下来调用updateDreamLocked(),更新屏保模式,具体处理在scheduleSandmanLocked()函数中,该函数是当系统进入/退出屏保状态或者Dozing下状态调用:

/*** Determines whether to post a message to the sandman to update the dream state.*/private void updateDreamLocked(int dirty) {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) {scheduleSandmanLocked();}}

2)updateDisplayPowerStateLocked更新电源显示状态

/*** Updates the display power state asynchronously.* When the update is finished, mDisplayReady will be set to true.  The display* controller posts a message to tell us when the actual display power state* has been updated so we come back here to double-check and finish up.** This function recalculates the display power state each time.*/private void updateDisplayPowerStateLocked(int dirty) {if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {int newScreenState = getDesiredScreenPowerStateLocked();if (newScreenState != mDisplayPowerRequest.screenState) {if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF&& mDisplayPowerRequest.screenState!= DisplayPowerRequest.SCREEN_STATE_OFF) {mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime();}mDisplayPowerRequest.screenState = newScreenState;nativeSetPowerState(newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);}int screenBrightness = mScreenBrightnessSettingDefault;float screenAutoBrightnessAdjustment = 0.0f;boolean autoBrightness = (mScreenBrightnessModeSetting ==Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {screenBrightness = mScreenBrightnessOverrideFromWindowManager;autoBrightness = false;} else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {screenBrightness = mTemporaryScreenBrightnessSettingOverride;} else if (isValidBrightness(mScreenBrightnessSetting)) {screenBrightness = mScreenBrightnessSetting;}if (autoBrightness) {screenBrightness = mScreenBrightnessSettingDefault;if (isValidAutoBrightnessAdjustment(mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {screenAutoBrightnessAdjustment =mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;} else if (isValidAutoBrightnessAdjustment(mScreenAutoBrightnessAdjustmentSetting)) {screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;}}screenBrightness = Math.max(Math.min(screenBrightness,mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);screenAutoBrightnessAdjustment = Math.max(Math.min(screenAutoBrightnessAdjustment, 1.0f), -1.0f);mDisplayPowerRequest.screenBrightness = screenBrightness;mDisplayPowerRequest.screenAutoBrightnessAdjustment =screenAutoBrightnessAdjustment;mDisplayPowerRequest.useAutoBrightness = autoBrightness;mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,mRequestWaitForNegativeProximity);mRequestWaitForNegativeProximity = false;if (DEBUG_SPEW) {Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady+ ", newScreenState=" + newScreenState+ ", mWakefulness=" + mWakefulness+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)+ ", mBootCompleted=" + mBootCompleted);}}}

2.2.4 Phase 3

sendPendingNotificationsLocked未做实际操作

2.2.5 Phase 4

最后一个函数updateSuspendBlockerLocked();由于系统中可能需要释放最后一个维持CPU唤醒或者维持屏幕亮灭的Blocker,所以必须将所有事物处理完成,再执行该操作。由于该函数是由PowerManagerService调用到底层的唯一入口,所以十分重要:

/*** Updates the suspend blocker that keeps the CPU alive.** This function must have no other side-effects.*/private void updateSuspendBlockerLocked() {final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();// 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;}}

needWakeLockSuspendBlocker变量判断wakelock是否带有WAKE_LOCK_CPU标志来决定是否为需要保持CPU唤醒,其中能维持CPU唤醒的wakelock类型有:PARTIAL_WAKE_LOCK,FULL_WAKE_LOCK,SCREEN_BRIGHT_WAKE_LOCK,SCREEN_DIM_WAKE_LOCK,DRAW_WAKE_LOCK。needDisplaySuspendBlocker 则是表示是否维持屏幕亮灭的变量,true表示维持屏幕亮,false表示可以关闭屏幕。

上面两段代码是向下申请PowerManagerService.WakeLocks和PowerManagerService.Display类型的wakelock锁的入口,mHoldingWakeLockSuspendBlocker表示当前是否持有cpu唤醒锁,如果持有则不必向下继续申请锁,如果维持有,且需要维持CPU唤醒则需要,申请CPU唤醒锁。(Display逻辑与其相似,就不做分析)调用到 SuspendBlockerImpl的acquire()函数中

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);}}
}

前面已经说过SuspendBlockerImpl维持了一个计数标志mReferenceCount 当为1的时候申请锁,为0时释放锁。nativeAcquireSuspendBlocker()函数通过JNI调用到native层的com_android_server_power_PowerManagerService.cpp文件的nativeAcquireSuspendBlocker函数,这里就不往下跟踪了。

3. gotoSleep

强制系统进入到睡眠状态,此接口也是应用不开放,此接口通常与wakeUp函数对应,是按关机键的时候会被调用到的两个函数。

4. userActivity

向PowerManagerService报告影响系统休眠的用户活动,重计算灭屏时间,背光亮度等,例如触屏,划屏,power键等用户活动

5. Wakelock

wakelock是PowerManager的一个内部类,提供了相关的接口来操作wakelock锁,比如newWakeLock()方法来创建wakelock锁,acquire()和release()方法来申请和释放锁,应用层经常使用控制设备休眠的函数。

6. 运用场景

学习完POMS之后,可以自定义关机键,控制屏幕状态,以及计算用户活动时间等。

浅谈framework之PowerManagerService相关推荐

  1. 浅谈Linux media framework

    基本概念 通过调试camera过程中对接触的v4l2,意外发现了Linux一个不是很起眼的子系统--Linux media framework,那它存在的意义是什么? 节选一段来自Linux源码中的文 ...

  2. 浅谈Python Web的五大框架

    说到web framework,Ruby的世界Rails一统江湖,而Python则是一个百花齐放的世界,各种micro-framework.framework不可胜数,不完全列表见:http://wi ...

  3. 【转】浅谈.net remoting 与webservice

    1. .NET Remoting .NET Remoting是微软随.NET推出的一种分布式应用解决方案,被誉为管理应用程序域之间的 RPC 的首选技,它允许不同应用程序域之间进行通信(这里的通信可以 ...

  4. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service Manager成为Android进程间 ...

  5. 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6621566 上一篇文章Android进程间通信(IPC)机制Binder简要介绍和学 ...

  6. 浅谈嵌套命名实体识别(Nested NER)

    ©PaperWeekly 原创 · 作者|张成蹊 单位|北京大学硕士生 研究方向|自然语言处理 序 命名实体识别(Named Entity Recognition, 下称 NER)任务,主要目的是从一 ...

  7. 浅谈Spring5 响应式编程

    目录 为什么是响应式编程 用于响应式编程实现的理想案例 响应流 (Reactive Streams) Spring 5 提供的响应式编程 Spring Web Reactive vs. Spring ...

  8. 压缩感知高斯测量矩阵matlab,浅谈压缩感知(十七):测量矩阵之有限等距常数RIC的计算...

    有限等距常数(RestrictedIsometry Constant, RIC)是与有限等距性质(Restricted IsometryProperty, RIP)紧密结合在一起的一个参数. 一.RI ...

  9. 浅谈五大Python Web框架

    http://www.csdn.net/article/2011-02-17/292058 导读:作者飞龙写了一篇<浅谈Python Web框架>,文中他介绍了几个Python Web框架 ...

最新文章

  1. 【总结】清除webbrowser cookie/session的6种方法
  2. linux 手动释放buff/cache
  3. animated bar chart race下载_下载腾讯会议
  4. C语言中被常用到的宏
  5. 【HeadFirst 设计模式学习笔记】13 MVC分析
  6. python可以用del释放资源_Python中垃圾回收和del语句详解
  7. VK1S68C中文资料
  8. 使用winx dvd ripper转换视频,如何获得高质量的视频?
  9. pands库中的一些函数用法
  10. python导入鸢尾花数据集_2020-11-01 鸢尾花数据集Python处理
  11. 网络游戏防沉迷的理想与现实
  12. 华为S2000系列交换机电源维修
  13. [从零开始学习FPGA编程-34]:进阶篇 - 基本时序电路-计数器(Verilog语言)
  14. 视频转gif软件哪个好
  15. 2017php最新版本,2017php受权验证系统2.6.8受权系统,真正完整可用,全新界面受权源码...
  16. 2022年毕业生求职找工作青睐哪个行业?
  17. c语言字节溢出,C语言变量定义与数据溢出(初学者)
  18. linux手机内存碎片整理软件,Linux不需要磁盘碎片整理
  19. Interproscan linux版本详细安装教程及运行报错解决方案
  20. windows 安装Abin

热门文章

  1. 《西游记》取经路线图|思维导图简单又漂亮
  2. 我们公司使用了 5 年的系统限流方案 ,从实现到部署实战详解,稳的一B
  3. 微信小程序左滑删除(Slideview)
  4. 【AWS+Drupal应用案例】如何让一个千万级流量网站从一直挂机到起死回生?
  5. 抖音直播流量怎么来?四大渠道告诉你
  6. 《十周成为数据分析师》笔记——业务线 第八节 常见互联网业务的数据分析报告的制作及用户分层模型
  7. 2D制作动画软件:Cartoon Animato 支持win/mac 中文激活版
  8. 7.20-7.22作业代码
  9. 航班信息检索与查询(基数排序)
  10. 谁抢走你的棒棒糖?精彩的创意让你得到的不仅仅是震撼 值得一看(图)