浅谈framework之PowerManagerService

1. 前言

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

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

下文为了叙述方便,我将PowerManagerServcie简称为POMS,并且会围绕POMS里提供的函数的功能来进行说明,如下:
下面介绍PowerManager中提供的相应接口:
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 call
    public void wakeUp(long eventTime) {
        if (eventTime > SystemClock.uptimeMillis()) {   //2
            throw new IllegalArgumentException("event time must not be in the future");
        }

        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);  //3

        final 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),  //6
                true,
                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)) {    //12
                updatePowerStateLocked(); //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();   //14
                mSendWakeUpFinishedNotificationWhenReady = 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*/);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_USER_ACTIVITY:
                    sendUserActivity();
                    break;

                case MSG_BROADCAST:
                    sendNextBroadcast();  //16
                    break;

                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);  //18

        try {
            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

  @Override
    public 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之后,可以自定义关机键,控制屏幕状态,以及计算用户活动时间等。

发布了70 篇原创文章 · 获赞 24 · 访问量 8245

猜你喜欢

转载自blog.csdn.net/angelsmiling/article/details/103298689