Android 4.0 中的PowerManager(电源管理--休眠唤醒)

来源:互联网 发布:java达内和黑马哪个好 编辑:程序博客网 时间:2024/05/29 16:27

http://blog.csdn.net/codectq/article/details/7324879

转发请注明出处:

http://blog.csdn.net/codectq/article/details/7324879

        最近,在学习让系统进入休眠的过程中,学习了电源管理的相关知识。为了备忘和理清思路现整理成文,以便日后查阅。

        移动设备由于自身的限制有一个硬伤就是电量的消耗问题。由于电池的电量有限,所以电源电量的管理显得就比较重要了。我们可以想象一下,当你去超市买完东西之后,却发现无法运回家,是多么难受的一件事情。

        Android的电源管理是在Linux电源管理的基础之上更好的一个电源管理方案,在这种策略下,通过Android framework层和本地的linux库,服务和应用都通过“wake lock”来取得CPU,从而达到省电的目的。如果没有活跃的唤醒锁,Android将关闭CPU。

         在Android 4.0 中,为上层提供的休眠函数为goToSleep()。下面详细讲解为什么这个命令会让系统进去休眠模式。

        首先,需要明白在Android 系统中一般会有这样的一个文件群,XXX.javaXXXservice.java*XXX*.cpp*XXX*.c。作为使用者我们首先需要了解的就是这个系统能够为我们提供的服务,如果这些服务会让我们满意,我们才会愿意为这个服务埋单。因此,在这里我们就先从服务入手,也就是从PowerManagerService.java开始入手。在这个文件的line2561出有goToSleep()函数的定义:

 public void goToSleep(long time)

    {

        goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);

    }

        goToSleep()函数接着调用了下面的goToSleepWithReason()函数。函数的定义如下:

public void goToSleepWithReason(long time, int reason)

    {

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

        synchronized (mLocks) {

            goToSleepLocked(time, reason);

        }

    }

      goToSleepLocked()函数的定义如下:

private void goToSleepLocked(long time, int reason) {



        if (mLastEventTime <= time) {

            mLastEventTime = time;

            // cancel all of the wake locks

            mWakeLockState = SCREEN_OFF;

            int N = mLocks.size();

            int numCleared = 0;

            boolean proxLock = false;

            for (int i=0; i<N; i++) {

                WakeLock wl = mLocks.get(i);

                if (isScreenLock(wl.flags)) {

                    if (((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)

                            && reason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {

                        proxLock = true;

                    } else {

                        mLocks.get(i).activated = false;

                        numCleared++;

                    }

                }

            }

            if (!proxLock) {

                mProxIgnoredBecauseScreenTurnedOff = true;

                if (mDebugProximitySensor) {

                    Slog.d(TAG, "setting mProxIgnoredBecauseScreenTurnedOff");

                }

            }

            EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);

            mStillNeedSleepNotification = true;

            mUserState = SCREEN_OFF;

            setPowerState(SCREEN_OFF, false, reason);

            cancelTimerLocked();

        }

    }

        其中,对我们来讲最有意义的函数为setPowerState()函数。此函数中调用了 setScreenStateLocked()函数


private int setScreenStateLocked(boolean on) {

        if (DEBUG_SCREEN_ON) {

            RuntimeException e = new RuntimeException("here");

            e.fillInStackTrace();

            Slog.i(TAG, "Set screen state: " + on, e);

        }

        if (on) {

            if ((mPowerState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {

                // If we are turning the screen state on, but the screen

                // light is currently off, then make sure that we set the

                // light at this point to 0.  This is the case where we are
                // turning on the screen and waiting for the UI to be drawn
                // before showing it to the user.  We want the light off
                // until it is ready to be shown to the user, not it using
                // whatever the last value it had.
                if (DEBUG_SCREEN_ON) {
                    Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
                            + Integer.toHexString(mPowerState)
                            + " mSkippedScreenOn=" + mSkippedScreenOn);
                }
                mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF);
            }
        }
        int err = Power.setScreenState(on);
        if (err == 0) {
            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
            if (mUseSoftwareAutoBrightness) {
                enableLightSensorLocked(on);

                if (!on) {
                    // make sure button and key backlights are off too
                    mButtonLight.turnOff();
                    mKeyboardLight.turnOff();
                    // clear current value so we will update based on the new conditions
                    // when the sensor is reenabled.
                    mLightSensorValue = -1;
                    // reset our highest light sensor value when the screen turns off
                    mHighestLightSensorValue = -1;
                }
            }
        }
        return err;
    }

       此函数调用了Power类中的setScreenState()函数。此函数通过JNI机制,最终到达硬件层的libhardware_legacy/power/Power.c文件通过对寄存器的操作完成对休眠的操作。在此函数中我们通过传入的参数是on,来进行相应的处理。